diff options
Diffstat (limited to 'libpthread')
694 files changed, 70921 insertions, 0 deletions
diff --git a/libpthread/nptl/.gitignore b/libpthread/nptl/.gitignore new file mode 100644 index 000000000..c7ded8eb2 --- /dev/null +++ b/libpthread/nptl/.gitignore @@ -0,0 +1,21 @@ +# +# Never ignore these +# +!.gitignore + +# +# Generated files +# +gen_l* +pthread-errnos.[hcs] +tcb-offsets.[hcs] +lowlevelbarrier.h +lowlevelcond.h +lowlevelrwlock.h +lowlevelrobustlock.h +unwindbuf.h +structsem.h +pthread-pi-defines.h +sysdeps/pthread/pt-sigaction.c +sysdeps/pthread/pt-sigfillset.c +sysdeps/pthread/pt-sigprocmask.c diff --git a/libpthread/nptl/ChangeLog b/libpthread/nptl/ChangeLog new file mode 100644 index 000000000..c81eb03b7 --- /dev/null +++ b/libpthread/nptl/ChangeLog @@ -0,0 +1,11100 @@ +2010-01-15 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: + Fix unwind info. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + +2010-01-15 Michal Schmidt <mschmidt@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: + Fix pthread_cond_timedwait with requeue-PI. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: + Fix pthread_cond_wait with requeue-PI. + +2010-01-14 Ulrich Drepper <drepper@redhat.com> + + * Versions: Add pthread_mutex_consistent, pthread_mutexattr_getrobust, + and pthread_mutexattr_setrobust for GLIBC_2.12. + * pthread_mutex_consistent.c: Define alias pthread_mutex_consistent. + * pthread_mutexattr_getrobust.c: Define alias + pthread_mutexattr_getrobust. + * pthread_mutexattr_setrobust.c: Define alias + pthread_mutexattr_setrobust. + +2010-01-12 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread.h: Cleanup. Fix up for XPG7. + +2010-01-08 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread.h: Fix pthread_mutex_consistent declaration. + +2009-12-18 Thomas Schwinge <thomas@codesourcery.com> + + * sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c (_init): Don't + call __gmon_start__. + * sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c (_init): Likewise. + +2009-12-17 Ulrich Drepper <drepper@redhat.com> + + * pthread_rwlock_init.c (__pthread_rwlock_init): Simplify code by + using memset. + +2009-12-01 Dinakar Guniguntala <dino@in.ibm.com> + + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.h: Define + FUTEX_WAIT_REQUEUE_PI and FUTEX_CMP_REQUEUE_PI. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: If mutex + is a non robust PI mutex, then use FUTEX_CMP_REQUEUE_PI. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: If mutex + is a non robust PI mutex, then use FUTEX_WAIT_REQUEUE_PI. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + +2009-12-12 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S (sem_timedwait): + Don't update nwaiters after invalid timeout is recognized. + +2009-11-27 Thomas Schwinge <thomas@codesourcery.com> + + * sysdeps/unix/sysv/linux/sh/pt-initfini.c (_init): Don't call + __gmon_start__. + +2009-11-27 Andreas Schwab <schwab@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/cancellation.S: Reload + THREAD_SELF->cancelhandling after returning from futex call. + +2009-11-24 Ulrich Drepper <drepper@redhat.com> + + * tst-sem13.c: New file. + * Makefile (tests): Add tst-sem13. + +2009-11-22 Roland McGrath <roland@redhat.com> + + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h: # include "i686/dl-sysdep.h" + instead of recapitulating its contents. + +2009-11-18 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Minor + optimizations and cleanups. + +2009-11-18 Dinakar Guniguntala <dino@in.ibm.com> + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: + Remove redundant code. Fix cfi offsets. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: + Fix cfi offsets. + +2009-11-17 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Minimally + reduce size of unwind info. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Convert to use + cfi directives. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + Based on a patch by Dinakar Guniguntala <dino@in.ibm.com>. + +2009-11-03 Andreas Schwab <schwab@linux-m68k.org> + + [BZ #4457] + * sysdeps/pthread/unwind-resume.c: Include <libgcc_s.h> and use + LIBGCC_S_SO. + * sysdeps/pthread/unwind-forcedunwind.c: Likewise. + +2009-10-30 Ulrich Drepper <drepper@redhat.com> + + * tst-sem11.c (main): Rewrite to avoid aliasing problems. + + [BZ #3270] + * allocatestack.c (__nptl_setxid): Perform the operation in multiple + steps to avoid races with creation and terminations. + * nptl-init.c (sighandler_setxid): Adjust. + Patch by Daniel Jacobowitz. + +2009-09-07 Andreas Schwab <schwab@redhat.com> + + * sysdeps/pthread/bits/libc-lock.h (BP_SYM): Remove space before paren. + +2009-09-02 Suzuki K P <suzuki@in.ibm.com> + Joseph Myers <joseph@codesourcery.com> + + [BZ #7094] + * sysdeps/unix/sysv/linux/timer_create.c (timer_create): + Initialize the sigev_notify field for newly created timer to make sure + the timer gets deleted from the active timer's list upon timer_delete. + +2009-08-27 Andrew Stubbs <ams@codesourcery.com> + + * sysdeps/unix/sysv/linux/sh/lowlevellock.S (__lll_timedlock_wait): + Correct a logic error. + +2009-08-25 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/x86_64/tls.h (RTLD_ENABLE_FOREIGN_CALL): Store old value + of the field in local variables. + (RTLD_FINALIZE_FOREIGN_CALL): Restore rtld_must_xmm_save from local + variable and don't unconditionally clear it. + +2009-08-24 Ulrich Drepper <drepper@redhat.com> + + * pthread_create.c (start_thread): Hint to the kernel that memory for + the stack can be reused. We do not mark all the memory. The part + still in use and some reserve are kept. + +2009-08-23 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Clean up namespace. + +2009-08-11 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S: Add CFI + directives. + +2009-08-10 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: Add CFI + directives. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: Likewise. + +2009-08-10 Andreas Schwab <schwab@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S + (__pthread_cond_signal): Don't clobber register used for syscall + number. + +2009-08-08 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S (sem_timedwait): + Optimize code path used when FUTEX_CLOCK_REALTIME is supported. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S + (__pthread_cond_wait): Optimize by avoiding use of callee-safe + register. + +2009-08-07 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Little optimizations + enabled by the special *_asynccancel functions. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + + * sysdeps/unix/sysv/linux/x86_64/cancellation.S: Include lowlevellock.h. + +2009-08-04 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/cancellation.S: New file. + * sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S: New file. + * sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S: New file. + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h (PSEUDO): Optimize + since we can assume the special __*_{en,dis}able_asynccancel + functions. + (PUSHARGS_*, POPARGS_*, SAVESTK_*, RESTSTK_*): Removed. + * sysdeps/x86_64/tcb-offsets.sym: Add cancellation-related bits + and PTHREAD_CANCELED. + +2009-07-31 Ulrich Drepper <drepper@redhat.com> + + * descr.h: Better definition of *_BITMASK macros for cancellation. + +2009-07-29 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/x86_64/tls.h (TLS_TCB_ALIGN): Define explicitly to 32. + + * sysdeps/x86_64/tls.h (tcbhead_t): Add room for SSE registers the + dynamic linker might have to save. + Define RTLD_CHECK_FOREIGN_CALL, RTLD_ENABLE_FOREIGN_CALL, + RTLD_PREPARE_FOREIGN_CALL, and RTLD_FINALIZE_FOREIGN_CALL. Pretty + printing. + + * sysdeps/x86_64/tcb-offsets.sym: Add RTLD_SAVESPACE_SSE. + +2009-07-28 Ulrich Drepper <drepper@redhat.com> + + * pthread_mutex_lock.c [NO_INCR] (__pthread_mutex_cond_lock_adjust): + New function. + * pthreadP.h: Declare __pthread_mutex_cond_lock_adjust. + * sysdeps/unix/sysv/linux/pthread-pi-defines.sym: Add ROBUST_BIT. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: Don't use + requeue_pi for robust mutexes. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + Don't only skip __pthread_mutex_cond_lock. Call instead + __pthread_mutex_cond_lock_adjust. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + + * pthread_mutex_unlock.c (__pthread_mutex_unlock_full): Minor + optimization of PI mutex handling. + +2009-07-27 Ulrich Drepper <drepper@redhat.com> + + [BZ #10418] + * pthread_mutex_unlock.c (__pthread_mutex_unlock_full): Use _rel + instead of of _acq variants of cmpxchg. + +2009-07-23 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/x86_64/configure.in: New file. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Fix error + path when not using absolute timeout futex. + +2009-07-20 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Minor + optimizations of last changes. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + +2009-07-19 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Define + FUTEX_WAIT_REQUEUE_PI and FUTEX_CMP_REQUEUE_PI. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: If mutex + is a PI mutex, then use FUTEX_CMP_REQUEUE_PI. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: If mutex + is a PI mutex, then use FUTEX_WAIT_REQUEUE_PI. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Make more robust. + +2009-07-18 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S + (__lll_robust_timedlock_wait): If possible use FUTEX_WAIT_BITSET to + directly use absolute timeout. + + * tst-sem5.c (do_test): Add test for premature timeout. + * Makefile: Linu tst-sem5 with librt. + + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S + (pthread_rwlock_timedwrlock): If possible use FUTEX_WAIT_BITSET to + directly use absolute timeout. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S + (pthread_rwlock_timedrdlock): Likewise. + + * tst-cond11.c (run_test): Add test to check that the timeout is + long enough. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S + (__pthread_cond_timedwait): If possible use FUTEX_WAIT_BITSET to + directly use absolute timeout. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S + (__pthread_cond_wait): Convert to using exception handler instead of + registered unwind buffer. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Likewise. + +2009-07-17 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S (sem_timedwait): + If possible use FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME to directly + use absolute timeout. + + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S (sem_wait): Optimize + handling of uncontested semaphore. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S + (__condvar_cleanup): Rewrite to use cfi directives instead of + hand-coded unwind tables. + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S (__pthread_once): + Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S (sem_wait): Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S (sem_timedwait): + Likewise. + +2009-06-12 Ulrich Drepper <drepper@redhat.com> + + * Makefile (libpthread-routines): Add pthread_sigqueue. + * Versions: Add pthread_sigqueue for GLIBC_2.11. + * sysdeps/pthread/bits/sigthread.h: Declare pthread_sigqueue. + * sysdeps/unix/sysv/linux/pthread_sigqueue.c: New file. + +2009-06-11 Ulrich Drepper <drepper@redhat.com> + + [BZ #10262] + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S + (LOAD_FUTEX_WAIT_ABS): Fix futex parameter in case private futexes + cannot be assumed. + Patch by Bryan Kadzban <bz-glibc@kdzbn.homelinux.net>. + +2009-05-16 Ulrich Drepper <drepper@redhat.com> + + * libc-cancellation.c: Move __libc_cleanup_routine to... + * libc-cleanup.c: ...here. New file. + * Makefile (routines): Add libc-cleanup. + + * cancellation.c (__pthread_disable_asynccancel): Remove unnecessary + test. + * libc-cancellation.c: Use <nptl/cancellation.c: to define the code. + * sysdeps/pthread/librt-cancellation.c: Likewise. + + [BZ #9924] + * nptl-init.c: Renamed from init.c. + * Makefile: Change all occurences of init.c to nptl-init.c. + +2009-05-15 Ulrich Drepper <drepper@redhat.com> + + * cancellation.c (__pthread_disable_asynccancel): Correct the bits + to test when deciding on the delay. + * libc-cancellation.c (__libc_disable_asynccancel): Likewise. + * pthread_cancel.c: Close race between deciding on sending a signal + and setting the CANCELING_BIT bit. + + * cancellation.c (__pthread_disable_asynccancel): Don't return if + thread is canceled. + * libc-cancellation.c (__libc_disable_asynccancel): Likewise. + +2009-04-27 Ulrich Drepper <drepper@redhat.com> + + * cancellation.c (__pthread_disable_asynccancel): Use THREAD_ATOMIC_AND + is available. + * libc-cancellation.c (__libc_disable_asynccancel): Likewise. + * sysdeps/x86_64/tls.h: Define THREAD_ATOMIC_AND. + * sysdeps/i386/tls.h: Likewise. + (tcbhead_t): Add __private_tm member. + +2009-04-26 Ulrich Drepper <drepper@redhat.com> + + * sem_open.c (sem_open): Rewrite initialization of initsem to + avoid warnings. + + * sysdeps/unix/sysv/linux/libc_pthread_init.c (__libc_pthread_init): + Avoid warning by using may_alias attribute on ptrhack. + +2009-04-22 Ulrich Drepper <drepper@redhat.com> + + [BZ #10090] + * pthread_attr_setschedparam.c (__pthread_attr_setschedparam): + Check policy and priority for validity. + Patch mostly by Zhang Xiliang <zhangxiliang@cn.fujitsu.com>. + +2009-03-15 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Change to use cfi directives instead of + hand-coded unwind sections. + +2009-03-10 Ulrich Drepper <drepper@redhat.com> + + * init.c (nptl_freeres): Compile only for SHARED. + +2009-03-09 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h: Define + FUTEX_WAIT_BITSET, FUTEX_WAKE_BITSET, FUTEX_CLOCK_REALTIME and + FUTEX_BITSET_MATCH_ANY. + +2009-02-27 Roland McGrath <roland@redhat.com> + + * init.c (__nptl_initial_report_events): Mark __attribute_used__. + * pthread_create.c (__nptl_threads_events, __nptl_last_event): Likewise. + +2009-02-26 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Define + _POSIX_THREAD_ROBUST_PRIO_INHERIT and + _POSIX_THREAD_ROBUST_PRIO_PROTECT. Reset value of macros from + 200112L to 200809L. + +2009-02-25 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread.h: The robust mutex functions are in + POSIX 2008. + +2009-02-24 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/bits/posix_opt.h (_BITS_POSIX_OPT_H): + Unify name of include protector macro. + +2009-02-14 SUGIOKA Toshinobu <sugioka@itonet.co.jp> + + * sysdeps/unix/sysv/linux/sh/lowlevellock.S: Define + LOAD_FUTEX_WAIT_ABS even if (FUTEX_WAIT == 0). + +2009-01-29 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/unwind-forcedunwind.c: Encrypt all function + pointer variables. + + * allocatestack.c (__free_stacks): Renamed from free_stacks. + (__free_stack_cache): Removed. Change callers to call __free_stacks. + * init.c (nptl_freeres): New function. + (pthread_functions): Initialize ptr_freeres to nptl_freeres. + * pthreadP.h: Don't declare __free_stack_cache. Declare __free_stacks. + * sysdeps/pthread/unwind-forcedunwind.c (libgcc_s_handle): New + variable. + (pthread_cancel_init): Depend in libgcc_s_handle for decision to + load DSO. Assign last. + (__unwind_freeres): New function. + + * allocatestack.c (__reclaim_stacks): Reset in_flight_stack later + for better debugging. No need to use stack_list_add here. + +2009-01-14 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/lowlevellock.S + (__lll_timedlock_wait): Use FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME + instead of computing relative timeout. + * sysdeps/unix/sysv/linux/sh/lowlevellock.h: Define + FUTEX_CLOCK_REALTIME and FUTEX_BITSET_MATCH_ANY. + +2009-01-25 Ulrich Drepper <drepper@redhat.com> + + * pthread_mutex_lock.c (__pthread_mutex_lock): Remove unused label out. + +2009-01-08 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/list.h (list_add): Initialize new element first. + (list_add_tail): Removed. + +2009-01-07 Ulrich Drepper <drepper@redhat.com> + + * (in_flight_stack): New variable. + (stack_list_del): New function. Use instead of list_del. + (stack_list_add): New function. Use instead of list_add when adding to + stack_cache and stack_used lists. + (__reclaim_stacks): Complete operations on stack_cache and stack_used lists + when the fork call interrupted another thread. + +2009-01-04 Ulrich Drepper <drepper@redhat.com> + + * init.c (__pthread_initialize_minimal_internal): Optimize test + FUTEX_CLOCK_REALTIME a bit. + +2009-01-03 Ulrich Drepper <drepper@redhat.com> + + * init.c (__pthread_initialize_minimal_internal): Cheat a bit by + only passing five parameters to FUTEX_WAIT_BITSET call. + + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S + (__lll_timedlock_wait): Use FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME + instead of computing relative timeout. + +2009-01-02 Ulrich Drepper <drepper@redhat.com> + + * init.c (__pthread_initialize_minimal_internal): Check for + FUTEX_CLOCK_REALTIME flag. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S (__lll_timedlock_wait): + Use FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME instead of computing + relative timeout. + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Define + FUTEX_CLOCK_REALTIME and FUTEX_BITSET_MATCH_ANY. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h: Likewise. + +2008-12-09 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread.h (pthread_cleanup_pop): Use { } as empty + loop body instead of ; to avoid gcc warnings. + (pthread_cleanup_pop_restore_np): Likewise. + Patch by Caolán McNamara <caolanm@redhat.com>. + +2008-12-09 Jakub Jelinek <jakub@redhat.com> + + * pthread_mutex_lock.c (__pthread_mutex_lock): Handle only the + fast path here, for robust/PI/PP mutexes call + __pthread_mutex_lock_full. Don't use switch, instead use a series + of ifs according to their probability. + (__pthread_mutex_lock_full): New function. + * pthread_mutex_unlock.c: Include assert.h. + (__pthread_mutex_unlock_usercnt): Handle only the + fast path here, for robust/PI/PP mutexes call + __pthread_mutex_unlock_full. Don't use switch, instead use a series + of ifs according to their probability. + (__pthread_mutex_unlock_full): New function. + * sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c + (__pthread_mutex_lock_full): Define. + +2008-12-08 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/x86_64/tls.h (tcbhead_t): Add fields reserved for TM + implementation. Add necessary padding and. + * descr.h (struct pthread): Increase padding for tcbhead_t to 24 + words. + +2008-12-04 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/lowlevellock.h: Define FUTEX_WAIT_BITSET + and FUTEX_WAKE_BITSET. + +2008-12-02 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Define FUTEX_WAIT_BITSET + and FUTEX_WAKE_BITSET. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. + +2008-11-25 Roland McGrath <roland@redhat.com> + + * sysdeps/alpha, sysdeps/unix/sysv/linux/alpha: + Subdirectories moved to ports repository as + sysdeps/.../nptl subdirectories. + +2008-11-12 Jakub Jelinek <jakub@redhat.com> + + [BZ #7008] + * pthread_condattr_setclock.c (pthread_condattr_setclock): Fix masking + of old value. + * pthread_cond_init.c (__pthread_cond_init): Fix + cond->__data.__nwaiters initialization. + * Makefile (tests): Add tst-cond23. + * tst-cond23.c: New test. + +2008-11-07 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/malloc-machine.h (MALLOC): Adjust __libc_tsd_define + arguments. + (tsd_setspecific, tsd_getspecific): Adjust __libc_tsd_{set,get} + arguments. + +2008-11-01 Ulrich Drepper <drepper@redhat.com> + + [BZ #6955] + * pthread_mutex_lock.c: Add support for private PI mutexes. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_trylock.c: Likewise. + * pthread_mutex_unlock.c: Likewise. + Patch mostly by Ben Jackson <ben@ben.com>. + +2008-10-31 Ulrich Drepper <drepper@redhat.com> + + [BZ #6843] + * sysdeps/pthread/gai_misc.h (__gai_create_helper_thread): + Increase stack size for helper thread. + +2008-10-06 Martin Schwidefsky <schwidefsky@de.ibm.com> + + * sysdeps/s390/tls.h (THREAD_SET_STACK_GUARD): Add empty inline + assembly with a clobber list for access registers a0 and a1. + +2008-09-11 Martin Schwidefsky <schwidefsky@de.ibm.com> + + * sysdeps/unix/sysv/linux/fork.c (__libc_fork): Add memory barrier + to force runp->refcntr to be read from memory. + +2008-09-08 Richard Guenther <rguenther@suse.de> + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_lock, + lll_robust_lock, lll_cond_lock, lll_robust_cond_lock, + lll_timedlock, lll_robust_timedlock, lll_unlock, + lll_robust_unlock): Promote private to int. + +2008-08-15 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/x86_64/pthreaddef.h: Remove ARCH_MAP_FLAGS and + ARCH_RETRY_MMAP definitions. + * allocatestack.c: Remove definition of ARCH_MAP_FLAGS. + Define MAP_STACK when not defined. + (allocate_stack): Use MAP_STACK instead of ARCH_MAP_FLAGS. Remove + handling of ARCH_RETRY_MMAP. + +2008-07-30 Ulrich Drepper <drepper@redhat.com> + + * tst-align2.c (f): Print message that f is reached. + +2008-04-28 Hiroki Kaminaga <kaminaga@sm.sony.co.jp> + + [BZ #6740] + * sysdeps/powerpc/tcb-offsets.sym (PRIVATE_FUTEX_OFFSET): Guard symbol + definition with #ifndef __ASSUME_PRIVATE_FUTEX. + +2008-07-25 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/mq_notify.c (init_mq_netlink): Use + SOCK_CLOEXEC if possible. + +2008-05-29 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-rwlock2a. + * tst-rwlock2.c: Use TYPE macro to decide what rwlock type to use. + * tst-rwlock2a.c: New file. + +2008-06-12 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread.h: Remove inadvertant checkin. + +2008-05-17 Samuel Thibault <samuel.thibault@ens-lyon.org> + + * sysdeps/pthread/pthread.h: Fix typo in comment. + +2008-05-28 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/createthread.c (do_clone): Pass accurate length + of CPU set to the kernel. + +2008-05-23 Paul Pluzhnikov <ppluzhnikov@google.com> + + * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: Add + cfi directives. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Likewise. + +2008-05-22 Paul Pluzhnikov <ppluzhnikov@google.com> + + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: Add + cfi directives. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S: + Likewise. + +2008-05-26 Ulrich Drepper <drepper@redhat.com> + + * tst-typesizes.c: Explicitly check __SIZEOF_PTHREAD_* constants. + +2008-05-20 Jakub Jelinek <jakub@redhat.com> + + David S. Miller <davem@davemloft.net> + + * sysdeps/unix/sysv/linux/sparc/sparc64/Makefile: New file. + +2008-05-10 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Access + __pshared correctly. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: + Likewise. + Reported by Clemens Kolbitsch <clemens.kol@gmx.at>. + +2008-04-14 David S. Miller <davem@davemloft.net> + + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c + (__old_sem_wait): Fix argument to lll_futex_wait(). + +2007-11-26 Daniel Jacobowitz <dan@codesourcery.com> + + * pthread_create.c: Require pthread_mutex_trylock and + pthread_key_delete for libgcc. + +2008-04-08 Jakub Jelinek <jakub@redhat.com> + + [BZ #6020] + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h + (lll_futex_wake_unlock): Add private argument to the pre-v9 macro. + Patch by Sunil Amitkumar Janki <devel.sjanki@gmail.com>. + +2008-03-27 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/bits/local_lim.h: Undefine ARG_MAX if + <linux/limits.h> has defined it. + * sysdeps/unix/sysv/linux/alpha/bits/local_lim.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/local_lim.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/local_lim.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/local_lim.h: Likewise. + +2008-03-18 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/ia64/dl-sysdep.h: Use __ASSEMBLER__ instead + of ASSEMBLER. + * sysdeps/unix/sysv/linux/i386/i686/dl-sysdep.h: Likewise. + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h: Likewise. + +2008-03-14 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h: Define + HAVE_DL_DISCOVER_OSVERSION. + * sysdeps/unix/sysv/linux/i386/i686/dl-sysdep.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/dl-sysdep.h: Likewise. + +2008-03-07 Ulrich Drepper <drepper@redhat.com> + + [BZ #5778] + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Change + _POSIX_CHOWN_RESTRICTED value to zero. + +2008-01-31 Roland McGrath <roland@redhat.com> + + * Makefile (omit-deps): Variable removed. + +2008-01-30 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/sem_post.S (sem_post): Avoid + unnecessary addr32 prefix. + +2008-01-29 Roland McGrath <roland@redhat.com> + + * Makeconfig (ptw-CPPFLAGS, sysd-rules-patterns): New variables. + +2008-01-22 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/sem_post.S: Don't overflow value field. + +2008-01-21 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h (XADD): Use + a scratch register. + * sysdeps/unix/sysv/linux/sh/lowlevellock.S + (__lll_lock_wait_private): Fix typo. + * sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S + (pthread_barrier_wait): Likewise. Adjust XADD use. + * sysdeps/unix/sysv/linux/sh/sem_post.S (__new_sem_post): + Adjust XADD use. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S + (pthread_rwlock_timedrdlock): Return correct return value. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S + (pthread_rwlock_timedwrlock): Likewise. + +2008-01-15 Ulrich Drepper <drepper@redhat.com> + + * tst-eintr2.c (do_test): make sure that if mutex_lock in main + thread returns the program exits with an error code. + +2008-01-10 Ulrich Drepper <drepper@redhat.com> + + * pthread-errnos.sym: Add EOVERFLOW. + * sysdeps/unix/sysv/linux/structsem.sym: Add SEM_VALUE_MAX. + * sysdeps/unix/sysv/linux/sem_post.c: Don't overflow value field. + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_post.S: Likewise. + +2007-12-14 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/x86_64/pthreaddef.h (ARCH_RETRY_MMAP): Take additional + parameter. Passed it as permission to mmap. + * allocatestack.c (allocate_stack): Pass prot as second parameter + to ARCH_RETRY_MMAP. + +2007-12-12 Ulrich Drepper <drepper@redhat.com> + + * tst-basic7.c: Allocate memory for the stack. + + [BZ #5465] + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S [!SHARED] + (__pthread_cond_timedwait): Don't use VDSO. + Patch by Michal Januszewski. + +2007-12-07 Ulrich Drepper <drepper@redhat.com> + + [BZ #5455] + * sysdeps/pthread/pthread.h [!__EXCEPTIONS] (pthread_cleanup_pop): + Allow label before pthread_cleanup_pop. + (pthread_cleanup_pop_restore_np): Likewise. + +2007-12-04 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/lowlevellock.S (__lll_timedlock_wait): + Store 2 before returning ETIMEDOUT. + +2007-11-23 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S (__lll_timedlock_wait): + Store 2 before returning ETIMEDOUT. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Likewise + * sysdeps/unix/sysv/linux/lowlevellock.c: Likewise. + (__lll_lock_wait_private): Optimize. + (__lll_lock_wait): Likewise. + +2007-11-20 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/pthread.h (pthread_cleanup_push, + pthread_cleanup_push_defer_np): Add extra (void *) cast to shut up + g++ 4.1 and 4.2 -Wstrict-aliasing warnings. + +2007-11-08 Ulrich Drepper <drepper@redhat.com> + + [BZ #5240] + * sysdeps/unix/sysv/linux/lowlevellock.c (__lll_timedlock_wait): + If we time out, try one last time to lock the futex to avoid + losing a wakeup signal. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Likewise. + + [BZ #5245] + * sysdeps/pthread/createthread.c (do_clone): Translate clone error + if necessary. + +2007-11-07 Ulrich Drepper <drepper@redhat.com> + + [BZ #5245] + * allocatestack.c (allocate_stack): Change ENOMEM error in case + mmap failed to EAGAIN. + * Makefile (tests): Add tst-basic7. + * tst-basic7.c: New file. + +2007-11-05 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/register-atfork.c (__register_atfork): + Use __linkin_atfork. + +2007-11-03 Mike Frysinger <vapier@gentoo.org> + + * sysdeps/unix/sysv/linux/sh/lowlevellock.S (LOAD_FUTEX_WAIT): Add + missing line continuations. + * sysdeps/unix/sysv/linux/sh/lowlevelrobustlock.S (LOAD_FUTEX_WAIT, + LOAD_FUTEX_WAKE): Likewise. Also add missing 3rd parameter. + +2007-10-28 Ulrich Drepper <drepper@redhat.com> + + [BZ #5220] + * sysdeps/unix/sysv/linux/kernel-posix-timers.h: Declare + __active_timer_sigev_thread and __active_timer_sigev_thread_lock. + (struct timer): Add next element. + * sysdeps/unix/sysv/linux/timer_create.c: For SIGEV_THREAD timers, + enqueue timer structure into __active_timer_sigev_thread list. + * sysdeps/unix/sysv/linux/timer_delete.c: For SIGEV_THREAD timers, + remove timer struct from __active_timer_sigev_thread. + * sysdeps/unix/sysv/linux/timer_routines.c (timer_helper_thread): + Before using timer structure make sure it is still on the + __active_timer_sigev_thread list. Keep lock until done. + Define __active_timer_sigev_thread and + __active_timer_sigev_thread_lock. + +2007-10-27 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/malloc-machine.h: Define ATFORK_MEM. + Redefine thread_atfork for use of ATFORK_MEM. + * sysdeps/unix/sysv/linux/fork.h: Define __linkin_atfork. + * sysdeps/unix/sysv/linux/register-atfork.c (__linkin_atfork): New + function. + * sysdeps/unix/sysv/linux/unregister-atfork.c (__unregister_atfork): + Use atomic operation when removing first element of list. + +2007-10-17 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S (__old_sem_post): New + routine instead of an alias to __new_sem_post. + +2007-10-15 Jakub Jelinek <jakub@redhat.com> + + * init.c (__pthread_initialize_minimal): Initialize word to appease + valgrind. + +2007-10-10 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/bits/libc-lock.h (__libc_rwlock_init): Inside of + libc.so just clear NAME. + (__libc_rwlock_fini): Nop inside of libc.so. + * tst-initializers1.c (main): Test if PTHREAD_RWLOCK_INITIALIZER is + all zeros. + +2007-09-02 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S + (__pthread_cond_wait): Fix unlocking of internal lock after mutex + unlocking failed. + Patch by Luca Barbieri <luca.barbieri@gmail.com>. + +2007-08-21 Ulrich Drepper <drepper@redhat.com> + + [BZ #4938] + * allocatestack.c (__reclaim_stacks): Clear the TSD in the + reclaimed stack if necessary. + * Makefile (tests): Add tst-tsd6. + * tst-tsd6.c: New file. + +2007-08-21 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h (lll_robust_dead): + Add private argument. + +2007-08-20 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Use clock_gettime from VDSO if possible. + +2007-08-16 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h + (__lll_robust_timedlock): Pass private as last argument to + __lll_robust_timedlock_wait. + (__lll_unlock): Fix a pasto. + +2007-08-15 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/sparc/internaltypes.h (sparc_new_sem, + sparc_old_sem): New structs. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c + (__sem_wait_cleanup): New function. + (__new_sem_wait): Use sparc_new_sem structure. Bump and afterwards + decrease nwaiters. Register __sem_wait_cleanup as cleanup handler. + Pass isem->private ^ FUTEX_PRIVATE_FLAG as last argument to + lll_futex_wait. + (__old_sem_wait): New function. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_wait.c: Include + nptl/sysdeps/unix/sysv/linux/sparc version. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_timedwait.c: + Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_post.c: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c + (__new_sem_trywait): Use sparc_old_sem structure. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c + (sem_timedwait): Use sparc_new_sem structure. Bump and afterwards + decrease nwaiters. Register __sem_wait_cleanup as cleanup handler. + Pass isem->private ^ FUTEX_PRIVATE_FLAG as last argument to + lll_futex_timed_wait. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c (__new_sem_post): + Use sparc_new_sem structure. Only wake if nwaiters > 0. Pass + isem->private ^ FUTEX_PRIVATE_FLAG as last argument to + lll_futex_wake. + (__old_sem_post): New function. + * sysdeps/unix/sysv/linux/sparc/sem_wait.c: New file. + * sysdeps/unix/sysv/linux/sparc/sem_init.c: New file. + * sysdeps/unix/sysv/linux/sparc/sem_timedwait.c: New file. + * sysdeps/unix/sysv/linux/sparc/sem_post.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_init.c: Remove. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_init.c: Remove. + +2007-08-14 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S + (__pthread_cond_broadcast): Pass LLL_PRIVATE to lll_* and or + FUTEX_PRIVATE_FLAG into SYS_futex op if cv is process private. + Don't use FUTEX_CMP_REQUEUE if dep_mutex is not process private. + * sysdeps/unix/sysv/linux/shpthread_cond_signal.S + (__pthread_cond_signal): Pass LLL_PRIVATE to lll_* and or + FUTEX_PRIVATE_FLAG into SYS_futex op if cv is process private. + Use FUTEX_WAKE_OP. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Include + kernel-features.h and tcb-offsets.h. + (__pthread_cond_wait, __condvar_w_cleanup): Pass LLL_PRIVATE to + lll_* and or FUTEX_PRIVATE_FLAG into SYS_futex op if cv is + process private. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Include + tcb-offsets.h. + (__pthread_cond_timedwait, __condvar_tw_cleanup): Pass LLL_PRIVATE + to lll_* and or FUTEX_PRIVATE_FLAG into SYS_futex op if cv is + process private. + * sysdeps/unix/sysv/linux/sh/pthread_once.S: Use #ifdef + __ASSUME_PRIVATE_FUTEX instead of #if __ASSUME_PRIVATE_FUTEX. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Likewise. + +2007-08-14 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/lowlevellock.c: Comment fix. + * sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c + (__lll_timedwait_tid): Pass LLL_SHARED as 4th argument to + lll_futex_timed_wait. + + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h (__lll_unlock, + __lll_robust_unlock): Rewrite as macros instead of inline functions. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h (__lll_unlock, + __lll_robust_unlock, __lll_wait_tid): Likewise. + +2007-08-13 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h (__lll_private_flag): + Fix a pasto. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S + (__pthread_cond_broadcast): Pass LLL_PRIVATE to lll_* and or + FUTEX_PRIVATE_FLAG into SYS_futex op if cv is process private. + Don't use FUTEX_CMP_REQUEUE if dep_mutex is not process private. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S + (__pthread_cond_signal): Pass LLL_PRIVATE to lll_* and or + FUTEX_PRIVATE_FLAG into SYS_futex op if cv is process private. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Include + kernel-features.h. + (__pthread_cond_wait, __condvar_w_cleanup): Pass LLL_PRIVATE to + lll_* and or FUTEX_PRIVATE_FLAG into SYS_futex op if cv is + process private. Switch DW_CFA_advance_loc1 and some + DW_CFA_advance_loc .eh_frame opcodes to DW_CFA_advance_loc4. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__pthread_cond_timedwait, __condvar_tw_cleanup): Pass LLL_PRIVATE to + lll_* and or FUTEX_PRIVATE_FLAG into SYS_futex op if cv is + process private. Switch DW_CFA_advance_loc{1,2} and some + DW_CFA_advance_loc .eh_frame opcodes to DW_CFA_advance_loc4. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Use + #ifdef __ASSUME_PRIVATE_FUTEX instead of #if __ASSUME_PRIVATE_FUTEX. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S + (__pthread_cond_broadcast): Compare %r8 instead of + dep_mutex-cond_*(%rdi) with $-1. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S + (__pthread_cond_signal): Xor FUTEX_WAKE_OP with FUTEX_WAKE instead + of oring. + +2007-08-13 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i786/Implies: New file. + +2007-08-13 Jakub Jelinek <jakub@redhat.com> + + * allocatestack.c: Include kernel-features.h. + * pthread_create.c: Likewise. + * pthread_mutex_init.c: Likewise. + * init.c: Likewise. + * pthread_cond_timedwait.c: Likewise. + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. + +2007-08-12 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h + [__WORDSIZE=32] (pthread_rwlock_t): Split __flags element into four + byte elements. One of them is the new __shared element. + [__WORDSIZE=64] (pthread_rwlock_t): Renamed __pad1 element to __shared, + adjust names of other padding elements. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h + [__WORDSIZE=32] (pthread_rwlock_t): Split __flags element into four + byte elements. One of them is the new __shared element. + [__WORDSIZE=64] (pthread_rwlock_t): Renamed __pad1 element to __shared, + adjust names of other padding elements. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h (pthread_rwlock_t): + Renamed __pad1 element to __shared, adjust names of other padding + elements. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h + (pthread_rwlock_t): Likewise. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (__lll_lock): Fix a + typo. + +2007-08-09 Anton Blanchard <anton@samba.org> + + * sysdeps/unix/sysv/linux/powerpc/pthread_spin_unlock.c: New file. + +2007-08-12 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Include + <kernel-features.h>. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + +2007-08-11 Ulrich Drepper <drepper@redhat.com> + + * pthreadP.h (PTHREAD_ROBUST_MUTEX_PSHARED): Define. + * pthread_mutex_lock.c: Use it instead of PTHREAD_MUTEX_PSHARED when + dealing with robust mutexes. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_trylock.c: Likewise. + * pthread_mutex_unlock.c: Likewise. + * sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c: Likewise. + +2007-08-06 Jakub Jelinek <jakub@redhat.com> + + * pthreadP.h (PTHREAD_MUTEX_PSHARED_BIT): Define. + (PTHREAD_MUTEX_TYPE): Mask __kind with 127. + (PTHREAD_MUTEX_PSHARED): Define. + * pthread_mutex_init.c (__pthread_mutex_init): Set + PTHREAD_MUTEX_PSHARED_BIT for pshared or robust + mutexes. + * pthread_mutex_lock.c (LLL_MUTEX_LOCK): Take mutex as argument + instead of its __data.__lock field, pass PTHREAD_MUTEX_PSHARED + as second argument to lll_lock. + (LLL_MUTEX_TRYLOCK): Take mutex as argument + instead of its __data.__lock field. + (LLL_ROBUST_MUTEX_LOCK): Take mutex as argument instead of its + __data.__lock field, pass PTHREAD_MUTEX_PSHARED as second argument + to lll_robust_lock. + (__pthread_mutex_lock): Update LLL_MUTEX_LOCK, LLL_MUTEX_TRYLOCK, + LLL_ROBUST_MUTEX_LOCK users, use PTHREAD_MUTEX_TYPE (mutex) + instead of mutex->__data.__kind directly, pass + PTHREAD_MUTEX_PSHARED (mutex) to lll_unlock and lll_futex_wait. + * pthread_mutex_trylock.c (__pthread_mutex_trylock): Use + PTHREAD_MUTEX_TYPE (mutex) instead of mutex->__data.__kind + directly, pass PTHREAD_MUTEX_PSHARED (mutex) to lll_unlock. + (pthread_mutex_timedlock): Pass PTHREAD_MUTEX_PSHARED (mutex) + to lll_timedlock, lll_robust_timedlock, lll_unlock and + lll_futex_timed_wait. Use PTHREAD_MUTEX_TYPE (mutex) instead + of mutex->__data.__kind directly. + * pthread_mutex_timedlock.c (pthread_mutex_timedlock): Pass + PTHREAD_MUTEX_PSHARED (mutex) to lll_timedlock, + lll_robust_timedlock, lll_unlock and lll_futex_timed_wait. Use + PTHREAD_MUTEX_TYPE (mutex) instead of mutex->__data.__kind directly. + * pthread_mutex_unlock.c (__pthread_mutex_unlock_usercnt): Pass + PTHREAD_MUTEX_PSHARED (mutex) to lll_unlock, lll_robust_unlock + and lll_futex_wake. + * pthread_mutex_setprioceiling.c (pthread_mutex_setprioceiling): Pass + PTHREAD_MUTEX_PSHARED (mutex) to lll_futex_wait and lll_futex_wake. + Use PTHREAD_MUTEX_TYPE (mutex) instead of mutex->__data.__kind + directly. + * sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c (LLL_MUTEX_LOCK): + Take mutex as argument instead of its __data.__lock field, pass + PTHREAD_MUTEX_PSHARED as second argument to lll_cond_lock. + (LLL_MUTEX_TRYLOCK): Take mutex as argument instead of its + __data.__lock field. + (LLL_ROBUST_MUTEX_LOCK): Take mutex as argument instead of its + __data.__lock field, pass PTHREAD_MUTEX_PSHARED as second argument + to lll_robust_cond_lock. + * pthread_cond_broadcast.c (__pthread_cond_broadcast): Add pshared + variable, pass it to lll_lock, lll_unlock, lll_futex_requeue and + lll_futex_wake. Don't use lll_futex_requeue if dependent mutex + has PTHREAD_MUTEX_PSHARED_BIT bit set in its __data.__kind. + * pthread_cond_destroy.c (__pthread_cond_destroy): Add pshared + variable, pass it to lll_lock, lll_unlock, lll_futex_wake and + lll_futex_wait. + * pthread_cond_signal.c (__pthread_cond_signal): Add pshared + variable, pass it to lll_lock, lll_unlock, lll_futex_wake_unlock and + lll_futex_wake. + * pthread_cond_timedwait.c (__pthread_cond_wait): Add + pshared variable, pass it to lll_lock, lll_unlock, + lll_futex_timedwait and lll_futex_wake. + * pthread_cond_wait.c (__condvar_cleanup, __pthread_cond_wait): Add + pshared variable, pass it to lll_lock, lll_unlock, lll_futex_wait + and lll_futex_wake. + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h (lll_futex_requeue, + lll_futex_wake_unlock): Add private argument, use __lll_private_flag + macro. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (lll_futex_requeue, + lll_futex_wake_unlock): Likewise. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (lll_futex_requeue): + Likewise. + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h (lll_futex_requeue, + lll_futex_wake_unlock): Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (lll_futex_requeue): + Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h (lll_futex_requeue, + lll_futex_wake_unlock): Likewise. + (lll_futex_wake): Fix a typo. + * sysdeps/unix/sysv/linux/pthread-pi-defines.sym (PS_BIT): Add. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S + (__pthread_cond_broadcast): Pass LLL_PRIVATE to lll_* and or + FUTEX_PRIVATE_FLAG into SYS_futex op if cv is process private. + Don't use FUTEX_CMP_REQUEUE if dep_mutex is not process private. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S + (__pthread_cond_signal): Pass LLL_PRIVATE to lll_* and or + FUTEX_PRIVATE_FLAG into SYS_futex op if cv is process private. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: + (__condvar_cleanup, __pthread_cond_wait): Likewise. + +2007-08-05 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h (PSEUDO): + Don't use CGOTSETUP and CGOTRESTORE macros. + (CGOTSETUP, CGOTRESTORE): Remove. + <IS_IN_rtld> (CENABLE, CDISABLE): Don't use JUMPTARGET, branch to + @local symbol. + +2007-08-01 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S: Remove + definitions for private futexes. + * sysdeps/unix/sysv/linux/sh/lowlevellock.S: Include + kernel-features.h and lowlevellock.h. Use private futexes if + they are available. + (__lll_lock_wait_private, __lll_unlock_wake_private): New. + (__lll_mutex_lock_wait): Rename to + (__lll_lock_wait): ... this. Don't compile in for libc.so. + (__lll_mutex_timedlock_wait): Rename to ... + (__lll_timedlock_wait): ... this. Use __NR_gettimeofday. + Don't compile in for libc.so. + (__lll_mutex_unlock_wake): Rename to ... + (__lll_unlock_wake): ... this. Don't compile in for libc.so. + (__lll_timedwait_tid): Use __NR_gettimeofday. + * sysdeps/unix/sysv/linux/sh/lowlevellock.h: Allow including + the header from assembler. Renamed all lll_mutex_* resp. + lll_robust_mutex_* macros to lll_* resp. lll_robust_*. + Renamed all LLL_MUTEX_LOCK_* macros to LLL_LOCK_*. + (FUTEX_CMP_REQUEUE, FUTEX_WAKE_OP, FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): + Define. + (__lll_lock_wait_private): Add prototype. + (__lll_lock_wait, __lll_timedlock_wait, __lll_robust_lock_wait, + __lll_robust_timedlock_wait, __lll_unlock_wake_private, + __lll_unlock_wake): Likewise. + (lll_lock): Add private argument. Call __lll_lock_wait_private + if private is constant LLL_PRIVATE. + (lll_robust_lock, lll_cond_lock, lll_robust_cond_lock, + lll_timedlock, lll_robust_timedlock): Add private argument. + (lll_unlock): Add private argument. Call __lll_unlock_wake_private + if private is constant LLL_PRIVATE. + (lll_robust_unlock, lll_robust_dead): Add private argument. + (lll_lock_t): Remove. + (__lll_cond_wait, __lll_cond_timedwait, __lll_cond_wake, + __lll_cond_broadcast, lll_cond_wait, lll_cond_timedwait, + lll_cond_wake, lll_cond_broadcast): Remove. + * sysdeps/unix/sysv/linux/sh/lowlevelrobustlock.S: Include + kernel-features.h and lowlevellock.h. + (SYS_gettimeofday, SYS_futex, FUTEX_WAIT, FUTEX_WAKE): Remove. + (LOAD_FUTEX_WAIT): Define. + (__lll_robust_mutex_lock_wait): Rename to ... + (__lll_robust_lock_wait): ... this. Add private argument. + Use LOAD_FUTEX_WAIT macro. + (__lll_robust_mutex_timedlock_wait): Rename to ... + (__lll_robust_timedlock_wait): ... this. Add private argument. + Use __NR_gettimeofday. Use LOAD_FUTEX_WAIT macro. + * sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S: Include + lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE): Remove. + (pthread_barrier_wait): Use __lll_{lock,unlock}_* instead of + __lll_mutex_{lock,unlock}_*. + * sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S: Include + lowlevellock.h and pthread-errnos.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE, + FUTEX_CMP_REQUEUE, EINVAL): Remove. + (__pthread_cond_broadcast): Use __lll_{lock,unlock}_* instead of + __lll_mutex_{lock,unlock}_*. + * sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S: Include + lowlevellock.h and pthread-errnos.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE, EINVAL): Remove. + (__pthread_cond_signal): Use __lll_{lock,unlock}_* instead of + __lll_mutex_{lock,unlock}_*. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Include + lowlevellock.h. + (SYS_futex, SYS_gettimeofday, FUTEX_WAIT, FUTEX_WAKE): Remove. + (__pthread_cond_timedwait): Use __lll_{lock,unlock}_* instead of + __lll_mutex_{lock,unlock}_*. Use __NR_gettimeofday. + (__condvar_tw_cleanup): Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Include + lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE): Remove. + (__pthread_cond_wait): Use __lll_{lock,unlock}_* instead of + __lll_mutex_{lock,unlock}_*. + ( __condvar_w_cleanup): Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_once.S: Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG): Remove. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: Include + lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG): Remove. + (__pthread_rwlock_rdlock): Use __lll_{lock,unlock}_* instead of + __lll_mutex_{lock,unlock}_*. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: Include + lowlevellock.h. + (SYS_gettimeofday, SYS_futex, FUTEX_WAIT, FUTEX_WAKE, + FUTEX_PRIVATE_FLAG): Remove. + (pthread_rwlock_timedrdlock): Use __lll_{lock,unlock}_* instead of + __lll_mutex_{lock,unlock}_*. Use __NR_gettimeofday. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: Include + lowlevellock.h. + (SYS_gettimeofday, SYS_futex, FUTEX_WAIT, FUTEX_WAKE, + FUTEX_PRIVATE_FLAG): Remove. + (pthread_rwlock_timedwrlock): Use __lll_{lock,unlock}_* instead of + __lll_mutex_{lock,unlock}_*. Use __NR_gettimeofday. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S: Include + lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG): Remove. + (__pthread_rwlock_unlock): Use __lll_{lock,unlock}_* instead of + __lll_mutex_{lock,unlock}_*. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Include + lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG): Remove. + (__pthread_rwlock_wrlock): Use __lll_{lock,unlock}_* instead of + __lll_mutex_{lock,unlock}_*. + * sysdeps/unix/sysv/linux/sh/sem_post.S: Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG): Remove. + (__new_sem_post): Use standard initial exec code sequences. + * sysdeps/unix/sysv/linux/sh/sem_timedwait.S: Include + lowlevellock.h. + (SYS_gettimeofday, SYS_futex, FUTEX_WAIT, FUTEX_WAKE, + FUTEX_PRIVATE_FLAG): Remove. + (sem_timedwait): Use __NR_gettimeofday. Use standard initial + exec code sequences. + * sysdeps/unix/sysv/linux/sh/sem_trywait.S: Include lowlevellock.h. + (__new_sem_trywait): Use standard initial exec code sequences. + * sysdeps/unix/sysv/linux/sh/sem_wait.S: Include lowlevellock.h. + (__new_sem_wait): Use standard initial exec code sequences. + +2007-07-31 Anton Blanchard <anton@samba.org> + + * sysdeps/unix/sysv/linux/powerpc/sem_post.c (__new_sem_post): + Use __asm __volatile (__lll_acq_instr ::: "memory") instead of + atomic_full_barrier. + +2007-07-31 Jakub Jelinek <jakub@redhat.com> + + * allocatestack.c (stack_cache_lock): Change type to int. + (get_cached_stack, allocate_stack, __deallocate_stack, + __make_stacks_executable, __find_thread_by_id, __nptl_setxid, + __pthread_init_static_tls, __wait_lookup_done): Add LLL_PRIVATE + as second argument to lll_lock and lll_unlock macros on + stack_cache_lock. + * pthread_create.c (__find_in_stack_list): Likewise. + (start_thread): Similarly with pd->lock. Use lll_robust_dead + macro instead of lll_robust_mutex_dead, pass LLL_SHARED to it + as second argument. + * descr.h (struct pthread): Change lock and setxid_futex field + type to int. + * old_pthread_cond_broadcast.c (__pthread_cond_broadcast_2_0): Use + LLL_LOCK_INITIALIZER instead of LLL_MUTEX_LOCK_INITIALIZER. + * old_pthread_cond_signal.c (__pthread_cond_signal_2_0): Likewise. + * old_pthread_cond_timedwait.c (__pthread_cond_timedwait_2_0): + Likewise. + * old_pthread_cond_wait.c (__pthread_cond_wait_2_0): Likewise. + * pthread_cond_init.c (__pthread_cond_init): Likewise. + * pthreadP.h (__attr_list_lock): Change type to int. + * pthread_attr_init.c (__attr_list_lock): Likewise. + * pthread_barrier_destroy.c (pthread_barrier_destroy): Pass + ibarrier->private ^ FUTEX_PRIVATE_FLAG as second argument to + lll_{,un}lock. + * pthread_barrier_wait.c (pthread_barrier_wait): Likewise and + also for lll_futex_{wake,wait}. + * pthread_barrier_init.c (pthread_barrier_init): Make iattr + a pointer to const. + * pthread_cond_broadcast.c (__pthread_cond_broadcast): Pass + LLL_SHARED as second argument to lll_{,un}lock. + * pthread_cond_destroy.c (__pthread_cond_destroy): Likewise. + * pthread_cond_signal.c (__pthread_cond_singal): Likewise. + * pthread_cond_timedwait.c (__pthread_cond_timedwait): Likewise. + * pthread_cond_wait.c (__condvar_cleanup, __pthread_cond_wait): + Likewise. + * pthread_getattr_np.c (pthread_getattr_np): Add LLL_PRIVATE + as second argument to lll_{,un}lock macros on pd->lock. + * pthread_getschedparam.c (__pthread_getschedparam): Likewise. + * pthread_setschedparam.c (__pthread_setschedparam): Likewise. + * pthread_setschedprio.c (pthread_setschedprio): Likewise. + * tpp.c (__pthread_tpp_change_priority, __pthread_current_priority): + Likewise. + * sysdeps/pthread/createthread.c (do_clone, create_thread): + Likewise. + * pthread_once.c (once_lock): Change type to int. + (__pthread_once): Pass LLL_PRIVATE as second argument to + lll_{,un}lock macros on once_lock. + * pthread_rwlock_rdlock.c (__pthread_rwlock_rdlock): Use + lll_{,un}lock macros instead of lll_mutex_{,un}lock, pass + rwlock->__data.__shared as second argument to them and similarly + for lll_futex_w*. + * pthread_rwlock_timedrdlock.c (pthread_rwlock_timedrdlock): + Likewise. + * pthread_rwlock_timedwrlock.c (pthread_rwlock_timedwrlock): + Likewise. + * pthread_rwlock_tryrdlock.c (__pthread_rwlock_tryrdlock): Likewise. + * pthread_rwlock_trywrlock.c (__pthread_rwlock_trywrlock): Likewise. + * pthread_rwlock_unlock.c (__pthread_rwlock_unlock): Likewise. + * pthread_rwlock_wrlock.c (__pthread_rwlock_wrlock): Likewise. + * sem_close.c (sem_close): Pass LLL_PRIVATE as second argument + to lll_{,un}lock macros on __sem_mappings_lock. + * sem_open.c (check_add_mapping): Likewise. + (__sem_mappings_lock): Change type to int. + * semaphoreP.h (__sem_mappings_lock): Likewise. + * pthread_mutex_lock.c (LLL_MUTEX_LOCK, LLL_MUTEX_TRYLOCK, + LLL_ROBUST_MUTEX_LOCK): Use lll_{,try,robust_}lock macros + instead of lll_*mutex_*, pass LLL_SHARED as last + argument. + (__pthread_mutex_lock): Use lll_unlock instead of lll_mutex_unlock, + pass LLL_SHARED as last argument. + * sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c (LLL_MUTEX_LOCK, + LLL_MUTEX_TRYLOCK, LLL_ROBUST_MUTEX_LOCK): Use + lll_{cond_,cond_try,robust_cond}lock macros instead of lll_*mutex_*, + pass LLL_SHARED as last argument. + * pthread_mutex_timedlock.c (pthread_mutex_timedlock): Use + lll_{timed,try,robust_timed,un}lock instead of lll_*mutex*, pass + LLL_SHARED as last argument. + * pthread_mutex_trylock.c (__pthread_mutex_trylock): Similarly. + * pthread_mutex_unlock.c (__pthread_mutex_unlock_usercnt): + Similarly. + * sysdeps/pthread/bits/libc-lock.h (__libc_lock_lock, + __libc_lock_lock_recursive, __libc_lock_unlock, + __libc_lock_unlock_recursive): Pass LLL_PRIVATE as second + argument to lll_{,un}lock. + * sysdeps/pthread/bits/stdio-lock.h (_IO_lock_lock, + _IO_lock_unlock): Likewise. + * sysdeps/unix/sysv/linux/fork.c (__libc_fork): Don't use + compound literal. + * sysdeps/unix/sysv/linux/unregister-atfork.c (__unregister_atfork): + Pass LLL_PRIVATE as second argument to lll_{,un}lock macros on + __fork_lock. + * sysdeps/unix/sysv/linux/register-atfork.c (__register_atfork, + free_mem): Likewise. + (__fork_lock): Change type to int. + * sysdeps/unix/sysv/linux/fork.h (__fork_lock): Likewise. + * sysdeps/unix/sysv/linux/sem_post.c (__new_sem_post): Pass + isem->private ^ FUTEX_PRIVATE_FLAG as second argument to + lll_futex_wake. + * sysdeps/unix/sysv/linux/sem_timedwait.c (sem_timedwait): Likewise. + * sysdeps/unix/sysv/linux/sem_wait.c (__new_sem_wait): Likewise. + * sysdeps/unix/sysv/linux/lowlevellock.c (__lll_lock_wait_private): + New function. + (__lll_lock_wait, __lll_timedlock_wait): Add private argument and + pass it through to lll_futex_*wait, only compile in when + IS_IN_libpthread. + * sysdeps/unix/sysv/linux/lowlevelrobustlock.c + (__lll_robust_lock_wait, __lll_robust_timedlock_wait): Add private + argument and pass it through to lll_futex_*wait. + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h: Renamed all + lll_mutex_* resp. lll_robust_mutex_* macros to lll_* resp. + lll_robust_*. Renamed all __lll_mutex_* resp. __lll_robust_mutex_* + inline functions to __lll_* resp. __lll_robust_*. + (LLL_MUTEX_LOCK_INITIALIZER): Remove. + (lll_mutex_dead): Add private argument. + (__lll_lock_wait_private): New prototype. + (__lll_lock_wait, __lll_robust_lock_wait, __lll_lock_timedwait, + __lll_robust_lock_timedwait): Add private argument to prototypes. + (__lll_lock): Add private argument, if it is constant LLL_PRIVATE, + call __lll_lock_wait_private, otherwise pass private to + __lll_lock_wait. + (__lll_robust_lock, __lll_cond_lock, __lll_timedlock, + __lll_robust_timedlock): Add private argument, pass it to + __lll_*wait functions. + (__lll_unlock): Add private argument, if it is constant LLL_PRIVATE, + call __lll_unlock_wake_private, otherwise pass private to + __lll_unlock_wake. + (__lll_robust_unlock): Add private argument, pass it to + __lll_robust_unlock_wake. + (lll_lock, lll_robust_lock, lll_cond_lock, lll_timedlock, + lll_robust_timedlock, lll_unlock, lll_robust_unlock): Add private + argument, pass it through to __lll_* inline function. + (__lll_mutex_unlock_force, lll_mutex_unlock_force): Remove. + (lll_lock_t): Remove. + (__lll_cond_wait, __lll_cond_timedwait, __lll_cond_wake, + __lll_cond_broadcast, lll_cond_wait, lll_cond_timedwait, + lll_cond_wake, lll_cond_broadcast): Remove. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Allow including + the header from assembler. Renamed all lll_mutex_* resp. + lll_robust_mutex_* macros to lll_* resp. lll_robust_*. + (LOCK, FUTEX_CMP_REQUEUE, FUTEX_WAKE_OP, + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define. + (LLL_MUTEX_LOCK_INITIALIZER, LLL_MUTEX_LOCK_INITIALIZER_LOCKED, + LLL_MUTEX_LOCK_INITIALIZER_WAITERS): Remove. + (__lll_mutex_lock_wait, __lll_mutex_timedlock_wait, + __lll_mutex_unlock_wake, __lll_lock_wait, __lll_unlock_wake): + Remove prototype. + (__lll_trylock_asm, __lll_lock_asm_start, __lll_unlock_asm): Define. + (lll_robust_trylock, lll_cond_trylock): Use LLL_LOCK_INITIALIZER* + rather than LLL_MUTEX_LOCK_INITIALIZER* macros. + (lll_trylock): Likewise, use __lll_trylock_asm, pass + MULTIPLE_THREADS_OFFSET as another asm operand. + (lll_lock): Add private argument, use __lll_lock_asm_start, pass + MULTIPLE_THREADS_OFFSET as last asm operand, call + __lll_lock_wait_private if private is constant LLL_PRIVATE, + otherwise pass private as another argument to __lll_lock_wait. + (lll_robust_lock, lll_cond_lock, lll_robust_cond_lock, + lll_timedlock, lll_robust_timedlock): Add private argument, pass + private as another argument to __lll_*lock_wait call. + (lll_unlock): Add private argument, use __lll_unlock_asm, pass + MULTIPLE_THREADS_OFFSET as another asm operand, call + __lll_unlock_wake_private if private is constant LLL_PRIVATE, + otherwise pass private as another argument to __lll_unlock_wake. + (lll_robust_unlock): Add private argument, pass private as another + argument to __lll_unlock_wake. + (lll_robust_dead): Add private argument, use __lll_private_flag + macro. + (lll_islocked): Use LLL_LOCK_INITIALIZER instead of + LLL_MUTEX_LOCK_INITIALIZER. + (lll_lock_t): Remove. + (LLL_LOCK_INITIALIZER_WAITERS): Define. + (__lll_cond_wait, __lll_cond_timedwait, __lll_cond_wake, + __lll_cond_broadcast, lll_cond_wait, lll_cond_timedwait, + lll_cond_wake, lll_cond_broadcast): Remove. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Revert + 2007-05-2{3,9} changes. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Include + kernel-features.h and lowlevellock.h. + (LOAD_PRIVATE_FUTEX_WAIT): Define. + (LOAD_FUTEX_WAIT): Rewritten. + (LOCK, SYS_gettimeofday, SYS_futex, FUTEX_WAIT, FUTEX_WAKE): Don't + define. + (__lll_lock_wait_private, __lll_unlock_wake_private): New functions. + (__lll_mutex_lock_wait): Rename to ... + (__lll_lock_wait): ... this. Take futex addr from %edx instead of + %ecx, %ecx is now private argument. Don't compile in for libc.so. + (__lll_mutex_timedlock_wait): Rename to ... + (__lll_timedlock_wait): ... this. Use __NR_gettimeofday. %esi + contains private argument. Don't compile in for libc.so. + (__lll_mutex_unlock_wake): Rename to ... + (__lll_unlock_wake): ... this. %ecx contains private argument. + Don't compile in for libc.so. + (__lll_timedwait_tid): Use __NR_gettimeofday. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S: Include + kernel-features.h and lowlevellock.h. + (LOAD_FUTEX_WAIT): Define. + (LOCK, SYS_gettimeofday, SYS_futex, FUTEX_WAIT, FUTEX_WAKE): Don't + define. + (__lll_robust_mutex_lock_wait): Rename to ... + (__lll_robust_lock_wait): ... this. Futex addr is now in %edx + argument, %ecx argument contains private. Use LOAD_FUTEX_WAIT + macro. + (__lll_robust_mutex_timedlock_wait): Rename to ... + (__lll_robust_timedlock_wait): ... this. Use __NR_gettimeofday. + %esi argument contains private, use LOAD_FUTEX_WAIT macro. + * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: Include + lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, LOCK): Don't define. + (pthread_barrier_wait): Rename __lll_mutex_* to __lll_*, pass + PRIVATE(%ebx) ^ LLL_SHARED as private argument in %ecx to + __lll_lock_wait and __lll_unlock_wake, pass MUTEX(%ebx) address + to __lll_lock_wait in %edx. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: + Include lowlevellock.h and pthread-errnos.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE, + FUTEX_CMP_REQUEUE, EINVAL, LOCK): Don't define. + (__pthread_cond_broadcast): Rename __lll_mutex_* to __lll_*, pass + cond_lock address in %edx rather than %ecx to __lll_lock_wait, + pass LLL_SHARED in %ecx to both __lll_lock_wait and + __lll_unlock_wake. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: + Include lowlevellock.h and pthread-errnos.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_WAKE_OP, + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, EINVAL, LOCK): Don't define. + (__pthread_cond_signal): Rename __lll_mutex_* to __lll_*, pass + cond_lock address in %edx rather than %ecx to __lll_lock_wait, + pass LLL_SHARED in %ecx to both __lll_lock_wait and + __lll_unlock_wake. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: + Include lowlevellock.h. + (SYS_futex, SYS_gettimeofday, FUTEX_WAIT, FUTEX_WAKE, LOCK): + Don't define. + (__pthread_cond_timedwait): Rename __lll_mutex_* to __lll_*, pass + cond_lock address in %edx rather than %ecx to __lll_lock_wait, + pass LLL_SHARED in %ecx to both __lll_lock_wait and + __lll_unlock_wake. Use __NR_gettimeofday. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: + Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, LOCK): Don't define. + (__pthread_cond_wait, __condvar_w_cleanup): Rename __lll_mutex_* + to __lll_*, pass cond_lock address in %edx rather than %ecx to + __lll_lock_wait, pass LLL_SHARED in %ecx to both __lll_lock_wait + and __lll_unlock_wake. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: + Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, LOCK): Don't define. + (__pthread_rwlock_rdlock): Rename __lll_mutex_* to __lll_*, pass + MUTEX(%ebx) address in %edx rather than %ecx to + __lll_lock_wait, pass PSHARED(%ebx) in %ecx to both __lll_lock_wait + and __lll_unlock_wake. Move return value from %ecx to %edx + register. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Include lowlevellock.h. + (SYS_futex, SYS_gettimeofday, FUTEX_WAIT, FUTEX_WAKE, LOCK): + Don't define. + (__pthread_rwlock_wrlock): Rename __lll_mutex_* to __lll_*, pass + MUTEX(%ebp) address in %edx rather than %ecx to + __lll_lock_wait, pass PSHARED(%ebp) in %ecx to both __lll_lock_wait + and __lll_unlock_wake. Move return value from %ecx to %edx + register. Use __NR_gettimeofday. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Include lowlevellock.h. + (SYS_futex, SYS_gettimeofday, FUTEX_WAIT, FUTEX_WAKE, LOCK): + Don't define. + (__pthread_rwlock_wrlock): Rename __lll_mutex_* to __lll_*, pass + MUTEX(%ebp) address in %edx rather than %ecx to + __lll_lock_wait, pass PSHARED(%ebp) in %ecx to both __lll_lock_wait + and __lll_unlock_wake. Move return value from %ecx to %edx + register. Use __NR_gettimeofday. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: + Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, LOCK): Don't define. + (__pthread_rwlock_unlock): Rename __lll_mutex_* to __lll_*, pass + MUTEX(%edi) address in %edx rather than %ecx to + __lll_lock_wait, pass PSHARED(%edi) in %ecx to both __lll_lock_wait + and __lll_unlock_wake. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: + Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, LOCK): Don't define. + (__pthread_rwlock_wrlock): Rename __lll_mutex_* to __lll_*, pass + MUTEX(%ebx) address in %edx rather than %ecx to + __lll_lock_wait, pass PSHARED(%ebx) in %ecx to both __lll_lock_wait + and __lll_unlock_wake. Move return value from %ecx to %edx + register. + * sysdeps/unix/sysv/linux/i386/pthread_once.S: Include + lowlevellock.h. + (LOCK, SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG): Don't + define. + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Include lowlevellock.h. + (LOCK, SYS_futex, FUTEX_WAKE): Don't define. + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Include + lowlevellock.h. + (LOCK, SYS_futex, SYS_gettimeofday, FUTEX_WAIT): Don't define. + (sem_timedwait): Use __NR_gettimeofday. + * sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S: Include + lowlevellock.h. + (LOCK): Don't define. + * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Include + lowlevellock.h. + (LOCK, SYS_futex, FUTEX_WAIT): Don't define. + * sysdeps/unix/sysv/linux/powerpc/sem_post.c: Wake only when there + are waiters. + * sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S: Revert + 2007-05-2{3,9} changes. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Include + kernel-features.h and lowlevellock.h. + (LOAD_PRIVATE_FUTEX_WAIT): Define. + (LOAD_FUTEX_WAIT): Rewritten. + (LOCK, SYS_futex, FUTEX_WAIT, FUTEX_WAKE): Don't define. + (__lll_lock_wait_private, __lll_unlock_wake_private): New functions. + (__lll_mutex_lock_wait): Rename to ... + (__lll_lock_wait): ... this. %esi is now private argument. + Don't compile in for libc.so. + (__lll_mutex_timedlock_wait): Rename to ... + (__lll_timedlock_wait): ... this. %esi contains private argument. + Don't compile in for libc.so. + (__lll_mutex_unlock_wake): Rename to ... + (__lll_unlock_wake): ... this. %esi contains private argument. + Don't compile in for libc.so. + * sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S: Include + kernel-features.h and lowlevellock.h. + (LOAD_FUTEX_WAIT): Define. + (LOCK, SYS_futex, FUTEX_WAIT, FUTEX_WAKE): Don't define. + (__lll_robust_mutex_lock_wait): Rename to ... + (__lll_robust_lock_wait): ... this. %esi argument contains private. + Use LOAD_FUTEX_WAIT macro. + (__lll_robust_mutex_timedlock_wait): Rename to ... + (__lll_robust_timedlock_wait): ... this. %esi argument contains + private, use LOAD_FUTEX_WAIT macro. + * sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S: Include + lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, LOCK): Don't define. + (pthread_barrier_wait): Rename __lll_mutex_* to __lll_*, pass + PRIVATE(%rdi) ^ LLL_SHARED as private argument in %esi to + __lll_lock_wait and __lll_unlock_wake. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: + Include lowlevellock.h and pthread-errnos.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE, + FUTEX_CMP_REQUEUE, EINVAL, LOCK): Don't define. + (__pthread_cond_broadcast): Rename __lll_mutex_* to __lll_*, + pass LLL_SHARED in %esi to both __lll_lock_wait and + __lll_unlock_wake. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: + Include lowlevellock.h and pthread-errnos.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_WAKE_OP, + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, EINVAL, LOCK): Don't define. + (__pthread_cond_signal): Rename __lll_mutex_* to __lll_*, + pass LLL_SHARED in %esi to both __lll_lock_wait and + __lll_unlock_wake. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: + Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, LOCK): Don't define. + (__pthread_cond_timedwait): Rename __lll_mutex_* to __lll_*, + pass LLL_SHARED in %esi to both __lll_lock_wait and + __lll_unlock_wake. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: + Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, LOCK): Don't define. + (__pthread_cond_wait, __condvar_cleanup): Rename __lll_mutex_* + to __lll_*, pass LLL_SHARED in %esi to both __lll_lock_wait + and __lll_unlock_wake. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: + Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG, LOCK): + Don't define. + (__pthread_rwlock_rdlock): Rename __lll_mutex_* to __lll_*, + pass PSHARED(%rdi) in %esi to both __lll_lock_wait + and __lll_unlock_wake. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S: + Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG, LOCK): + Don't define. + (__pthread_rwlock_wrlock): Rename __lll_mutex_* to __lll_*, + pass PSHARED(%rdi) in %esi to both __lll_lock_wait + and __lll_unlock_wake. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S: + Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG, LOCK): + Don't define. + (__pthread_rwlock_wrlock): Rename __lll_mutex_* to __lll_*, + pass PSHARED(%rdi) in %esi to both __lll_lock_wait + and __lll_unlock_wake. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S: + Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG, LOCK): + Don't define. + (__pthread_rwlock_unlock): Rename __lll_mutex_* to __lll_*, + pass PSHARED(%rdi) in %esi to both __lll_lock_wait + and __lll_unlock_wake. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: + Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG, LOCK): + Don't define. + (__pthread_rwlock_wrlock): Rename __lll_mutex_* to __lll_*, + pass PSHARED(%rdi) in %ecx to both __lll_lock_wait + and __lll_unlock_wake. + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Include + lowlevellock.h. + (LOCK, SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG): Don't + define. + * sysdeps/unix/sysv/linux/x86_64/sem_post.S: Include lowlevellock.h. + (LOCK, SYS_futex, FUTEX_WAKE): Don't define. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Include + lowlevellock.h. + (LOCK, SYS_futex, FUTEX_WAIT): Don't define. + * sysdeps/unix/sysv/linux/x86_64/sem_trywait.S: Include + lowlevellock.h. + (LOCK): Don't define. + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Include + lowlevellock.h. + (LOCK, SYS_futex, FUTEX_WAIT): Don't define. + * sysdeps/unix/sysv/linux/sparc/internaltypes.h: New file. + * sysdeps/unix/sysv/linux/sparc/pthread_barrier_destroy.c: New file. + * sysdeps/unix/sysv/linux/sparc/pthread_barrier_init.c: New file. + * sysdeps/unix/sysv/linux/sparc/pthread_barrier_wait.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c + (__lll_lock_wait_private): New function. + (__lll_lock_wait, __lll_timedlock_wait): Add private argument, pass + it to lll_futex_*wait. Don't compile in for libc.so. + * sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_init.c: + Remove. + * sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c + (struct sparc_pthread_barrier): Remove. + (pthread_barrier_wait): Use union sparc_pthread_barrier instead of + struct sparc_pthread_barrier. Pass + ibarrier->s.pshared ? LLL_SHARED : LLL_PRIVATE to lll_{,un}lock + and lll_futex_wait macros. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_init.c: + Remove. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c: + Include sparc pthread_barrier_wait.c instead of generic one. + +2007-07-30 Jakub Jelinek <jakub@redhat.com> + + * tst-rwlock14.c (do_test): Avoid warnings on 32-bit arches. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S + (pthread_rwlock_timedrdlock): Copy futex retval to %esi rather than + %ecx. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S + (pthread_rwlock_timedwrlock): Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S + (__pthread_rwlock_unlock): Fix MUTEX != 0 args to __lll_*. + +2007-07-31 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/sparc/tls.h (tcbhead_t): Add private_futex field. + +2007-07-26 Jakub Jelinek <jakub@redhat.com> + + * tst-locale2.c (useless): Add return statement. + +2007-07-24 Jakub Jelinek <jakub@redhat.com> + + * allocatestack.c (__nptl_setxid, __wait_lookup_done): Replace + lll_private_futex_* (*) with lll_futex_* (*, LLL_PRIVATE). + * pthread_create.c (start_thread): Likewise. + * init.c (sighandler_setxid): Likewise. + * sysdeps/alpha/tls.h (THREAD_GSCOPE_RESET_FLAG): Likewise. + * sysdeps/ia64/tls.h (THREAD_GSCOPE_RESET_FLAG): Likewise. + * sysdeps/i386/tls.h (THREAD_GSCOPE_RESET_FLAG): Likewise. + * sysdeps/s390/tls.h (THREAD_GSCOPE_RESET_FLAG): Likewise. + * sysdeps/powerpc/tls.h (THREAD_GSCOPE_RESET_FLAG): Likewise. + * sysdeps/x86_64/tls.h (THREAD_GSCOPE_RESET_FLAG): Likewise. + * sysdeps/sparc/tls.h (THREAD_GSCOPE_RESET_FLAG): Likewise. + * sysdeps/sh/tls.h (THREAD_GSCOPE_RESET_FLAG): Likewise. + * sysdeps/pthread/aio_misc.h (AIO_MISC_NOTIFY, AIO_MISC_WAIT): + Likewise. + * sysdeps/pthread/gai_misc.h (GAI_MISC_NOTIFY, GAI_MISC_WAIT): + Likewise. + * sysdeps/unix/sysv/linux/unregister-atfork.c (__unregister_atfork): + Likewise. + * sysdeps/unix/sysv/linux/rtld-lowlevel.h (__rtld_waitzero, + __rtld_notify): Likewise. + * sysdeps/unix/sysv/linux/fork.c (__libc_fork): Likewise. + * sysdeps/unix/sysv/linux/powerpc/pthread_once.c (clear_once_control, + __pthread_once): Likewise. + * sysdeps/unix/sysv/linux/alpha/pthread_once.c (clear_once_control, + __pthread_once): Add LLL_PRIVATE as last argument to lll_futex_*. + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h (FUTEX_PRIVATE_FLAG, + LLL_PRIVATE, LLL_SHARED, __lll_private_flag): Define. + (lll_futex_wait): Add private argument, define as wrapper around + lll_futex_timed_wait. + (lll_futex_timed_wait, lll_futex_wake): Add private argument, + use __lll_private_flag macro. + (lll_robust_mutex_dead, __lll_mutex_unlock, __lll_robust_mutex_unlock, + __lll_mutex_unlock_force): Pass LLL_SHARED as last arg to lll_futex_*. + * sysdeps/unix/sysv/linux/ia64/pthread_once.c (clear_once_control, + __pthread_once): Add LLL_PRIVATE as last argument to lll_futex_*. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (FUTEX_PRIVATE_FLAG, + LLL_PRIVATE, LLL_SHARED, __lll_private_flag): Define. + (lll_futex_wait): Add private argument, define as wrapper around + lll_futex_timed_wait. + (lll_futex_timed_wait, lll_futex_wake): Add private argument, + use __lll_private_flag macro. + (__lll_mutex_unlock, __lll_robust_mutex_unlock, lll_wait_tid, + __lll_mutex_unlock_force): Pass LLL_SHARED as last arg to lll_futex_*. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h (__lll_private_flag): + Define. + (lll_futex_timed_wait, lll_futex_wake): Use it. + (lll_private_futex_wait, lll_private_futex_timed_wait, + lll_private_futex_wake): Removed. + * sysdeps/unix/sysv/linux/s390/pthread_once.c (clear_once_control, + __pthread_once): Add LLL_PRIVATE as last argument to lll_futex_*. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h (FUTEX_PRIVATE_FLAG, + LLL_PRIVATE, LLL_SHARED, __lll_private_flag): Define. + (lll_futex_wait): Add private argument, define as wrapper around + lll_futex_timed_wait. + (lll_futex_timed_wait, lll_futex_wake): Add private argument, + use __lll_private_flag macro. + (lll_robust_mutex_dead, __lll_mutex_unlock, __lll_robust_mutex_unlock, + lll_wait_tid, __lll_mutex_unlock_force): Pass LLL_SHARED as last arg + to lll_futex_*. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h + (lll_private_futex_wait, lll_private_futex_timed_wait, + lll_private_futex_wake): Removed. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (__lll_private_flag): + Fix !__ASSUME_PRIVATE_FUTEX non-constant private case. + (lll_private_futex_wait, lll_private_futex_timed_wait, + lll_private_futex_wake): Removed. + * sysdeps/unix/sysv/linux/sparc/pthread_once.c (clear_once_control, + __pthread_once): Add LLL_PRIVATE as last argument to lll_futex_*. + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h (FUTEX_PRIVATE_FLAG, + LLL_PRIVATE, LLL_SHARED, __lll_private_flag): Define. + (lll_futex_wait): Add private argument, define as wrapper around + lll_futex_timed_wait. + (lll_futex_timed_wait, lll_futex_wake): Add private argument, + use __lll_private_flag macro. + (lll_robust_mutex_dead, __lll_mutex_unlock, __lll_robust_mutex_unlock, + lll_wait_tid, __lll_mutex_unlock_force): Pass LLL_SHARED as last arg + to lll_futex_*. + * sysdeps/unix/sysv/linux/sh/lowlevellock.h (__lll_private_flag): + Define. + (lll_futex_timed_wait, lll_futex_wake): Use it. + (lll_private_futex_wait, lll_private_futex_timed_wait, + lll_private_futex_wake): Removed. + +2007-07-27 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/sparc/tls.h (tcbhead_t): Move gscope_flag to the end + of the structure for sparc32. + +2007-07-26 Aurelien Jarno <aurelien@aurel32.net> + + * sysdeps/sparc/tls.h (tcbhead_t): Add gscope_flag. + +2007-07-23 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S: Fix + code used when private futexes are assumed. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S: + Likewise. + +2007-07-23 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h + (__lll_private_flag): Define. + (lll_futex_wait): Define as a wrapper around lll_futex_timed_wait. + (lll_futex_timed_wait, lll_futex_wake, lll_futex_wake_unlock): Use + __lll_private_flag. + (lll_private_futex_wait, lll_private_futex_timedwait, + lll_private_futex_wake): Define as wrapper around non-_private + macros. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h + (__lll_private_flag): Define. + (lll_futex_timed_wait, lll_futex_wake): Use __lll_private_flag. + (lll_private_futex_wait, lll_private_futex_timedwait, + lll_private_futex_wake): Define as wrapper around non-_private + macros. + +2007-07-10 Steven Munroe <sjmunroe@us.ibm.com> + + * pthread_rwlock_rdlock.c (__pthread_rwlock_rdlock): Add LLL_SHARED + parameter to lll_futex_wait call. + * pthread_rwlock_wrlock.c (__pthread_rwlock_wrlock): Likewise. + + * sysdeps/unix/sysv/linux/powerpc/pthread_once.c (__pthread_once): + Replace lll_futex_wait with lll_private_futex_wait. + * sysdeps/unix/sysv/linux/powerpc/sem_post.c (__new_sem_post): + Add LLL_SHARED parameter to lll_futex_wake(). + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Define LLL_PRIVATE + LLL_SHARED, lll_private_futex_wait, lll_private_futex_timed_wait and + lll_private_futex_wake. + (lll_futex_wait): Add private parameter. Adjust FUTEX_PRIVATE_FLAG + bit from private parm before syscall. + (lll_futex_timed_wait): Likewise. + (lll_futex_wake): Likewise. + (lll_futex_wake_unlock): Likewise. + (lll_mutex_unlock): Add LLL_SHARED parm to lll_futex_wake call. + (lll_robust_mutex_unlock): Likewise. + (lll_mutex_unlock_force): Likewise. + (lll_wait_tid): Add LLL_SHARED parm to lll_futex_wait call. + +2007-07-23 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S: Fix + compilation when unconditionally using private futexes. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: Likewise. + +2007-07-17 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/bits/stdio-lock.h (_IO_acquire_lock_clear_flags2): + Define. + +2007-07-06 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/sh/tls.h: Include stdlib.h, list.h, sysdep.h and + kernel-features.h. + +2007-05-16 Roland McGrath <roland@redhat.com> + + * init.c (__nptl_initial_report_events): New variable. + (__pthread_initialize_minimal_internal): Initialize pd->report_events + to that. + +2007-06-22 Jakub Jelinek <jakub@redhat.com> + + * pthread_getattr_np.c (pthread_getattr_np): Clear cpuset and + cpusetsize if pthread_getaffinity_np failed with ENOSYS. + +2007-06-19 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/rtld-lowlevel.h: Remove mrlock + implementation. + +2007-06-18 Ulrich Drepper <drepper@redhat.com> + + * pthreadP.h: Define PTHREAD_MUTEX_TYPE. + * phtread_mutex_lock.c: Use PTHREAD_MUTEX_TYPE. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_trylock.c: Likewise. + * pthread_mutex_unlock.c: Likewise. + +2007-06-17 Andreas Schwab <schwab@suse.de> + + * sysdeps/pthread/pt-initfini.c: Tell gcc about the nonstandard + sections. + +2007-06-17 Ulrich Drepper <drepper@redhat.com> + + * allocatestack.c (allocate_stack): Make code compile if + __ASSUME_PRIVATE_FUTEX is set. + +2007-06-17 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: + (__pthread_rwlock_rdlock): Don't use non SH-3/4 instruction. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: + (__pthread_rwlock_wrlock): Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: + (pthread_rwlock_timedrdlock): Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: + (pthread_rwlock_timedwrlock): Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S: + (__pthread_rwlock_unlock): Likewise. + +2007-06-10 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/sh/tcb-offsets.sym: Add PRIVATE_FUTEX. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Include endian.h. + Split __flags into __flags, __shared, __pad1 and __pad2. + * sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S: Use private + futexes if they are available. + * sysdeps/unix/sysv/linux/sh/lowlevellock.S: Adjust so that change + in libc-lowlevellock.S allow using private futexes. + * sysdeps/unix/sysv/linux/sh/lowlevellock.h: Define + FUTEX_PRIVATE_FLAG. Add additional parameter to lll_futex_wait, + lll_futex_timed_wait and lll_futex_wake. Change lll_futex_wait + to call lll_futex_timed_wait. Add lll_private_futex_wait, + lll_private_futex_timed_wait and lll_private_futex_wake. + (lll_robust_mutex_unlock): Fix typo. + * sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S: Use private + field in futex command setup. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Use + COND_NWAITERS_SHIFT instead of COND_CLOCK_BITS. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_once.S: Use private futexes + if they are available. Remove clear_once_control. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: Use private + futexes if they are available. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/sem_post.S: Add private futex support. + Wake only when there are waiters. + * sysdeps/unix/sysv/linux/sh/sem_wait.S: Add private futex + support. Indicate that there are waiters. Remove unnecessary + extra cancellation test. + * sysdeps/unix/sysv/linux/sh/sem_timedwait.S: Likewise. Removed + left-over duplication of __sem_wait_cleanup. + +2007-06-07 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Add additional + parameter to lll_futex_wait, lll_futex_timed_wait, and + lll_futex_wake. Change lll_futex_wait to call lll_futex_timed_wait. + Add lll_private_futex_wait, lll_private_futex_timed_wait, and + lll_private_futex_wake. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Likewise. + * allocatestack.c: Adjust use of lll_futex_* macros. + * init.c: Likewise. + * lowlevellock.h: Likewise. + * pthread_barrier_wait.c: Likewise. + * pthread_cond_broadcast.c: Likewise. + * pthread_cond_destroy.c: Likewise. + * pthread_cond_signal.c: Likewise. + * pthread_cond_timedwait.c: Likewise. + * pthread_cond_wait.c: Likewise. + * pthread_create.c: Likewise. + * pthread_mutex_lock.c: Likewise. + * pthread_mutex_setprioceiling.c: Likewise. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_unlock.c: Likewise. + * pthread_rwlock_timedrdlock.c: Likewise. + * pthread_rwlock_timedwrlock.c: Likewise. + * pthread_rwlock_unlock.c: Likewise. + * sysdeps/alpha/tls.h: Likewise. + * sysdeps/i386/tls.h: Likewise. + * sysdeps/ia64/tls.h: Likewise. + * sysdeps/powerpc/tls.h: Likewise. + * sysdeps/pthread/aio_misc.h: Likewise. + * sysdeps/pthread/gai_misc.h: Likewise. + * sysdeps/s390/tls.h: Likewise. + * sysdeps/sh/tls.h: Likewise. + * sysdeps/sparc/tls.h: Likewise. + * sysdeps/unix/sysv/linux/fork.c: Likewise. + * sysdeps/unix/sysv/linux/lowlevellock.c: Likewise. + * sysdeps/unix/sysv/linux/lowlevelrobustlock.c: Likewise. + * sysdeps/unix/sysv/linux/rtld-lowlevel.h: Likewise. + * sysdeps/unix/sysv/linux/sem_post.c: Likewise. + * sysdeps/unix/sysv/linux/sem_timedwait.c: Likewise. + * sysdeps/unix/sysv/linux/sem_wait.c: Likewise. + * sysdeps/unix/sysv/linux/unregister-atfork.c: Likewise. + * sysdeps/unix/sysv/linux/sparc/pthread_once.c: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c: + Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c: Likewise. + * sysdeps/x86_64/tls.h: Likewise. + +2007-05-29 Ulrich Drepper <drepper@redhat.com> + + * pthread_getattr_np.c: No need to install a cancellation handler, + this is no cancellation point. + * pthread_getschedparam.c: Likewise. + * pthread_setschedparam.c: Likewise. + * pthread_setschedprio.c: Likewise. + * sysdeps/unix/sysv/linux/lowlevellock.c: Remove all traces of + lll_unlock_wake_cb. + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/sh/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c: Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. + + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Checking + whether there are more than one thread makes no sense here since + we only call the slow path if the locks are taken. + * sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S: Likewise. + + * sysdeps/unix/sysv/linux/internaltypes.h: Introduce + COND_NWAITERS_SHIFT. + * pthread_cond_destroy.c: Use COND_NWAITERS_SHIFT instead of + COND_CLOCK_BITS. + * pthread_cond_init.c: Likewise. + * pthread_cond_timedwait.c: Likewise. + * pthread_cond_wait.c: Likewise. + * pthread_condattr_getclock.c: Likewise. + * pthread_condattr_setclock.c: Likewise. + * sysdeps/unix/sysv/linux/lowlevelcond.sym: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + +2007-05-28 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstacksize.c: Include + unistd.h. + + * 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 <rth@redhat.com> + + * 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-27 Ulrich Drepper <drepper@redhat.com> + + * init.c: Make it compile with older kernel headers. + + * tst-initializers1.c: Show through exit code which test failed. + + * pthread_rwlock_init.c: Also initialize __shared field. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Split __flags + element in rwlock structure into four byte elements. One of them is + the new __shared element. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h [__WORDSIZE=32]: + Likewise. + [__WORDSIZE=64]: Renamed __pad1 element int rwlock structure to + __shared, adjust names of other padding elements. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/pthread/pthread.h: Adjust rwlock initializers. + * sysdeps/unix/sysv/linux/lowlevelrwlock.sym: Add PSHARED. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Define + FUTEX_PRIVATE_FLAG. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: Change main + futex to use private operations if possible. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. + +2007-05-26 Ulrich Drepper <drepper@redhat.com> + + * pthreadP.h (PTHREAD_RWLOCK_PREFER_READER_P): Define. + * pthread_rwlock_rdlock.c: Use PTHREAD_RWLOCK_PREFER_READER_P. + * pthread_rwlock_timedrdlock.c: Likewise. + * pthread_rwlock_tryrdlock.c: Likewise. + + * sysdeps/unix/sysv/linux/x86_64/sem_trywait.S (sem_trywait): Tiny + optimization. + + * sysdeps/unix/sysv/linux/sem_wait.c: Add missing break. + * sysdeps/unix/sysv/linux/sem_timedwait.c: Removed left-over + duplication of __sem_wait_cleanup. + + * allocatestack.c: Revert last change. + * init.c: Likewise. + * sysdeps/i386/tls.h: Likewise. + * sysdeps/x86_64/tls.h: Likewise. + * descr.h [TLS_DTV_AT_TP] (struct pthread): Add private_futex field to + header structure. + * sysdeps/powerpc/tcb-offsets.sym: Add PRIVATE_FUTEX_OFFSET. + + * sysdeps/unix/sysv/linux/internaltypes.h (struct pthread_barrier): + Add private field. + * sysdeps/unix/sysv/linux/lowlevelbarrier.sym: Add PRIVATE definition. + * pthread_barrier_init.c: Set private flag if pshared and private + futexes are supported. + * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: Use + private field in futex command setup. + * sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S: Likewise. + +2007-05-25 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Add private futex + support. + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_post.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise. + + * semaphoreP.h: Declare __old_sem_init and __old_sem_wait. + * sem_init.c (__new_sem_init): Rewrite to initialize all three + fields in the structure. + (__old_sem_init): New function. + * sem_open.c: Initialize all fields of the structure. + * sem_getvalue.c: Adjust for renamed element. + * sysdeps/unix/sysv/linux/Makefile [subdir=nptl] + (gen-as-const-headers): Add structsem.sym. + * sysdeps/unix/sysv/linux/structsem.sym: New file. + * sysdeps/unix/sysv/linux/internaltypes.h: Rename struct sem to + struct new_sem. Add struct old_sem. + * sysdeps/unix/sysv/linux/sem_post.c: Wake only when there are waiters. + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_post.S: Likewise. + * sysdeps/unix/sysv/linux/sem_wait.c: Indicate that there are waiters. + * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise. + * sysdeps/unix/sysv/linux/sem_timedwait.c: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise. + * Makefile (tests): Add tst-sem10, tst-sem11, tst-sem12. + * tst-sem10.c: New file. + * tst-sem11.c: New file. + * tst-sem12.c: New file. + * tst-typesizes.c: Test struct new_sem and struct old_sem instead + of struct sem. + +2007-05-25 Ulrich Drepper <drepper@redhat.com> + Jakub Jelinek <jakub@redhat.com> + + * 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. + +2007-05-24 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/i386/tls.h (THREAD_SET_PRIVATE_FUTEX, + THREAD_COPY_PRIVATE_FUTEX): Define. + * sysdeps/x86_64/tls.h (THREAD_SET_PRIVATE_FUTEX, + THREAD_COPY_PRIVATE_FUTEX): Define. + * allocatestack.c (allocate_stack): Use THREAD_COPY_PRIVATE_FUTEX. + * init.c (__pthread_initialize_minimal_internal): Use + THREAD_SET_PRIVATE_FUTEX. + + * 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. + +2007-05-23 Ulrich Drepper <drepper@redhat.com> + + * init.c (__pthread_initialize_minimal_internal): Check whether + private futexes are available. + * allocatestack.c (allocate_stack): Copy private_futex field from + current thread into the new stack. + * sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S: Use private + futexes if they are available. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Likewise + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Adjust so that change + in libc-lowlevellock.S allow using private futexes. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Define + FUTEX_PRIVATE_FLAG. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Use private futexes + if they are available. + * sysdeps/unix/sysv/linux/i386/pthread_once.S: Likewise. + * sysdeps/x86_64/tcb-offsets.sym: Add PRIVATE_FUTEX. + * sysdeps/i386/tcb-offsets.sym: Likewise. + * sysdeps/x86_64/tls.h (tcbhead_t): Add private_futex field. + * sysdeps/i386/tls.h (tcbhead_t): Likewise. + +2007-05-21 Ulrich Drepper <drepper@redhat.com> + + * 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-21 Jakub Jelinek <jakub@redhat.com> + + * tst-robust9.c (do_test): Don't fail if ENABLE_PI and + pthread_mutex_init failed with ENOTSUP. + +2007-05-19 Ulrich Drepper <drepper@redhat.com> + + * 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). + +2007-05-17 Ulrich Drepper <drepper@redhat.com> + + [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 <anemo@mba.ocn.ne.jp>. + + * Makefile (tests): Add tst-robust9 and tst-robustpi9. + * tst-robust9.c: New file. + * tst-robustpi9.c: New file. + + * sysdeps/unix/sysv/linux/sem_wait.c (__new_sem_wait): Remove + unnecessary extra cancellation test. + +2007-05-14 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Remove unnecessary + extra cancellation test. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise. + +2007-05-10 Ulrich Drepper <drepper@redhat.com> + + * descr.h (struct pthread): Rearrange members to fill hole in + 64-bit layout. + + * sysdeps/unix/sysv/linux/pthread_setaffinity.c + (__pthread_setaffinity_new): If syscall was successful and + RESET_VGETCPU_CACHE is defined, use it before returning. + * sysdeps/unix/sysv/linux/x86_64/pthread_setaffinity.c: New file. + +2007-05-10 Jakub Jelinek <jakub@redhat.com> + + [BZ #4455] + * tst-align2.c: Include stackinfo.h. + * tst-getpid1.c: Likewise. + +2007-05-02 Carlos O'Donell <carlos@systemhalted.org> + + [BZ #4455] + * tst-align2.c (do_test): Add _STACK_GROWS_UP case. + * tst-getpid1.c (do_test): Likewise. + + [BZ #4456] + * allocatestack.c (change_stack_perm): Add _STACK_GROWS_UP case. + (allocate_stack): Likewise. + +2007-05-07 Ulrich Drepper <drepper@redhat.com> + + * 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 <kuznet@ms2.inr.ac.ru>. + +2007-05-06 Mike Frysinger <vapier@gentoo.org> + + [BZ #4465] + * tst-cancel-wrappers.sh: Set C["fdatasync"] to 1. + * tst-cancel4.c (tf_fdatasync): New test. + +2007-04-27 Ulrich Drepper <drepper@redhat.com> + + [BZ #4392] + * pthread_mutex_trylock.c (__pthread_mutex_trylock): Treat error + check mutexes like normal mutexes. + + [BZ #4306] + * sysdeps/unix/sysv/linux/timer_create.c (timer_create): + Initialize the whole sigevent structure to appease valgrind. + +2007-04-25 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/x86_64/tls.h (tcbhead_t): Add vgetcpu_cache. + * sysdeps/x86_64/tcb-offsets.sym: Add VGETCPU_CACHE_OFFSET. + +2007-04-06 Ulrich Drepper <drepper@redhat.com> + + * tst-locale1.c: Avoid warnings. + * tst-locale2.c: Likewise. + +2007-03-19 Steven Munroe <sjmunroe@us.ibm.com> + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h + (__lll_robust_trylock): Add MUTEX_HINT_ACQ to lwarx instruction. + +2007-03-16 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/bits/libc-lock.h: Use __extern_inline and + __extern_always_inline where appropriate. + * sysdeps/pthread/pthread.h: Likewise. + +2007-03-13 Richard Henderson <rth@redhat.com> + + * sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h (PSEUDO): Use two + separate cfi regions for the two subsections. + +2007-02-25 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/fork.c (__libc_fork): Reset refcntr in + new thread, don't just decrement it. + Patch by Suzuki K P <suzuki@in.ibm.com>. + +2007-02-21 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread-functions.h: Correct last patch, correct + PTHFCT_CALL definition. + +2007-02-18 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread-functions.h: If PTR_DEMANGLE is not + available, don't use it. + +2007-02-09 Jakub Jelinek <jakub@redhat.com> + + * 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. + +2007-01-18 Ulrich Drepper <drepper@redhat.com> + + * tst-initializers1.c: We want to test the initializers as seen + outside of libc, so undefined _LIBC. + + * pthread_join.c (cleanup): Avoid warning. + +2007-01-17 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S + (__lll_timedwait_tid): Add unwind info. + + * sysdeps/unix/sysv/linux/libc_pthread_init.c: Don't just copy the + function table, mangle the pointers. + * sysdeps/pthread/pthread-functions.h: Define PTHFCT_CALL. + * forward.c: Use PTHFCT_CALL and __libc_pthread_functions_init. + * sysdeps/pthread/bits/libc-lock.h: When using __libc_pthread_functions + demangle pointers before use. + * sysdeps/unix/sysv/linux/s390/jmp-unwind.c: Use PTHFCT_CALL to + demangle pointer. + * sysdeps/unix/sysv/linux/jmp-unwind.c: Likewise. + * sysdeps/pthread/setxid.h: Likewise. + +2007-01-12 Ulrich Drepper <drepper@redhat.com> + + * tst-rwlock7.c: Show some more information in case of correct + behavior. + +2007-01-11 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h + (lll_futex_timed_wait): Undo part of last change, don't negate + return value. + +2007-01-10 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Cleanups. Define + FUTEX_CMP_REQUEUE and lll_futex_requeue. + +2006-12-28 David S. Miller <davem@davemloft.net> + + * shlib-versions: Fix sparc64 linux target specification. + +2007-01-10 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c: + Adjust include path for pthread_barrier_wait.c move. + +2006-12-21 Jakub Jelinek <jakub@redhat.com> + + * 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-12-06 Jakub Jelinek <jakub@redhat.com> + + * 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. + +2006-12-09 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/rtld-lowlevel.h + (__rtld_mrlock_initialize): Add missing closing parenthesis. + +2006-10-30 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/ia64/pthread_spin_unlock.c (pthread_spin_unlock): Use + __sync_lock_release instead of __sync_lock_release_si. + +2006-10-29 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (RTLD_SINGLE_THREAD_P): + Define. + (SINGLE_THREAD_P): Define to 1 if IS_IN_rtld. + * sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: Likewise. + +2006-10-27 Ulrich Drepper <drepper@redhat.com> + + * 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 <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/rtld-lowlevel.h (__rtld_mrlock_lock, + __rtld_mrlock_change): Update oldval if atomic compare and exchange + failed. + + * sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h (SINGLE_THREAD_P): + Define to THREAD_SELF->header.multiple_threads. + * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (SINGLE_THREAD_P): + Likewise. + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (SINGLE_THREAD_P): + Likewise. + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h + (SINGLE_THREAD_P): Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h + (SINGLE_THREAD_P): Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h + (SINGLE_THREAD_P): Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h + (SINGLE_THREAD_P): Likewise. + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h (SINGLE_THREAD_P): + Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h + (SINGLE_THREAD_P): Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h + (SINGLE_THREAD_P): Likewise. + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h (SINGLE_THREAD_P): + Likewise. + +2006-10-26 Jakub Jelinek <jakub@redhat.com> + + * pthread_attr_setstacksize.c (NEW_VERNUM): Define to GLIBC_2_3_3 + by default rather than 2_3_3. + +2006-10-17 Jakub Jelinek <jakub@redhat.com> + + * 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. + +2006-10-12 Ulrich Drepper <drepper@redhat.com> + + [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. + +2006-10-11 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Add support for + cancelable syscalls with six parameters. + + * sysdeps/unix/sysv/linux/rtld-lowlevel.h: Use catomic_* + operations instead of atomic_*. + +2006-10-09 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/rtld-lowlevel.h: New file.. + +2006-10-07 Ulrich Drepper <drepper@redhat.com> + + * 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. + +2006-09-24 Ulrich Drepper <drepper@redhat.com> + + [BZ #3251] + * descr.h (ENQUEUE_MUTEX_BOTH): Add cast to avoid warning. + Patch by Petr Baudis. + +2006-09-18 Jakub Jelinek <jakub@redhat.com> + + * tst-kill4.c (do_test): Explicitly set tf thread's stack size. + + * tst-cancel2.c (tf): Loop as long as something was written. + +2006-09-12 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S: For PI + mutexes wake all mutexes. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Don't increment + WAKEUP_SEQ if this would increase the value beyond TOTAL_SEQ. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. + +2006-09-12 Ulrich Drepper <drepper@redhat.com> + + * tst-cond22.c (tf): Slight changes to the pthread_cond_wait use + to guarantee the thread is always canceled. + +2006-09-08 Jakub Jelinek <jakub@redhat.com> + + * tst-cond22.c: Include pthread.h instead of pthreadP.h. + Include stdlib.h. + * sysdeps/pthread/pthread_cond_wait.c (__condvar_cleanup): Only + increase FUTEX if increasing WAKEUP_SEQ. Fix comment typo. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + +2006-09-08 Ulrich Drepper <drepper@redhat.com> + + [BZ #3123] + * sysdeps/pthread/pthread_cond_wait.c (__condvar_cleanup): Don't + increment WAKEUP_SEQ if this would increase the value beyond TOTAL_SEQ. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + * Makefile (tests): Add tst-cond22. + * tst-cond22.c: New file. + +2006-09-05 Ulrich Drepper <drepper@redhat.com> + + [BZ #3124] + * descr.h (struct pthread): Add parent_cancelhandling. + * sysdeps/pthread/createthread.c (create_thread): Pass parent + cancelhandling value to child. + * pthread_create.c (start_thread): If parent thread was canceled + reset the SIGCANCEL mask. + * Makefile (tests): Add tst-cancel25. + * tst-cancel25.c: New file. + +2006-09-05 Jakub Jelinek <jakub@redhat.com> + Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/gai_misc.h (GAI_MISC_NOTIFY): Don't decrement + counterp if it is already zero. + * sysdeps/pthread/aio_misc.h (AIO_MISC_NOTIFY): Likewise.. + +2006-03-04 Jakub Jelinek <jakub@redhat.com> + Roland McGrath <roland@redhat.com> + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h + (LLL_STUB_UNWIND_INFO_START, LLL_STUB_UNWIND_INFO_END, + LLL_STUB_UNWIND_INFO_3, LLL_STUB_UNWIND_INFO_4): Define. + (lll_mutex_lock, lll_robust_mutex_lock, lll_mutex_cond_lock, + lll_robust_mutex_cond_lock, lll_mutex_timedlock, + lll_robust_mutex_timedlock, lll_mutex_unlock, + lll_robust_mutex_unlock, lll_lock, lll_unlock): Use them. + Add _L_*_ symbols around the subsection. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Add unwind info. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S: Likewise. + +2006-03-03 Jakub Jelinek <jakub@redhat.com> + Roland McGrath <roland@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h + (LLL_STUB_UNWIND_INFO_START, LLL_STUB_UNWIND_INFO_END, + LLL_STUB_UNWIND_INFO_5, LLL_STUB_UNWIND_INFO_6): Define. + (lll_mutex_lock, lll_robust_mutex_lock, lll_mutex_cond_lock, + lll_robust_mutex_cond_lock, lll_mutex_timedlock, + lll_robust_mutex_timedlock, lll_mutex_unlock, + lll_robust_mutex_unlock, lll_lock, lll_unlock): Use them. + Add _L_*_ symbols around the subsection. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Add unwind info. + * sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S: Likewise. + +2006-08-31 Ulrich Drepper <drepper@redhat.com> + + * pthread_rwlock_trywrlock.c (__pthread_rwlock_trywrlock): Undo last + change because it can disturb too much existing code. If real hard + reader preference is needed we'll introduce another type. + * sysdeps/pthread/pthread_rwlock_timedwrlock.c + (pthread_rwlock_timedwrlock): Likewise. + * sysdeps/pthread/pthread_rwlock_wrlock.c (__pthread_rwlock_wrlock): + Likewise. + +2006-08-30 Ulrich Drepper <drepper@redhat.com> + + * pthread_rwlock_trywrlock.c (__pthread_rwlock_trywrlock): Respect + reader preference. + * sysdeps/pthread/pthread_rwlock_timedwrlock.c + (pthread_rwlock_timedwrlock): Likewise. + * sysdeps/pthread/pthread_rwlock_wrlock.c (__pthread_rwlock_wrlock): + Likewise. + +2006-08-25 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/libc_pthread_init.c (freeres_libpthread): + Only define ifdef SHARED. + +2006-08-23 Ulrich Drepper <drepper@redhat.com> + + * allocatestack.c (queue_stack): Move freeing of surplus stacks to... + (free_stacks): ...here. + (__free_stack_cache): New function. + * pthreadP.h: Declare __free_stack_cache. + * sysdeps/pthread/pthread-functions.h (pthread_functions): Add + ptr_freeres. + * init.c (pthread_functions): Initialize ptr_freeres. + * sysdeps/unix/sysv/linux/libc_pthread_init.c (freeres_libptread): + New freeres function. + +2006-07-30 Joseph S. Myers <joseph@codesourcery.com> + + [BZ #3018] + * Makefile (extra-objs): Add modules to extra-test-objs instead. + +2006-08-20 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Define + _XOPEN_REALTIME_THREADS. + +2006-08-15 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/clock_settime.c (INTERNAL_VSYSCALL): Use + HAVE_CLOCK_GETRES_VSYSCALL as guard macro rather than + HAVE_CLOCK_GETTIME_VSYSCALL. + (maybe_syscall_settime_cpu): Use plain INTERNAL_VSYSCALL here. + +2006-08-14 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/bits/posix_opt.h + (_POSIX_THREAD_PRIO_PROTECT): Define to 200112L. + * descr.h (struct priority_protection_data): New type. + (struct pthread): Add tpp field. + * pthreadP.h (PTHREAD_MUTEX_PP_NORMAL_NP, + PTHREAD_MUTEX_PP_RECURSIVE_NP, PTHREAD_MUTEX_PP_ERRORCHECK_NP, + PTHREAD_MUTEX_PP_ADAPTIVE_NP): New enum values. + * pthread_mutex_init.c (__pthread_mutex_init): Handle non-robust + TPP mutexes. + * pthread_mutex_lock.c (__pthread_mutex_lock): Handle TPP mutexes. + * pthread_mutex_trylock.c (__pthread_mutex_trylock): Likewise. + * pthread_mutex_timedlock.c (pthread_mutex_timedlock): Likewise. + * pthread_mutex_unlock.c (__pthread_mutex_unlock_usercnt): Likewise. + * tpp.c: New file. + * pthread_setschedparam.c (__pthread_setschedparam): Handle priority + boosted by TPP. + * pthread_setschedprio.c (pthread_setschedprio): Likewise. + * pthread_mutexattr_getprioceiling.c + (pthread_mutexattr_getprioceiling): If ceiling is 0, ensure it is + in the SCHED_FIFO priority range. + * pthread_mutexattr_setprioceiling.c + (pthread_mutexattr_setprioceiling): Fix prioceiling validation. + * pthread_mutex_getprioceiling.c (pthread_mutex_getprioceiling): Fail + if mutex is not TPP. Ceiling is now in __data.__lock. + * pthread_mutex_setprioceiling.c: Include stdbool.h. + (pthread_mutex_setprioceiling): Fix prioceiling validation. Ceiling + is now in __data.__lock. Add locking. + * pthread_create.c (__free_tcb): Free pd->tpp structure. + * Makefile (libpthread-routines): Add tpp. + (xtests): Add tst-mutexpp1, tst-mutexpp6 and tst-mutexpp10. + * tst-tpp.h: New file. + * tst-mutexpp1.c: New file. + * tst-mutexpp6.c: New file. + * tst-mutexpp10.c: New file. + * tst-mutex1.c (TEST_FUNCTION): Don't redefine if already defined. + * tst-mutex6.c (TEST_FUNCTION): Likewise. + +2006-08-12 Ulrich Drepper <drepper@redhat.com> + + [BZ #2843] + * pthread_join.c (pthread_join): Account for self being canceled + when checking for deadlocks. + * tst-join5.c: Cleanups. Allow to be used in tst-join6. + (tf1): Don't print anything after pthread_join returns, this would be + another cancellation point. + (tf2): Likewise. + * tst-join6.c: New file. + * Makefile (tests): Add tst-join6. + +2006-08-03 Ulrich Drepper <drepper@redhat.com> + + [BZ #2892] + * pthread_setspecific.c (__pthread_setspecific): Check + out-of-range index before checking for unused key. + + * sysdeps/pthread/gai_misc.h: New file. + +2006-08-01 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/smp.h: New file. Old Linux-specific + file. Don't use sysctl. + * sysdeps/unix/sysv/linux/smp.h: Always assume SMP. Archs can + overwrite the file if this is likely not true. + +2006-07-31 Daniel Jacobowitz <dan@codesourcery.com> + + * allocatestack.c (__reclaim_stacks): Reset the PID on cached stacks. + * Makefile (tests): Add tst-getpid3. + * tst-getpid3.c: New file. + +2006-07-30 Roland McGrath <roland@redhat.com> + + * Makefile (libpthread-routines): Add ptw-sigsuspend. + + * sysdeps/unix/sysv/linux/i386/not-cancel.h + (pause_not_cancel): New macro. + (nanosleep_not_cancel): New macro. + (sigsuspend_not_cancel): New macro. + * pthread_mutex_timedlock.c (pthread_mutex_timedlock): Use + nanosleep_not_cancel macro from <not-cancel.h>. + * pthread_mutex_lock.c (__pthread_mutex_lock): Use pause_not_cancel + macro from <not-cancel.h>. + +2006-07-28 Ulrich Drepper <drepper@redhat.com> + Jakub Jelinek <jakub@redhat.com> + + * descr.h: Change ENQUEUE_MUTEX and DEQUEUE_MUTEX for bit 0 + notification of PI mutex. Add ENQUEUE_MUTEX_PI. + * pthreadP.h: Define PTHREAD_MUTEX_PI_* macros for PI mutex types. + * pthread_mutex_setprioceilining.c: Adjust for mutex type name change. + * pthread_mutex_init.c: Add support for priority inheritance mutex. + * pthread_mutex_lock.c: Likewise. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_trylock.c: Likewise. + * pthread_mutex_unlock.c: Likewise. + * sysdeps/pthread/pthread_cond_broadcast.c: For PI mutexes wake + all mutexes. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.c: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.c: Likewise. + * sysdeps/unix/sysv/linux/pthread-pi-defines.sym: New file. + * sysdeps/unix/sysv/linux/Makefile (gen-as-const-header): Add + pthread-pi-defines.sym. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Define FUTEX_LOCK_PI, + FUTEX_UNLOCK_PI, and FUTEX_TRYLOCK_PI. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/sh/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Define + _POSIX_THREAD_PRIO_INHERIT to 200112L. + * tst-mutex1.c: Adjust to allow use in PI mutex test. + * tst-mutex2.c: Likewise. + * tst-mutex3.c: Likewise. + * tst-mutex4.c: Likewise. + * tst-mutex5.c: Likewise. + * tst-mutex6.c: Likewise. + * tst-mutex7.c: Likewise. + * tst-mutex7a.c: Likewise. + * tst-mutex8.c: Likewise. + * tst-mutex9.c: Likewise. + * tst-robust1.c: Likewise. + * tst-robust7.c: Likewise. + * tst-robust8.c: Likewise. + * tst-mutexpi1.c: New file. + * tst-mutexpi2.c: New file. + * tst-mutexpi3.c: New file. + * tst-mutexpi4.c: New file. + * tst-mutexpi5.c: New file. + * tst-mutexpi6.c: New file. + * tst-mutexpi7.c: New file. + * tst-mutexpi7a.c: New file. + * tst-mutexpi8.c: New file. + * tst-mutexpi9.c: New file. + * tst-robust1.c: New file. + * tst-robust2.c: New file. + * tst-robust3.c: New file. + * tst-robust4.c: New file. + * tst-robust5.c: New file. + * tst-robust6.c: New file. + * tst-robust7.c: New file. + * tst-robust8.c: New file. + * Makefile (tests): Add the new tests. + + * pthread_create.c (start_thread): Add some casts to avoid warnings. + * pthread_mutex_destroy.c: Remove unneeded label. + +2006-07-01 Ulrich Drepper <drepper@redhat.com> + + * pthread_mutex_init.c (__pthread_mutex_init): Move some + computations to compile time. + +2006-06-04 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread.h: Add pthread_equal inline version. + +2006-05-15 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/fork.h: Mark __fork_handlers as hidden. + +2006-05-11 Ulrich Drepper <drepper@redhat.com> + + * pthread_key_create.c (__pthread_key_create): Do away with + __pthread_keys_lock. + + * sysdeps/unix/sysv/linux/pthread_setaffinity.c + (__kernel_cpumask_size): Mark as hidden. + * sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c: Likewise. + + * sem_open.c (__sem_mappings_lock): Mark as hidden. + * semaphoreP.h (__sem_mappings_lock): Likewise. + +2006-05-10 Ulrich Drepper <drepper@redhat.com> + + * pthread_atfork.c: Mark __dso_handle as hidden. + +2006-05-09 Ulrich Drepper <drepper@redhat.com> + + [BZ #2644] + * sysdeps/pthread/unwind-forcedunwind.c: Different solution for + the reload problem. Change the one path in pthread_cancel_init + which causes the problem. Force gcc to reload. Simplify callers. + * sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c + (_Unwind_GetBSP): Undo last patch. + +2006-05-07 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c: Make sure the + function pointer is reloaded after pthread_cancel_init calls. + + [BZ #2644] + * sysdeps/pthread/unwind-forcedunwind.c: Make sure functions + pointers are reloaded after pthread_cancel_init calls. + +2006-05-01 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/allocalim.h (__libc_use_alloca): Mark with + __always_inline. + +2006-04-27 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/timer_routines.c (timer_helper_thread): + Allocate new object which is passed to timer_sigev_thread so that + the timer can be deleted before the new thread is scheduled. + +2006-04-26 Roland McGrath <roland@redhat.com> + + * sysdeps/x86_64/tls.h: Include <asm/prctl.h> inside [! __ASSEMBLER__]. + +2006-04-08 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Remove branch predicion + suffix for conditional jumps. + * sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Likewise. + + * init.c (sigcancel_handler): Compare with correct PID even if the + thread is in the middle of a fork call. + (sighandler_setxid): Likewise. + Reported by Suzuki K P <suzuki@in.ibm.com> . + +2006-04-07 Jakub Jelinek <jakub@redhat.com> + + * pthreadP.h (FUTEX_TID_MASK): Sync with kernel. + +2006-04-06 Ulrich Drepper <drepper@redhat.com> + + * pthread_getattr_np.c (pthread_getattr_np): Close fp if getrlimit + fails [Coverity CID 105]. + +2006-04-05 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread.h: Add nonnull attributes. + +2006-04-03 Steven Munroe <sjmunroe@us.ibm.com> + + [BZ #2505] + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h [_ARCH_PWR4]: + Define __lll_rel_instr using lwsync. + +2006-03-27 Ulrich Drepper <drepper@redhat.com> + + * allocatestack.c (allocate_stack): Always initialize robust_head. + * descr.h: Define struct robust_list_head. + (struct pthread): Use robust_list_head in robust mutex list definition. + Adjust ENQUEUE_MUTEX and DEQUEUE_MUTEX. + * init.c [!__ASSUME_SET_ROBUST_LIST] (__set_robust_list_avail): Define. + (__pthread_initialize_minimal_internal): Register robust_list with + the kernel. + * pthreadP.h: Remove PRIVATE_ from PTHREAD_MUTEX_ROBUST_* names. + Declare __set_robust_list_avail. + * pthread_create.c (start_thread): Register robust_list of new thread. + [!__ASSUME_SET_ROBUST_LIST]: If robust_list is not empty wake up + waiters. + * pthread_mutex_destroy.c: For robust mutexes don't look at the + number of users, it's unreliable. + * pthread_mutex_init.c: Allow use of pshared robust mutexes if + set_robust_list syscall is available. + * pthread_mutex_consistent.c: Adjust for PTHREAD_MUTEX_ROBUST_* rename. + * pthread_mutex_lock.c: Simplify robust mutex code a bit. + Set robust_head.list_op_pending before trying to lock a robust mutex. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_trylock.c: Likewise. + * pthread_mutex_unlock.c: Likewise for unlocking. + * Makefile (tests): Add tst-robust8. + * tst-robust8.c: New file. + +2006-03-08 Andreas Schwab <schwab@suse.de> + + * sysdeps/unix/sysv/linux/ia64/dl-sysdep.h + (DL_SYSINFO_IMPLEMENTATION): Add missing newline. + +2006-03-05 Roland McGrath <roland@redhat.com> + + * configure (libc_add_on): Disable add-on when $add_ons_automatic = yes + and $config_os doesn't match *linux*. + +2006-03-05 David S. Miller <davem@sunset.davemloft.net> + + * sysdeps/unix/sysv/linux/sparc/sparc32/pt-vfork.S: + Use __syscall_error. + * sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/pt-vfork.S: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S: Likewise. + * sysdeps/unix/sysv/linux/sparc/Makefile: New file. + +2006-03-02 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/aio_misc.h: Various cleanups. + +2006-03-01 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S + (__lll_robust_lock_wait): Also set FUTEX_WAITERS bit if we got the + mutex. + (__lll_robust_timedlock_wait): Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S + (__lll_robust_lock_wait): Likewise. + (__lll_robust_timedlock_wait): Likewise. + * sysdeps/unix/sysv/linux/lowlevelrobustlock.c + (__lll_robust_lock_wait): Likewise. + (__lll_robust_timedlock_wait): Likewise. + +2006-03-01 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h (lll_robust_mutex_dead, + lll_robust_mutex_trylock, lll_robust_mutex_lock, + lll_robust_mutex_cond_lock, lll_robust_mutex_timedlock, + lll_robust_mutex_unlock): Define. + (__lll_robust_lock_wait, __lll_robust_timedlock_wait): New prototypes. + +2006-02-28 H.J. Lu <hongjiu.lu@intel.com> + + * sysdeps/unix/sysv/linux/ia64/clone2.S: Include <clone2.S> + instead of <clone.S>. + +2006-02-27 Jakub Jelinek <jakub@redhat.com> + + * Makefile (libpthread-routines): Add + pthread_mutexattr_[sg]etprotocol, pthread_mutexattr_[sg]etprioceiling + and pthread_mutex_[sg]etprioceiling. + * Versions (GLIBC_2.4): Export pthread_mutexattr_getprotocol, + pthread_mutexattr_setprotocol, pthread_mutexattr_getprioceiling, + pthread_mutexattr_setprioceiling, pthread_mutex_getprioceiling and + pthread_mutex_setprioceiling. + * sysdeps/pthread/pthread.h (PTHREAD_PRIO_NONE, PTHREAD_PRIO_INHERIT, + PTHREAD_PRIO_PROTECT): New enum values. + (pthread_mutexattr_getprotocol, pthread_mutexattr_setprotocol, + pthread_mutexattr_getprioceiling, pthread_mutexattr_setprioceiling, + pthread_mutex_getprioceiling, pthread_mutex_setprioceiling): New + prototypes. + * pthreadP.h (PTHREAD_MUTEX_PRIO_INHERIT_PRIVATE_NP, + PTHREAD_MUTEX_PRIO_PROTECT_PRIVATE_NP): New enum values. + (PTHREAD_MUTEX_PRIO_CEILING_SHIFT, PTHREAD_MUTEX_PRIO_CEILING_MASK): + Define. + (PTHREAD_MUTEXATTR_PROTOCOL_SHIFT, PTHREAD_MUTEXATTR_PROTOCOL_MASK, + PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT, + PTHREAD_MUTEXATTR_PRIO_CEILING_MASK): Define. + (PTHREAD_MUTEXATTR_FLAG_BITS): Or in PTHREAD_MUTEXATTR_PROTOCOL_MASK + and PTHREAD_MUTEXATTR_PRIO_CEILING_MASK. + * pthread_mutex_init.c (__pthread_mutex_init): For the time being + return ENOTSUP for PTHREAD_PRIO_INHERIT or PTHREAD_PRIO_PROTECT + protocol mutexes. + * pthread_mutex_getprioceiling.c: New file. + * pthread_mutex_setprioceiling.c: New file. + * pthread_mutexattr_getprioceiling.c: New file. + * pthread_mutexattr_setprioceiling.c: New file. + * pthread_mutexattr_getprotocol.c: New file. + * pthread_mutexattr_setprotocol.c: New file. + +2006-02-27 Daniel Jacobowitz <dan@codesourcery.com> + + * sysdeps/unix/sysv/linux/aio_misc.h: Include <limits.h>. + +2006-02-27 Roland McGrath <roland@redhat.com> + + * sysdeps/pthread/Subdirs: List nptl here too. + * configure (libc_add_on_canonical): New variable. + + * sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h: Use #include_next. + + * sysdeps/unix/sysv/linux/sleep.c: Use #include_next after #include of + self to get main source tree's file. + * sysdeps/unix/sysv/linux/alpha/clone.S: Likewise. + * sysdeps/unix/sysv/linux/i386/clone.S: Likewise. + * sysdeps/unix/sysv/linux/i386/vfork.S: Likewise. + * sysdeps/unix/sysv/linux/ia64/clone2.S: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-32/clone.S: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/clone.S: Likewise. + * sysdeps/unix/sysv/linux/sh/clone.S: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/clone.S: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/clone.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/clone.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/vfork.S: Likewise. + + * Makefile: Use $(sysdirs) in vpath directive. + + * sysdeps/pthread/Makefile (CFLAGS-libc-start.c): Variable removed. + (CPPFLAGS-timer_routines.c): Likewise. + + * Makeconfig (includes): Variable removed. + +2006-02-26 Roland McGrath <roland@redhat.com> + + * sysdeps/generic/pt-raise.c: Moved to ... + * pt-raise.c: ... here. + * sysdeps/generic/lowlevellock.h: Moved to ... + * lowlevellock.h: ... here. + +2006-02-23 Roland McGrath <roland@redhat.com> + + * descr.h (struct pthread): Add final member `end_padding'. + (PTHREAD_STRUCT_END_PADDING): Use it. + +2006-02-20 Roland McGrath <roland@redhat.com> + + * sysdeps/mips: Directory removed, saved in ports repository. + * sysdeps/unix/sysv/linux/mips: Likewise. + +2006-02-18 Ulrich Drepper <drepper@redhat.com> + + * tst-robust1.c: Add second mutex to check that the mutex list is + handled correctly. + +2006-02-17 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h (lll_robust_mutex_dead, + lll_robust_mutex_trylock, lll_robust_mutex_lock, + lll_robust_mutex_cond_lock, lll_robust_mutex_timedlock, + lll_robust_mutex_unlock): New macros. + (__lll_robust_lock_wait, __lll_robust_timedlock_wait): New prototypes. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/lowlevelrobustlock.c: New file. + +2006-02-17 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/lowlevellock.h: Add lll_robust_mutex_* + definitions. + * sysdeps/unix/sysv/linux/sh/lowlevelrobustlock.S: New file. + +2006-02-17 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h + (lll_robust_mutex_unlock): Avoid unnecessary wakeups. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h + (lll_robust_mutex_unlock): Likewise. + +2006-02-13 Jakub Jelinek <jakub@redhat.com> + + * descr.h [!__PTHREAD_MUTEX_HAVE_PREV] (DEQUEUE_MUTEX): + Set robust_list.__next rather than robust_list. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h + (__pthread_list_t): New typedef. + (pthread_mutex_t): Replace __next and __prev fields with __list. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h + (__pthread_list_t): New typedef. + (pthread_mutex_t): Replace __next and __prev fields with __list. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h + (__pthread_list_t, __pthread_slist_t): New typedefs. + (pthread_mutex_t): Replace __next and __prev fields with __list. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h + (__pthread_list_t, __pthread_slist_t): New typedefs. + (pthread_mutex_t): Replace __next and __prev fields with __list. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h + (__pthread_list_t, __pthread_slist_t): New typedefs. + (pthread_mutex_t): Replace __next and __prev fields with __list. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h + (__pthread_slist_t): New typedef. + (pthread_mutex_t): Replace __next field with __list. + +2006-02-15 Ulrich Drepper <drepper@redhat.com> + + * pthreadP.h: Define PTHREAD_MUTEX_INCONSISTENT instead of + PTHREAD_MUTEX_OWNERDEAD. + (PTHREAD_MUTEX_ROBUST_PRIVATE_NP): Define as 16, not 256. + Define FUTEX_WAITERS, FUTEX_OWNER_DIED, FUTEX_TID_MASK. + * Makefile (libpthread-routines): Add lowlevelrobustlock. + * pthread_create.c (start_thread): Very much simplify robust_list loop. + * pthread_mutex_consistent.c: Inconsistent mutex have __owner now set + to PTHREAD_MUTEX_INCONSISTENT. + * pthread_mutex_destroy.c: Allow destroying of inconsistent mutexes. + * pthread_mutex_lock.c: Reimplement robust mutex handling. + * pthread_mutex_trylock.c: Likewise. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_unlock.c: Likewise. + * sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c: Likewise. + * sysdeps/unix/sysv/linux/Makefile (gen-as-const-headers): Add + lowlevelrobustlock.sym. + * sysdeps/unix/sysv/linux/lowlevelrobustlock.sym: New file. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Add lll_robust_mutex_* + definitions. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S: New file. + * sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S: New file. + +2006-02-12 Ulrich Drepper <drepper@redhat.com> + + * allocatestack.c (allocate_stack): Initialize robust_list. + * init.c (__pthread_initialize_minimal_internal): Likewise. + * descr.h (struct xid_command): Pretty printing. + (struct pthread): Use __pthread_list_t or __pthread_slist_t for + robust_list. Adjust macros. + * pthread_create.c (start_thread): Adjust robust_list handling. + * phtread_mutex_unlock.c: Don't allow unlocking from any thread + but the owner for all robust mutex types. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Define + __pthread_list_t and __pthread_slist_t. Use them in pthread_mutex_t. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + * sysdeps/pthread/pthread.h: Adjust mutex initializers. + + * sysdeps/unix/sysv/linux/i386/not-cancel.h: Define openat_not_cancel, + openat_not_cancel_3, openat64_not_cancel, and openat64_not_cancel_3. + +2006-02-08 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_futex_wait, + lll_futex_timedwait, lll_wait_tid): Add "memory" clobber. + +2006-01-20 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/lowlevellock.h (lll_futex_wait): + Return status. + (lll_futex_timed_wait): Define. + +2006-01-19 Ulrich Drepper <drepper@redhat.com> + + * tst-cancel4.c: Test ppoll. + +2006-01-18 Andreas Jaeger <aj@suse.de> + + [BZ #2167] + * sysdeps/unix/sysv/linux/mips/bits/pthreadtypes.h + (pthread_mutex_t): Follow changes for other archs. Based on patch + by Jim Gifford <patches@jg555.com>. + +2006-01-13 Richard Henderson <rth@redhat.com> + + * sysdeps/alpha/tls.h (tcbhead_t): Rename member to __private. + +2006-01-10 Roland McGrath <roland@redhat.com> + + * sysdeps/alpha/jmpbuf-unwind.h: File moved to main source tree. + * sysdeps/i386/jmpbuf-unwind.h: Likewise. + * sysdeps/mips/jmpbuf-unwind.h: Likewise. + * sysdeps/powerpc/jmpbuf-unwind.h: Likewise. + * sysdeps/s390/jmpbuf-unwind.h: Likewise. + * sysdeps/sh/jmpbuf-unwind.h: Likewise. + * sysdeps/sparc/sparc32/jmpbuf-unwind.h: Likewise. + * sysdeps/sparc/sparc64/jmpbuf-unwind.h: Likewise. + * sysdeps/x86_64/jmpbuf-unwind.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h: Likewise. + +2006-01-09 Roland McGrath <roland@redhat.com> + + * tst-initializers1-c89.c: New file. + * tst-initializers1-c99.c: New file. + * tst-initializers1-gnu89.c: New file. + * tst-initializers1-gnu99.c: New file. + * Makefile (tests): Add them. + (CFLAGS-tst-initializers1-c89.c): New variable. + (CFLAGS-tst-initializers1-c99.c): New variable. + (CFLAGS-tst-initializers1-gnu89.c): New variable. + (CFLAGS-tst-initializers1-gnu99.c): New variable. + + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_mutex_t): + Use __extension__ on anonymous union definition. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. + +2006-01-08 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_mutex_t): + Don't give the union a name because it changes the mangled name. + Instead name the struct for __data. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h (pthread_mutex_t): + Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h (pthread_mutex_t): + Likewise. + +2006-01-09 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/sparc/sparc64/jmpbuf-unwind.h (_JMPBUF_UNWINDS_ADJ): Add + stack bias to mc_ftp field. + +2006-01-07 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/aio_misc.h (AIO_MISC_WAIT): Work around gcc + being too clever and reloading the futex value where it shouldn't. + +2006-01-06 Ulrich Drepper <drepper@redhat.com> + + * descr.h [!__PTHREAD_MUTEX_HAVE_PREV] (DEQUEUE_MUTEX): Use + correct type. + +2006-01-06 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h (PSEUDO): + Add cfi directives. + +2006-01-06 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/ia64/tls.h (tcbhead_t): Rename private member to __private. + * sysdeps/ia64/tcb-offsets.sym: Adjust for private->__private + rename in tcbhead_t. + + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_mutex_t): + Don't give the union a name because it changes the mangled name. + Instead name the struct for __data. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + * pthread_create.c (start_thread): Adjust robust mutex free loop. + * descr.h (ENQUEUE_MUTEX, DEQUEUE_MUTEX): Adjust. + +2006-01-05 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_futex_wait): + Return status. + (lll_futex_timed_wait): Define. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. + * sysdeps/pthread/aio_misc.h: New file. + +2006-01-03 Joseph S. Myers <joseph@codesourcery.com> + + * Makefile ($(objpfx)$(multidir)): Use mkdir -p. + +2006-01-03 Steven Munroe <sjmunroe@us.ibm.com> + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h + (PSEUDO): Remove redundant cfi_startproc and cfi_endproc directives. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h: Likewise. + +2006-01-04 Ulrich Drepper <drepper@redhat.com> + + * tst-cancel24.cc: Use C headers instead of C++ headers. + +2006-01-03 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h: Remove #error for + sparc-linux configured glibc. + (lll_futex_wake_unlock): Define to 1 for sparc-linux configured glibc. + (__lll_mutex_trylock, __lll_mutex_cond_trylock, __lll_mutex_lock, + __lll_mutex_cond_lock, __lll_mutex_timedlock): Use + atomic_compare_and_exchange_val_24_acq instead of + atomic_compare_and_exchange_val_acq. + (lll_mutex_unlock, lll_mutex_unlock_force): Use atomic_exchange_24_rel + instead of atomic_exchange_rel. + * sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_init.c: New + file. + * sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c: New + file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_init.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_init.c: + New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c: + New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_init.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_post.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_timedwait.c: New + file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_trywait.c: New + file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_wait.c: New file. + +2006-01-03 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread.h [__WORDSIZE==64]: Don't use cast in + mutex initializers. + +2006-01-02 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/sparc/tls.h (tcbhead_t): Add pointer_guard field. + (THREAD_GET_POINTER_GUARD, THREAD_SET_POINTER_GUARD, + THREAD_COPY_POINTER_GUARD): Define. + * sysdeps/sparc/tcb-offsets.sym (POINTER_GUARD): Define. + * sysdeps/sparc/sparc64/jmpbuf-unwind.h: Revert 2005-12-27 changes. + +2006-01-01 Ulrich Drepper <drepper@redhat.com> + + * version.c: Update copyright year. + +2005-12-29 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: Remove explicit + .eh_frame section, use cfi_* directives. + * sysdeps/unix/sysv/linux/sh/lowlevellock.S: Add cfi instrumentation. + +2005-12-30 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h: Undo last change for + now. + +2005-12-29 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/sigaction.c: Removed. + * sigaction.c: New file. + * sysdeps/unix/sysv/linux/Makefile: Define CFLAGS-sigaction.c. + +2005-12-28 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-signal7. + * tst-signal7.c: New file. + +2005-12-27 Roland McGrath <roland@redhat.com> + + * sysdeps/x86_64/jmpbuf-unwind.h (_jmpbuf_sp): New inline function. + (_JMPBUF_UNWINDS_ADJ): Use it, to PTR_DEMANGLE before comparison. + * sysdeps/alpha/jmpbuf-unwind.h: Likewise. + * sysdeps/i386/jmpbuf-unwind.h: Likewise. + * sysdeps/mips/jmpbuf-unwind.h: Likewise. + * sysdeps/powerpc/jmpbuf-unwind.h: Likewise. + * sysdeps/s390/jmpbuf-unwind.h: Likewise. + * sysdeps/sh/jmpbuf-unwind.h: Likewise. + * sysdeps/sparc/sparc32/jmpbuf-unwind.h: Likewise. + * sysdeps/sparc/sparc64/jmpbuf-unwind.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h: Likewise. + +2005-12-27 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h: Add __next + and __prev field to pthread_mutex_t. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Add __next field + to pthread_mutex_t. + +2005-12-26 Ulrich Drepper <drepper@redhat.com> + + * pthreadP.h: Define PTHREAD_MUTEX_ROBUST_PRIVATE_NP, + PTHREAD_MUTEX_ROBUST_PRIVATE_RECURSIVE_NP, + PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP, + PTHREAD_MUTEX_ROBUST_PRIVATE_ADAPTIVE_NP, + PTHREAD_MUTEXATTR_FLAG_ROBUST, PTHREAD_MUTEXATTR_FLAG_PSHARED, + and PTHREAD_MUTEXATTR_FLAG_BITS. + * descr.h (struct pthread): Add robust_list field and define + ENQUEUE_MUTEX and DEQUEUE_MUTEX macros. + * pthread_mutexattr_getrobust.c: New file. + * pthread_mutexattr_setrobust.c: New file. + * pthread_mutex_consistent.c: New file. + * sysdeps/pthread/pthread.h: Declare pthread_mutexattr_getrobust, + pthread_mutexattr_setrobust, and pthread_mutex_consistent. + Define PTHREAD_MUTEX_STALLED_NP and PTHREAD_MUTEX_ROBUST_NP. + Adjust pthread_mutex_t initializers. + * nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Add __next + field to pthread_mutex_t. + * nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Add __next + and __prev field to pthread_mutex_t. + * Versions [GLIBC_2.4]: Export pthread_mutexattr_getrobust_np, + pthread_mutexattr_setrobust_np, and pthread_mutex_consistent_np. + * pthread_mutexattr_getpshared.c: Use PTHREAD_MUTEXATTR_FLAG_PSHARED + and PTHREAD_MUTEXATTR_FLAG_BITS macros instead of magic numbers. + * pthread_mutexattr_gettype.c: Likewise. + * pthread_mutexattr_setpshared.c: Likewise. + * pthread_mutexattr_settype.c: Likewise. + * pthread_mutex_init.c: Reject robust+pshared attribute for now. + Initialize mutex kind according to robust flag. + * pthread_mutex_lock.c: Implement local robust mutex. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_trylock.c: Likewise. + * pthread_mutex_unlock.c: Likewise. + * pthread_create.c (start_thread): Mark robust mutexes which remained + locked as dead. + * tst-robust1.c: New file. + * tst-robust2.c: New file. + * tst-robust3.c: New file. + * tst-robust4.c: New file. + * tst-robust5.c: New file. + * tst-robust6.c: New file. + * tst-robust7.c: New file. + * Makefile (libpthread-routines): Add pthread_mutexattr_getrobust, + pthread_mutexattr_setrobust, and pthread_mutex_consistent. + (tests): Add tst-robust1, tst-robust2, tst-robust3, tst-robust4, + tst-robust5, tst-robust6, and tst-robust7. + + * tst-typesizes.c: New file. + * Makefile (tests): Add tst-typesizes. + + * tst-once3.c: More debug output. + +2005-12-24 Ulrich Drepper <drepper@redhat.com> + + * pthread_mutex_trylock.c (__pthread_mutex_trylock): Add break + missing after last change. + + * version.c: Update copyright year. + +2005-12-23 Ulrich Drepper <drepper@redhat.com> + + * pthread_mutex_destroy.c: Set mutex type to an invalid value. + * pthread_mutex_lock.c: Return EINVAL for invalid mutex type. + * pthread_mutex_trylock.c: Likewise. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_unlock.c: Likewise. + +2005-12-22 Roland McGrath <roland@redhat.com> + + * sysdeps/pthread/sigaction.c: Use "" instead of <> to include self, + so that #include_next's search location is not reset to the -I.. + directory where <nptl/...> can be found. + +2005-12-22 Ulrich Drepper <drepper@redhat.com> + + [BZ #1913] + * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S (__new_sem_wait): + Fix unwind info. Remove useless branch prediction prefix. + * tst-cancel24.cc: New file. + * Makefile: Add rules to build and run tst-cancel24. + +2005-12-21 Roland McGrath <roland@redhat.com> + + * libc-cancellation.c: Use <> rather than "" #includes. + * pt-cleanup.c: Likewise. + * pthread_create.c: Likewise. + * pthread_join.c: Likewise. + * pthread_timedjoin.c: Likewise. + * pthread_tryjoin.c: Likewise. + * sysdeps/unix/sysv/linux/libc_pthread_init.c: Likewise. + * sysdeps/unix/sysv/linux/register-atfork.c: Likewise. + * sysdeps/unix/sysv/linux/unregister-atfork.c: Likewise. + * unwind.c: Likewise. + +2005-12-19 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/sh/tcb-offsets.sym: Add POINTER_GUARD. + * sysdeps/sh/tls.h (tcbhead_t): Remove private and add pointer_guard. + (THREAD_GET_POINTER_GUARD, THREAD_SET_POINTER_GUARD, + THREAD_COPY_POINTER_GUARD): Define. + +2005-12-19 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/ia64/tls.h (TLS_PRE_TCB_SIZE): Make room for 2 uintptr_t's + rather than one. + (THREAD_GET_POINTER_GUARD, THREAD_SET_POINTER_GUARD, + THREAD_COPY_POINTER_GUARD): Define. + * sysdeps/powerpc/tcb-offsets.sym (POINTER_GUARD): Add. + * sysdeps/powerpc/tls.h (tcbhead_t): Add pointer_guard field. + (THREAD_GET_POINTER_GUARD, THREAD_SET_POINTER_GUARD, + THREAD_COPY_POINTER_GUARD): Define. + * sysdeps/s390/tcb-offsets.sym (STACK_GUARD): Add. + * sysdeps/s390/tls.h (THREAD_GET_POINTER_GUARD, + THREAD_SET_POINTER_GUARD, THREAD_COPY_POINTER_GUARD): Define. + * sysdeps/unix/sysv/linux/ia64/__ia64_longjmp.S (__ia64_longjmp): + Use PTR_DEMANGLE for B0 if defined. + +2005-12-17 Ulrich Drepper <drepper@redhat.com> + + * pthread_create.c (__pthread_create_2_1): Use + THREAD_COPY_POINTER_GUARD if available. + * sysdeps/i386/tcb-offsets.sym: Add POINTER_GUARD. + * sysdeps/x86_64/tcb-offsets.sym: Likewise. + * sysdeps/i386/tls.h (tcbhead_t): Add pointer_guard. + Define THREAD_SET_POINTER_GUARD and THREAD_COPY_POINTER_GUARD. + * sysdeps/x86_64/tls.h: Likewise. + +2005-12-15 Roland McGrath <roland@redhat.com> + + * sysdeps/unix/sysv/linux/mq_notify.c: Don't use sysdeps/generic. + +2005-12-13 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/sigfillset.c: Adjust for files moved out of + sysdeps/generic. + * errno-loc.c: New file. + +2005-12-12 Roland McGrath <roland@redhat.com> + + * init.c (__pthread_initialize_minimal_internal): Do __static_tls_size + adjustments before choosing stack size. Update minimum stack size + calculation to match allocate_stack change. + +2005-12-12 Ulrich Drepper <drepper@redhat.com> + + * allocatestack.c (allocate_stack): Don't demand that there is an + additional full page available on the stack beside guard, TLS, the + minimum stack. + +2005-11-24 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h + (__cleanup_fct_attribute): Use __regparm__ not regparm. + + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: When + compiling 32-bit code we must define __cleanup_fct_attribute. + +005-11-24 Jakub Jelinek <jakub@redhat.com> + + [BZ #1920] + * sysdeps/pthread/pthread.h (__pthread_unwind_next): Use + __attribute__ instead of __attribute. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h + (__cleanup_fct_attribute): Likewise. + +2005-11-17 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/unwind-forcedunwind.c (pthread_cancel_init): Put + a write barrier before writing libgcc_s_getcfa. + +2005-11-06 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/configure: Removed. + +2005-11-05 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/ia64/pt-initfini.c: Remove trace of + optional init_array/fini_array support. + +2005-10-24 Roland McGrath <roland@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/sem_trywait.S: Remove unnecessary + versioned_symbol use. + +2005-10-16 Roland McGrath <roland@redhat.com> + + * init.c (__pthread_initialize_minimal_internal): Even when using a + compile-time default stack size, apply the minimum that allocate_stack + will require, and round up to page size. + +2005-10-10 Daniel Jacobowitz <dan@codesourcery.com> + + * Makefile ($(test-modules)): Remove static pattern rule. + +2005-10-14 Jakub Jelinek <jakub@redhat.com> + Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Fix stack + alignment in callback function. + * Makefile: Add rules to build and run tst-align3. + * tst-align3.c: New file. + +2005-10-03 Jakub Jelinek <jakub@redhat.com> + + * allocatestack.c (setxid_signal_thread): Add + INTERNAL_SYSCALL_DECL (err). + +2005-10-02 Jakub Jelinek <jakub@redhat.com> + + * allocatestack.c (setxid_signal_thread): Need to use + atomic_compare_and_exchange_bool_acq. + +2005-10-01 Ulrich Drepper <drepper@redhat.com> + Jakub Jelinek <jakub@redhat.com> + + * descr.h: Define SETXID_BIT and SETXID_BITMASK. Adjust + CANCEL_RESTMASK. + (struct pthread): Move specific_used field to avoid padding. + Add setxid_futex field. + * init.c (sighandler_setxid): Reset setxid flag and release the + setxid futex. + * allocatestack.c (setxid_signal_thread): New function. Broken + out of the bodies of the two loops in __nptl_setxid. For undetached + threads check whether they are exiting and if yes, don't send a signal. + (__nptl_setxid): Simplify loops by using setxid_signal_thread. + * pthread_create.c (start_thread): For undetached threads, check + whether setxid bit is set. If yes, wait until signal has been + processed. + + * allocatestack.c (STACK_VARIABLES): Initialize them. + * pthread_create.c (__pthread_create_2_1): Initialize pd. + +2004-09-02 Jakub Jelinek <jakub@redhat.com> + + * pthread_cond_destroy.c (__pthread_cond_destroy): If there are + waiters, awake all waiters on the associated mutex. + +2005-09-22 Roland McGrath <roland@redhat.com> + + * perf.c [__x86_64__] (HP_TIMING_NOW): New macro (copied from + ../sysdeps/x86_64/hp-timing.h). + +2005-08-29 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (FUTEX_WAKE_OP, + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define. + (lll_futex_wake_unlock): Define. + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h (FUTEX_WAKE_OP, + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define. + (lll_futex_wake_unlock): Define. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (FUTEX_WAKE_OP, + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define. + (lll_futex_wake_unlock): Define. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h (FUTEX_WAKE_OP, + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define. + (lll_futex_wake_unlock): Define. + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h (FUTEX_WAKE_OP, + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define. + (lll_futex_wake_unlock): Define. + * sysdeps/pthread/pthread_cond_signal.c (__pthread_cond_signal): Use + lll_futex_wake_unlock. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S + (FUTEX_WAKE_OP, FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define. + (__pthread_cond_signal): Use FUTEX_WAKE_OP. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S + (FUTEX_WAKE_OP, FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define. + (__pthread_cond_signal): Use FUTEX_WAKE_OP. + +2005-09-05 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/lowlevellock.S (__lll_mutex_lock_wait): + Fix typo in register name. + +2005-08-23 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/timer_routines.c (timer_helper_thread): + Use __sigfillset. Document that sigfillset does the right thing wrt + to SIGSETXID. + +2005-07-11 Jakub Jelinek <jakub@redhat.com> + + [BZ #1102] + * sysdeps/pthread/pthread.h (PTHREAD_MUTEX_INITIALIZER, + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, + PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, + PTHREAD_MUTEX_ADAPTIVE_NP, PTHREAD_RWLOCK_INITIALIZER, + PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP, + PTHREAD_COND_INITIALIZER): Supply zeros for all fields + in the structure. + * Makefile (tests): Add tst-initializers1. + (CFLAGS-tst-initializers1.c): Set. + * tst-initializers1.c: New test. + +2005-07-11 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_rwlock_t): + Make sure __flags are located at offset 48 from the start of the + structure. + +2005-07-02 Roland McGrath <roland@redhat.com> + + * Makeconfig: Comment fix. + +2005-07-05 Jakub Jelinek <jakub@redhat.com> + + * descr.h (PTHREAD_STRUCT_END_PADDING): Define. + * sysdeps/ia64/tls.h (TLS_PRE_TCB_SIZE): If PTHREAD_STRUCT_END_PADDING + is smaller than 8 bytes, increase TLS_PRE_TCB_SIZE by 16 bytes. + (THREAD_SYSINFO, THREAD_SELF, DB_THREAD_SELF): Don't assume + TLS_PRE_TCB_SIZE is sizeof (struct pthread). + (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. + * sysdeps/ia64/tcb-offsets.sym (PID, TID, MULTIPLE_THREADS_OFFSET): + Use TLS_PRE_TCB_SIZE instead of sizeof (struct pthread). + * sysdeps/unix/sysv/linux/ia64/createthread.c (TLS_VALUE): Don't + assume TLS_PRE_TCB_SIZE is sizeof (struct pthread). + +2005-06-25 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/i386/tls.h (tcbhead_t): Add stack_guard field. + (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. + * sysdeps/x86_64/tls.h (tcbhead_t): Add sysinfo and stack_guard + fields. + (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. + * sysdeps/s390/tls.h (tcbhead_t): Add stack_guard + field. Put in sysinfo field unconditionally. + (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. + * sysdeps/powerpc/tls.h (tcbhead_t): Add stack_guard field. + (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. + * sysdeps/sparc/tls.h (tcbhead_t): Add sysinfo and stack_guard + fields. + (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. + * pthread_create.c (__pthread_create_2_1): Use + THREAD_COPY_STACK_GUARD macro. + * Makefile: Add rules to build and run tst-stackguard1{,-static} + tests. + * tst-stackguard1.c: New file. + * tst-stackguard1-static.c: New file. + +2005-06-14 Alan Modra <amodra@bigpond.net.au> + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h (PSEUDO): + Invoke CGOTSETUP and CGOTRESTORE. + (CGOTSETUP, CGOTRESTORE): Define. + +2005-05-29 Richard Henderson <rth@redhat.com> + + * tst-cancel4.c (WRITE_BUFFER_SIZE): New. + (tf_write, tf_writev): Use it. + (do_test): Use socketpair instead of pipe. Set SO_SNDBUF to + the system minimum. + +2005-05-23 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h + [IS_IN_librt] (CENABLE, CDISABLE): Use JUMPTARGET instead of + __librt_*_asynccancel@local. + +2005-05-17 Alan Modra <amodra@bigpond.net.au> + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h: Delete + all occurrences of JUMPTARGET. Instead append @local to labels. + +2005-05-20 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/i386/tls.h (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN): Define to + size/alignment of struct pthread rather than tcbhead_t. + * sysdeps/x86_64/tls.h (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN): + Likewise. + * sysdeps/s390/tls.h (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN): + Likewise. + * sysdeps/sparc/tls.h (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN): + Likewise. + +2005-05-19 Richard Henderson <rth@redhat.com> + + * sysdeps/ia64/pthread_spin_lock.c (pthread_spin_lock): Use + __sync_val_compare_and_swap, not explicit _si variant. + * sysdeps/ia64/pthread_spin_trylock.c (pthread_spin_trylock): Likewise. + +2005-05-03 Ulrich Drepper <drepper@redhat.com> + + [BZ #915] + * sysdeps/pthread/pthread.h: Avoid empty initializers. + +2005-05-03 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Remove explicit + .eh_frame section, use cfi_* directives. + +2005-04-27 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/pthread_getcpuclockid.c: Use <> instead + of "" includes. + +2005-04-27 Ulrich Drepper <drepper@redhat.com> + + [BZ #1075] + * tst-cancel17.c (do_test): Add arbitrary factor to make sure + aio_write blocks. + +2005-04-27 Roland McGrath <roland@redhat.com> + + * Makefile (tests): Remove tst-clock2. + + * sysdeps/unix/sysv/linux/timer_create.c (timer_create): Handle + CLOCK_PROCESS_CPUTIME_ID and CLOCK_PROCESS_THREAD_ID specially, + translating to the kernel clockid_t for our own process/thread clock. + + * sysdeps/unix/sysv/linux/pthread_getcpuclockid.c: New file. + +2005-04-15 Jakub Jelinek <jakub@redhat.com> + + * old_pthread_cond_init.c: Include <errno.h>. + (__pthread_cond_init_2_0): Fail with EINVAL if COND_ATTR is + process shared or uses clock other than CLOCK_REALTIME. + * pthread_cond_init.c (__pthread_cond_init): Remove bogus comment. + +2005-04-13 David S. Miller <davem@davemloft.net> + + * sysdeps/sparc/sparc64/jmpbuf-unwind.h: New file. + * sysdeps/sparc/sparc64/clone.S: New file. + +2005-04-05 Jakub Jelinek <jakub@redhat.com> + + [BZ #1102] + * sysdeps/pthread/pthread.h (__pthread_cleanup_routine): Use + __inline instead of inline. + * sysdeps/pthread/bits/libc-lock.h (__libc_cleanup_routine): Likewise. + +2005-03-31 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S: Use + functionally equivalent, but shorter instructions. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_post.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise. + +2005-03-28 Daniel Jacobowitz <dan@codesourcery.com> + + * sysdeps/mips/Makefile: New file. + * sysdeps/mips/nptl-sysdep.S: New file. + * sysdeps/mips/tcb-offsets.sym: New file. + * sysdeps/mips/pthread_spin_lock.S: New file. + * sysdeps/mips/pthread_spin_trylock.S: New file. + * sysdeps/mips/pthreaddef.h: New file. + * sysdeps/mips/tls.h: New file. + * sysdeps/mips/jmpbuf-unwind.h: New file. + * sysdeps/unix/sysv/linux/mips/lowlevellock.h: New file. + * sysdeps/unix/sysv/linux/mips/bits/pthreadtypes.h: New file. + * sysdeps/unix/sysv/linux/mips/bits/semaphore.h: New file. + * sysdeps/unix/sysv/linux/mips/pthread_once.c: New file. + * sysdeps/unix/sysv/linux/mips/fork.c: New file. + * sysdeps/unix/sysv/linux/mips/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/mips/vfork.S: New file. + * sysdeps/unix/sysv/linux/mips/clone.S: New file. + * sysdeps/unix/sysv/linux/mips/createthread.c: New file. + * sysdeps/unix/sysv/linux/mips/sysdep-cancel.h: New file. + +2005-03-23 Ulrich Drepper <drepper@redhat.com> + + [BZ #1112] + * pthread_create.c (__pthread_create_2_1): Rename syscall error + variable to scerr. + +2005-03-10 Jakub Jelinek <jakub@redhat.com> + + * tst-getpid1.c (do_test): Align stack passed to clone{2,}. + +2005-02-25 Roland McGrath <roland@redhat.com> + + * alloca_cutoff.c: Correct license text. + * tst-unload.c: Likewise. + * sysdeps/pthread/allocalim.h: Likewise. + * sysdeps/pthread/pt-initfini.c: Likewise. + * sysdeps/pthread/bits/libc-lock.h: Likewise. + * sysdeps/pthread/bits/sigthread.h: Likewise. + * sysdeps/unix/sysv/linux/bits/local_lim.h: Likewise. + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Likewise. + +2005-02-16 Roland McGrath <roland@redhat.com> + + * sysdeps/pthread/pthread-functions.h (struct pthread_functions): + Use unsigned int * for ptr_nthreads. + +2005-02-14 Alan Modra <amodra@bigpond.net.au> + + [BZ #721] + * sysdeps/powerpc/tcb-offsets.sym (thread_offsetof): Redefine to suit + gcc4. + +2005-02-07 Richard Henderson <rth@redhat.com> + + [BZ #787] + * sysdeps/pthread/pthread.h (__sigsetjmp): Use pointer as first + argument. + +2004-11-03 Marcus Brinkmann <marcus@gnu.org> + + * sysdeps/generic/lowlevellock.h (__generic_mutex_unlock): Fix + order of arguments in invocation of atomic_add_zero. + +2005-01-26 Jakub Jelinek <jakub@redhat.com> + + [BZ #737] + * sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S (__new_sem_trywait): + Use direct %gs segment access or, if NO_TLS_DIRECT_SEG_REFS, + at least gotntpoff relocation and addition. + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S (sem_timedwait): + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S (__new_sem_post): + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S (__new_sem_wait): + Likewise. + +2005-01-06 Ulrich Drepper <drepper@redhat.com> + + * allocatestack.c (init_one_static_tls): Adjust initialization of DTV + entry for static tls deallocation fix. + * sysdeps/alpha/tls.h (dtv_t): Change pointer type to be struct which + also contains information whether the memory pointed to is static + TLS or not. + * 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. + +2004-12-27 Ulrich Drepper <drepper@redhat.com> + + * init.c (__pthread_initialize_minimal_internal): Use __sigemptyset. + +2004-12-21 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/i386/tls.h (CALL_THREAD_FCT): Maintain 16 byte alignment of + %esp. + * Makefile (tests): Add tst-align2. + * tst-align2.c: New test. + * sysdeps/i386/Makefile (CFLAGS-tst-align{,2}.c): Add + -mpreferred-stack-boundary=4. + +2004-12-18 Roland McGrath <roland@redhat.com> + + * sysdeps/unix/sysv/linux/powerpc/powerpc64/bits/local_lim.h: + New file removed withdrawn for the moment. + +2004-12-17 Richard Henderson <rth@redhat.com> + + * sysdeps/unix/sysv/linux/alpha/clone.S: New file. + * sysdeps/alpha/tcb-offsets.sym (TID_OFFSET): New. + +2004-12-16 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/powerpc/powerpc64/bits/local_lim.h: New file. + Increased PTHREAD_STACK_MIN. + + * tst-context1.c (stacks): Use bigger stack size. + +2004-12-16 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/sparc/sparc32/clone.S: New file. + * sysdeps/sparc/tcb-offsets.sym: Add TID. + +2004-12-15 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/s390/s390-32/clone.S: New file. + * sysdeps/unix/sysv/linux/s390/s390-64/clone.S: New file. + * sysdeps/s390/tcb-offsets.sym (TID): Add. + +2004-12-15 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S: New file. + +2004-12-14 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/powerpc/tcb-offsets.sym: Add TID. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S: New file. + + * tst-getpid1.c: If child crashes, report this first. Print which + signal. + +2004-12-09 Ulrich Drepper <drepper@redhat.com> + + * init.c (__pthread_initialize_minimal_internal): Also unblock + SIGSETXID. + +2004-12-01 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/bits/posix_opt.h (_POSIX_CPUTIME, + _POSIX_THREAD_CPUTIME): Define to 0. + * sysdeps/pthread/timer_create.c (timer_create): Remove unused code + handling CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID. + * sysdeps/pthread/timer_routines.c (__timer_signal_thread_pclk, + __timer_signal_thread_tclk): Remove. + (init_module): Remove their initialization. + (thread_cleanup): Remove their cleanup assertions. + * sysdeps/pthread/posix-timer.h (__timer_signal_thread_pclk, + __timer_signal_thread_tclk): Remove. + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Removed. + * sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: Removed. + * sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: Removed. + +2004-12-07 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/ia64/tcb-offsets.sym (TID): Add. + * sysdeps/unix/sysv/linux/ia64/clone2.S: New file. + + * Makefile (tests): Add tst-getpid2. + * tst-getpid1.c (TEST_CLONE_FLAGS): Define. + (do_test): Use it. Use __clone2 instead of clone on ia64. + * tst-getpid2.c: New test. + +2004-12-07 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/clone.S: New file. + +2004-12-04 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-getpid1. + * tst-getpid1.c: New file. + * sysdeps/unix/sysv/linux/i386/clone.S: New file. + * sysdeps/unix/sysv/linux/x86_64/clone.S: New file. + +2004-12-02 Roland McGrath <roland@redhat.com> + + * Makefile (libpthread-nonshared): Variable removed. + ($(objpfx)libpthread_nonshared.a): Target removed. + ($(inst_libdir)/libpthread_nonshared.a): Likewise. + These are now handled by generic magic from + libpthread-static-only-routines being set. + +2004-11-27 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/bits/posix_opt.h (_POSIX_PRIORITIZED_IO, + _POSIX2_CHAR_TERM, _POSIX_THREAD_PRIO_INHERIT, + _POSIX_THREAD_PRIO_PROTECT): Define. + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: Likewise. + +2004-11-26 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/bits/posix_opt.h (_POSIX_ADVISORY_INFO, + _POSIX_SPORADIC_SERVER, _POSIX_THREAD_SPORADIC_SERVER, _POSIX_TRACE, + _POSIX_TRACE_EVENT_FILTER, _POSIX_TRACE_INHERIT, _POSIX_TRACE_LOG, + _POSIX_TYPED_MEMORY_OBJECTS, _POSIX_IPV6, _POSIX_RAW_SOCKETS): Define. + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: Likewise. + +2004-11-24 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/x86_64/Makefile [nptl]: Define CFLAGS-pthread_create.c. + + * Makefile (libpthread-routines): Add pthread_setschedprio. + * Versions [libpthread, GLIBC_2.3.4]: Add pthread_setschedprio. + * sysdeps/pthread/pthread.h: Declare pthread_setschedprio. + * pthread_setschedprio.c: New file. + +2004-11-20 Jakub Jelinek <jakub@redhat.com> + + * pthread_create.c (pthread_cancel): Add PTHREAD_STATIC_FN_REQUIRE. + * pthread_cancel.c (pthread_create): Likewise. + + * Makefile (libpthread-routines): Add vars. + * sysdeps/pthread/createthread.c (__pthread_multiple_threads): Remove. + * init.c (__default_stacksize, __is_smp): Remove. + * vars.c: New file. + * pthreadP.h (__find_thread_by_id): If !SHARED, add weak_function + and define a wrapper macro. + (PTHREAD_STATIC_FN_REQUIRE): Define. + * allocatestack.c (__find_thread_by_id): Undefine. + * pthread_create (__pthread_keys): Remove. + (pthread_mutex_lock, pthread_mutex_unlock, pthread_once, + pthread_key_create, pthread_setspecific, pthread_getspecific): Add + PTHREAD_STATIC_FN_REQUIRE. + +2004-11-18 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/sh/tls.h (DB_THREAD_SELF): Set the correct bias + parameter to REGISTER macro. + +2004-11-17 Roland McGrath <roland@redhat.com> + + * sysdeps/unix/sysv/linux/timer_routines.c (__start_helper_thread): + Make sure SIGCANCEL is blocked as well. + +2004-11-10 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/setxid.h: New file. + * sysdeps/pthread/pthread-functions.h (HAVE_PTR__NPTL_SETXID): Remove. + (struct xid_command): Add forward decl. + (struct pthread_functions): Change return type of __nptl_setxid hook + to int. + * pthreadP.h (__nptl_setxid): Change return type to int. + * allocatestack.c (__nptl_setxid): Call INTERNAL_SYSCALL_NCS in the + calling thread, return its return value and set errno on failure. + * descr.h (struct xid_command): Change id type to long array. + + * Makefile: Add rules to build and test tst-setuid1 and + tst-setuid1-static. + * tst-setuid1.c: New test. + * tst-setuid1-static.c: New test. + +2004-11-10 Jakub Jelinek <jakub@redhat.com> + + * Makefile (tests): Add tst-exit3. + * tst-exit3.c: New test. + +2004-11-09 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-exit2. + * tst-exit2.c: New file. + +2004-11-09 Roland McGrath <roland@redhat.com> + + [BZ #530] + * sysdeps/pthread/createthread.c (do_clone): Increment __nptl_nthreads + here, before calling clone. + * pthread_create.c (start_thread): Don't do it here. + +2004-11-02 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/smp.h: Include <errno.h>. + +2004-10-29 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/sem_timedwait.S (sem_timedwait): + Set ETIMEDOUT to errno when time is up. Tweak to avoid + assembler warning. + +2004-10-28 Jakub Jelinek <jakub@redhat.com> + + * pthread_create.c (__pthread_create_2_1): Avoid leaking stacks + if sched_priority is not between minprio and maxprio. + +2004-10-25 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Use clock_gettime syscall if exists. + + * sysdeps/unix/sysv/linux/sh/lowlevellock.S + (__lll_mutex_timedlock_wait): Fix a bad branch condition. + +2004-10-24 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/smp.h (is_smp_system): Use + not-cancelable I/O functions. + +2004-10-21 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/lowlevellock.S + (__lll_mutex_timedlock_wait): If woken but cannot get the lock, + make sure 2 is stored in the futex and we looked at the old value. + Fix a few other problems to return the correct value. + +2004-10-14 Richard Henderson <rth@redhat.com> + + * sysdeps/alpha/tcb-offsets.sym (thread_offsetof): Redefine to + make gcc4 happy. + +2004-10-06 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/jmp-unwind.c: Include pthreadP.h instead + of pthread-functions.h and pthreaddef.h. + * sysdeps/unix/sysv/linux/s390/jmp-unwind.c: Likewise. + + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h (pthread_cond_t): + Change __data.__nwaiters from int to unsigned int. + + * tst-clock2.c (do_test): Don't fail if _POSIX_THREAD_CPUTIME == 0 and + sysconf (_SC_THREAD_CPUTIME) returns negative value. + + * allocatestack.c (__find_thread_by_id): Move attribute_hidden + before return type. + + * sysdeps/s390/jmpbuf-unwind.h: Include bits/wordsize.h. + (JMPBUF_CFA_UNWINDS_ADJ): Subtract 96 resp. 160 bytes from CFA. + +2004-10-06 Ulrich Drepper <drepper@redhat.com> + + * tst-cancel4.c (tf_msgrcv): Check for failure in msgget. If the + test fails, remove message queue. + (tf_msgsnd): Likewise. + +2004-10-05 Jakub Jelinek <jakub@redhat.com> + + * tst-clock1.c: Change #ifdef to #if defined. + * tst-clock2.c: Likewise. + * tst-cond11.c: Likewise. + + * sysdeps/pthread/timer_create.c (timer_create): Use + defined _POSIX_CPUTIME && _POSIX_CPUTIME >= 0 instead of + defined CLOCK_PROCESS_CPUTIME_ID #ifs and similarly for + THREAD_CPUTIME. + +2004-10-05 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h (_POSIX_CPUTIME, + _POSIX_THREAD_CPUTIME): Define to 0. + +2004-10-04 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Define _POSIX_CPUTIME + and _POSIX_THREAD_CPUTIME to zero. + * sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: Likewise. + * tst-barrier2.c: Fix testing for POSIX feature. + * tst-clock1.c: Likewise. + * tst-clock2.c: Likewise. + * tst-cond11.c: Likewise. + * tst-cond4.c: Likewise. + * tst-cond6.c: Likewise. + * tst-flock2.c: Likewise. + * tst-mutex4.c: Likewise. + * tst-mutex9.c: Likewise. + * tst-rwlock12.c: Likewise. + * tst-rwlock4.c: Likewise. + * tst-signal1.c: Likewise. + * tst-spin2.c: Likewise. + * sysdeps/pthread/posix-timer.h: Likewise. + * sysdeps/pthread/timer_create.c: Likewise. + * sysdeps/pthread/timer_routines.c: Likewise. + +2004-10-01 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S + (__lll_mutex_timedlock_wait): Address futex correctly. + + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S + (__lll_mutex_timedlock_wait): If woken but cannot get the lock, + make sure 2 is stored in the futex and we looked at the old value. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S + (__lll_mutex_timedlock_wait): Likewise. Fix a few other problems + which might very well made the code not working at all before. + [BZ #417] + +2004-09-28 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/pthread_kill.c (__pthread_kill): Don't + allow SIGSETXID to be sent. + * sysdeps/pthread/sigaction.c (__sigaction): Don't allow action + for SIGSETXID to be defined. + * sysdeps/pthread/pthread_sigmask.c (pthread_sigmask): Make sure + SIGSETXID cannot be blocked. + + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h (pthread_cond_t): + Add __extension__ to long long types. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + +2004-09-25 Ulrich Drepper <drepper@redhat.com> + + * descr.h (struct pthread): Add stopped_start field. + * sysdeps/pthread/createthread.c (create_thread): Set + start_stopped flag in descriptor for new thread appropriately. + * pthread_create.c (start_thread): Only take lock to be stopped on + startup if stopped_start flag says so. + +2004-09-24 Ulrich Drepper <drepper@redhat.com> + + * pthread_create.c (__pthread_create_2_1): Remember whether thread + is created detached and if yes, do not try to free the stack in case + the thread creation failed. + * sysdeps/pthread/createthread.c (do_clone): Free stack here if clone + call fails. Don't depend on INTERNAL_SYSCALL_ERRNO return zero in + case there has been no error. [BZ #405] + + * pthread_create.c (start_thread): Don't wait for scheduler data + etc to be set at the beginning of the function. The cancellation + infrastructure must have been set up. And enable async + cancellation before potentially going to sleep. [BZ #401] + +2004-09-20 Ulrich Drepper <drepper@redhat.com> + + * Versions: Remove exports for pthread_set*id_np functions. + * sysdeps/pthread/pthread.h: Remove pthread_set*id_np prototypes + for now. + * Makefile: Don't build pthread_set*id code for now. + +2004-09-19 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/allocrtsig.c: Allocate second signal for + internal use. + * allocatestack.c (__nptl_setxid): New function. + * descr.h (struct xid_command): Define type. + * init.c (pthread_functions): Add ptr__nptl_setxid initialization. + (sighandler_setxid): New function. + (__pthread_initialize_minimal): Register sighandler_setxid for + SIGCANCEL. + * pt-allocrtsig.c: Update comment. + * pthreadP.h: Define SIGSETXID. Declare __xidcmd variable. + Declare __nptl_setxid. + * sysdeps/pthread/pthread-functions.h: Add ptr__nptl_setxid. + * sysdeps/pthread/pthread.h: Declare pthread_setgid_np, + pthread_setuid_np, pthread_setegid_np, pthread_seteuid_np, + pthread_setregid_np, pthread_setreuid_np, pthread_setresgid_np, + and pthread_setresuid_np. + * pthread_setgid_np.c: New file. + * pthread_setuid_np.c: New file. + * pthread_setegid_np.c: New file. + * pthread_seteuid_np.c: New file. + * pthread_setregid_np.c: New file. + * pthread_setreuid_np.c: New file. + * pthread_setresgid_np.c: New file. + * pthread_setresuid_np.c: New file. + * Versions [libpthread, GLIBC_2.3.4]: Add pthread_setgid_np, + pthread_setuid_np, pthread_setegid_np, pthread_seteuid_np, + pthread_setregid_np, pthread_setreuid_np, pthread_setresgid_np, + and pthread_setresuid_np. + * Makefile (libpthread-routines): Add pthread_setuid, pthread_seteuid, + pthread_setreuid, pthread_setresuid, pthread_setgid, pthread_setegid, + pthread_setregid, and pthread_setresgid. + +2004-09-18 Ulrich Drepper <drepper@redhat.com> + + * allocatestack.c (allocate_stack): Return EAGAIN instead of + ENOMEM when out of memory. + +2004-09-10 Roland McGrath <roland@redhat.com> + + [BZ #379] + * allocatestack.c (allocate_stack): Remove [__ASSUME_CLONE_STOPPED] + code, since we don't try to use the broken CLONE_STOPPED any more. + * pthread_create.c (start_thread): Likewise. + +2004-09-15 Richard Henderson <rth@redhat.com> + + * sysdeps/unix/sysv/linux/alpha/vfork.S: Use libc_hidden_def. + +2004-09-01 David Mosberger <davidm@hpl.hp.com> + + * sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h + (__libc_unwind_longjmp): Delete macro and declare as function. + * sysdeps/unix/sysv/linux/ia64/Makefile (sysdep_routines): Mention + __ia64_longjmp, sigstack_longjmp, and __sigstack_longjmp for + nptl directory. + * sysdeps/unix/sysv/linux/ia64/__ia64_longjmp.S: New file. + * sysdeps/unix/sysv/linux/ia64/__sigstack_longjmp.c: New file. + * sysdeps/unix/sysv/linux/ia64/unwind_longjmp.c: New file. + +2004-09-12 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread.h: Make rwlock prototypes available also + for __USE_XOPEN2K. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h: Define rwlock + types also for __USE_XOPEN2K. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + [BZ #320] + +2004-09-08 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread.h + (PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP): Make safe for C++. + (PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP): Likewise. + (PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP): Likewise. + (PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP): Likewise. + [BZ #375] + +2004-09-07 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h: Allow + PSEUDO to be used with . prefix. + + * sysdeps/unix/sysv/linux/alpha/pthread_once.c (__pthread_once): + Use atomic_increment instead of atomic_exchange_and_add. + * sysdeps/unix/sysv/linux/sparc/pthread_once.c (__pthread_once): + Likewise. + * sysdeps/unix/sysv/linux/ia64/pthread_once.c (__pthread_once): + Likewise. + * sysdeps/unix/sysv/linux/powerpc/pthread_once.c (__pthread_once): + Likewise. + + * allocatestack.c (allocate_stack): Use atomic_increment_val + instead of atomic_exchange_and_add. + * sysdeps/unix/sysv/linux/sem_post.c (__new_sem_post): Likewise. + * sysdeps/unix/sysv/linux/powerpc/sem_post.c (__new_sem_post): + Likewise. + * sysdeps/pthread/pthread_barrier_wait.c (pthread_barrier_wait): + Likewise. + + * sysdeps/pthread/pthread.h (pthread_once): Remove __THROW since + the initialization function might throw. + +2005-09-05 Richard Henderson <rth@redhat.com> + + * sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h (SINGLE_THREAD_P): + Move definition inside libpthread, libc, librt check. Provide + definition for rtld. + +2004-09-02 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/alpha/jmpbuf-unwind.h: Define __libc_unwind_longjmp. + * sysdeps/i386/jmpbuf-unwind.h: Likewise + * sysdeps/powerpc/jmpbuf-unwind.h: Likewise. + * sysdeps/s390/jmpbuf-unwind.h: Likewise. + * sysdeps/sh/jmpbuf-unwind.h: Likewise. + * sysdeps/sparc/sparc32/jmpbuf-unwind.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h: Likewise. + * sysdeps/x86_64/jmpbuf-unwind.h: Likewise. + * unwind.c: Use it. + + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_cond_t): + Rename __data.__clock to __data.__nwaiters, make it unsigned int. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h (pthread_cond_t): + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: + Decrement __nwaiters. If pthread_cond_destroy has been called and + this is the last waiter, signal pthread_cond_destroy caller and + avoid using the pthread_cond_t structure after unlock. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + Read clock type from the least significant bits of __nwaiters instead + of __clock. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/internaltypes.h: Define COND_CLOCK_BITS. + +2004-08-31 Jakub Jelinek <jakub@redhat.com> + + [BZ #342] + * Makefile (tests): Add tst-cond20 and tst-cond21. + * tst-cond20.c: New test. + * tst-cond21.c: New test. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h + (pthread_cond_t): Rename __data.__clock to __data.__nwaiters, make + it unsigned int. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h (pthread_cond_t): + Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h + (pthread_cond_t): Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h (pthread_cond_t): + Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h (pthread_cond_t): + Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h (pthread_cond_t): + Likewise. + * sysdeps/unix/sysv/linux/lowlevelcond.sym (cond_clock): Remove. + (cond_nwaiters): New. + (clock_bits): New. + * pthread_cond_destroy.c (__pthread_cond_destroy): Return EBUSY + if there are waiters not signalled yet. + Wait until all already signalled waiters wake up. + * sysdeps/pthread/pthread_cond_wait.c (__condvar_cleanup): Decrement + __nwaiters. If pthread_cond_destroy has been called and this is the + last waiter, signal pthread_cond_destroy caller and avoid using + the pthread_cond_t structure after unlock. + (__pthread_cond_wait): Increment __nwaiters in the beginning, + decrement it when leaving. If pthread_cond_destroy has been called + and this is the last waiter, signal pthread_cond_destroy caller. + * sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait): + Likewise. Read clock type from the least significant bits of + __nwaiters instead of __clock. + * pthread_condattr_setclock.c (pthread_condattr_setclock): Check + whether clock ID can be encoded in COND_CLOCK_BITS bits. + * pthread_condattr_getclock.c (pthread_condattr_getclock): Decode + clock type just from the last COND_CLOCK_BITS bits of value. + * pthread_cond_init.c (__pthread_cond_init): Initialize __nwaiters + instead of __clock, just from second bit of condattr's value. + +2004-08-30 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Include + bits/wordsize.h. Make the header match i386 header when __WORDSIZE + != 64. + * sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h: Likewise. + +2004-08-15 Roland McGrath <roland@frob.com> + + * pthread_atfork.c: Update copyright terms including special exception + for these trivial files, which are statically linked into executables + that use dynamic linking for the significant library code. + +2004-08-09 Jakub Jelinek <jakub@redhat.com> + + * DESIGN-rwlock.txt: Add decreasing of nr_readers_queued to + pthread_rwlock_rdlock. + * sysdeps/pthread/pthread_rwlock_rdlock (__pthread_rwlock_rdlock): + Decrease __nr_readers_queued after reacquiring lock. + * sysdeps/pthread/pthread_rwlock_timedrdlock + (pthread_rwlock_timedrdlock): Likewise. + Reported by Bob Cook <bobcook47@hotmail.com>. + +2004-08-11 Jakub Jelinek <jakub@redhat.com> + + * tst-rwlock14.c (tf): Read main thread handle from *ARG + before pthread_barrier_wait. + +2004-08-07 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: + Remove unnecessary exception handling data. + +2004-07-23 Jakub Jelinek <jakub@redhat.com> + + [BZ #284] + * sysdeps/pthread/pthread.h (pthread_getcpuclockid): Use __clockid_t + instead of clockid_t. + +2004-07-21 Roland McGrath <roland@redhat.com> + + * Makefile ($(objpfx)multidir.mk): Use $(make-target-directory). + +2004-07-19 Roland McGrath <roland@redhat.com> + + * tst-cancel4.c (tf_waitid): Use WEXITED flag bit if available. + +2004-07-02 Roland McGrath <roland@redhat.com> + + * configure: Don't exit. + +2004-07-14 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Check for invalid nanosecond in + timeout value. + +2004-07-07 Ulrich Drepper <drepper@redhat.com> + + * Makefile: Add rules to build and run tst-fini1. + * tst-fini1.c: New file. + * tst-fini1mod.c: New file. + +2004-07-05 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Define NO_CANCELLATION + if no cancellation support is needed. + * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h: Likewise. + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Define __NR_futex + only if not already defined. + +2004-07-05 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (lll_unlock): Use + constraint "m" instead of "0" for futex. + + * shlib-versions: Add powerpc64-.*-linux.*. + +2004-07-04 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S + (pthread_rwlock_timedrdlock): Use cmpq instead of cmpl to check + for valid tv_nsec. + * tst-rwlock14.c (do_test): Test for invalid tv_nsec equal to + 1 billion and 64-bit tv_nsec which is valid when truncated to 32 + bits. + +2004-06-29 Roland McGrath <roland@redhat.com> + + * Banner: NPTL no longer has its own version number. + * Makefile (nptl-version): Variable removed. + * sysdeps/pthread/Makefile (CFLAGS-confstr.c): Set LIBPTHREAD_VERSION + using $(version), the glibc version number. + +2004-06-29 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/pthread_once.S (__pthread_once): + Fix branch offset for a PLT entry. + * sysdeps/unix/sysv/linux/sh/sem_post.S (__new_sem_post): + Likewise. + * sysdeps/unix/sysv/linux/sh/sem_timedwait.S (sem_timedwait): + Likewise. + * sysdeps/unix/sysv/linux/sh/sem_trywait.S (__new_sem_trywait): + Likewise. + * sysdeps/unix/sysv/linux/sh/sem_wait.S (__new_sem_wait): + Likewise. + +2004-06-28 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/alpha/tcb-offsets.sym (MULTIPLE_THREADS_OFFSET): Define + unconditionally. + +2004-06-28 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/pthread_rwlock_timedwrlock.c + (pthread_rwlock_timedwrlock): Return EINVAL if tv_nsec is negative, + instead of tv_sec. + * sysdeps/pthread/pthread_rwlock_timedrdlock.c + (pthread_rwlock_timedrdlock): Likewise. + +2004-06-22 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/s390/lowlevellock.h (lll_futex_requeue): + Set __r7 to val, not mutex. + +2004-06-27 Ulrich Drepper <drepper@redhat.com> + + * Makefile: Add rules to build tst-rwlock14. + * tst-rwlock14.c: New file. + +2004-06-24 Boris Hu <boris.hu@intel.com> + + * sysdeps/pthread/pthread_rwlock_timedrdlock.c: Add timeout validation + check. + * sysdeps/pthread/pthread_rwlock_timedwrlock.c: Likewise. + +2004-06-19 Andreas Jaeger <aj@suse.de> + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Fix + assembler in last patch. + +2004-06-17 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread_cond_timedwait.c + (__pthread_cond_timedwait): Also check for negativ nanoseconds. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Check for invalid nanosecond in + timeout value. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + * tst-cond19.c: New file. + * Makefile: Add rules to build and run tst-cond19. + +2004-06-15 Steven Munroe <sjmunroe@us.ibm.com> + + * tst-context1.c (GUARD_PATTERN): Defined. + (tst_context_t): Define struct containing ucontext_t & guard words. + (ctx): Declare as an array of tst_context_t. + (fct): Verify uc_link & guard words are still valid. + (tf): Initialize guard words in ctx. Adjust ctx refs for new struct. + +2004-06-13 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h (pthread_cond_t): + Add __data.__futex field, reshuffle __data.__clock. + * sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S + (__pthread_cond_signal): Increment __futex at the same time as + __wakeup_seq or __total_seq. Pass address of __futex instead of + address of low 32-bits of __wakeup_seq to futex syscall. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S + (__pthread_cond_wait): Likewise. Pass __futex value from before + releasing internal lock to FUTEX_WAIT. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S + (FUTEX_CMP_REQUEUE): Define. + (__pthread_cond_broadcast): Set __futex to 2 * __total_seq. + Use FUTEX_CMP_REQUEUE operation instead of FUTEX_REQUEUE. + Pass __futex value from before the unlock and __futex address instead + of address of low 32-bits of __wakeup_seq to futex syscall. + Fallback to FUTEX_WAKE all on any errors. + +2004-06-08 Jakub Jelinek <jakub@redhat.com> + + * pthread_mutexattr_getpshared.c (pthread_mutex_getpshared): Fix + comment typo. + * pthread_mutexattr_gettype.c (pthread_mutexattr_gettype): Likewise. + * pthread_mutexattr_init.c (__pthread_mutexattr_init): Likewise. + * pthread_mutexattr_settype.c (__pthread_mutexattr_settype): Likewise. + * pthread_mutexattr_setpshared.c (pthread_mutexattr_setpshared): + Likewise. Reported by Bob Cook <bobcook47@hotmail.com>. + +2004-06-11 Martin Schwidefsky <schwidefsky@de.ibm.com> + + * sysdeps/unix/sysv/linux/s390/lowlevellock.h (lll_compare_and_swap): + Add memory clobber to inline assembly. + (__lll_mutex_trylock): Likewise. + (__lll_mutex_cond_trylock): Likewise. + +2004-06-07 Martin Schwidefsky <schwidefsky@de.ibm.com> + + * sysdeps/unix/sysv/linux/s390/lowlevellock.h (lll_futex_requeue): + Pass val argument as 6th system call argument in %r7. + +2004-05-21 Jakub Jelinek <jakub@redhat.com> + + * Makefile (tests): Add tst-cond16. + * sysdeps/unix/sysv/linux/lowlevelcond.sym (cond_futex): Add. + * pthread_cond_init.c (__pthread_cond_init): Clear __data.__futex. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_cond_t): + Add __data.__futex field, reshuffle __data.__clock. + * sysdeps/unix/sysv/linux/i386/pthread_cond_signal.S + (__pthread_cond_signal): Increment __futex at the same time as + __wakeup_seq or __total_seq. Pass address of __futex instead of + address of low 32-bits of __wakeup_seq to futex syscall. + * sysdeps/unix/sysv/linux/i386/pthread_cond_wait.S + (__pthread_cond_wait): Likewise. Pass __futex value from before + releasing internal lock to FUTEX_WAIT. + * sysdeps/unix/sysv/linux/i386/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Likewise. + * sysdeps/unix/sysv/linux/i386/pthread_cond_broadcast.S + (FUTEX_CMP_REQUEUE): Define. + (__pthread_cond_broadcast): Set __futex to 2 * __total_seq. + Use FUTEX_CMP_REQUEUE operation instead of FUTEX_REQUEUE. + Pass __futex value from before the unlock and __futex address instead + of address of low 32-bits of __wakeup_seq to futex syscall. + Fallback to FUTEX_WAKE all on any errors. + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h (FUTEX_CMP_REQUEUE): + Define. + (lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE + internally. Return non-zero if error, zero if success. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_cond_t): + Add __data.__futex field, reshuffle __data.__clock. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h (FUTEX_CMP_REQUEUE): + Define. + (lll_futex_requeue): Add val argument, return 1 unconditionally + for the time being. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h (pthread_cond_t): + Add __data.__futex field, reshuffle __data.__clock. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (FUTEX_CMP_REQUEUE): + Define. + (lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE + internally. Return non-zero if error, zero if success. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h + (pthread_cond_t): Add __data.__futex field, reshuffle __data.__clock. + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h (FUTEX_CMP_REQUEUE): + Define. + (lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE + internally. Return non-zero if error, zero if success. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h (pthread_cond_t): + Add __data.__futex field, reshuffle __data.__clock. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (FUTEX_CMP_REQUEUE): + Define. + (lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE + internally. Return non-zero if error, zero if success. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h (pthread_cond_t): + Add __data.__futex field, reshuffle __data.__clock. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h (pthread_cond_t): + Add __data.__futex field, reshuffle __data.__clock. + * sysdeps/pthread/pthread_cond_signal.c (__pthread_cond_signal): + Increment __futex at the same time as __wakeup_seq or __total_seq. + Pass address of __futex instead of address of low 32-bits of + __wakeup_seq to futex syscall. + * sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): Likewise. + Pass __futex value from before releasing internal lock + to FUTEX_WAIT. + * sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait): + Likewise. Avoid unnecessary shadowing of variables. + * sysdeps/pthread/pthread_cond_broadcast.c (__pthread_cond_broadcast): + Set __futex to 2 * __total_seq. Pass __futex value from before the + unlock and __futex address instead of address of low 32-bits of + __wakeup_seq to futex_requeue macro, adjust for new return value + meaning. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S + (__pthread_cond_signal): Increment __futex at the same time as + __wakeup_seq or __total_seq. Pass address of __futex instead of + address of low 32-bits of __wakeup_seq to futex syscall. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S + (__pthread_cond_wait): Likewise. Pass __futex value from before + releasing internal lock to FUTEX_WAIT. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S + (FUTEX_CMP_REQUEUE): Define. + (__pthread_cond_broadcast): Set __futex to 2 * __total_seq. + Use FUTEX_CMP_REQUEUE operation instead of FUTEX_REQUEUE. + Pass __futex value from before the unlock and __futex address instead + of address of low 32-bits of __wakeup_seq to futex syscall. + Fallback to FUTEX_WAKE all on any errors. + +2004-06-03 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/lowlevellock.h (lll_mutex_lock): + Add nop to align the end of critical section. + (lll_mutex_cond_lock, lll_mutex_timedlock): Likewise. + +2004-06-01 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h (pthread_cond_t): + Add __broadcast_seq field. + * sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S: Mark + all waiters as woken with woken_seq and bump broadcast counter. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Use new + __broadcast_seq. Increment __woken_seq correctly when cleanuped. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. + Comment typo fixes. Avoid returning -ETIMEDOUT. + +2004-06-01 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__condvar_tw_cleanup): Fix access to saved broadcast_seq value. + Reported by Kaz Kojima. + +2004-05-25 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/aio_misc.h: New file. + +2004-05-21 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): Compare + __broadcast_seq with bc_seq after acquiring internal lock instead of + before it. + +2004-05-18 Jakub Jelinek <jakub@redhat.com> + + * Makefile (.NOTPARALLEL): Only serialize make check/xcheck, not + compilation. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Avoid returning -ETIMEDOUT. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h + (pthread_cond_t): Add __data.__broadcast_seq field. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S + (FRAME_SIZE): Define. + (__pthread_cond_timedwait): Use it. Store/check broadcast_seq. + Comment typo fixes. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S (FRAME_SIZE): + Define. + (__pthread_cond_wait): Use it. Store/check broadcast_seq. Comment + typo fixes. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S + (__pthread_cond_broadcast): Increment broadcast_seq. Comment typo + fixes. + +2004-05-18 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/lowlevelcond.sym: Add broadcast_seq entry. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_cond_t): + Add __broadcast_seq field. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Mark + all waiters as woken with woken_seq and bump broadcast counter. + * sysdeps/pthread/pthread_cond_broadcast.c: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Use new + __broadcast_seq field. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/pthread/pthread_cond_wait.c: Likewise. + * sysdeps/pthread/pthread_cond_timedwait.c: Likewise. + * pthread_cond_init.c: Initialize __broadcast_seq field. + * Makefile (tests): Add tst-cond17 and tst-cond18. + Add .NOTPARALLEL goal. + * tst-cond16.c: New file. From Jakub. + * tst-cond17.c: New file. From Jakub. + * tst-cond18.c: New file. From Jakub. + +2004-05-16 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Correct some + unwind info. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: + Parametrize frame size. Correct some unwind info. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + +2004-05-04 Jakub Jelinek <jakub@redhat.com> + + * tst-stack3.c: Note testing functionality beyond POSIX. + +2004-05-04 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (USE___THREAD): + Change conditional from ifdef to if. + +2004-04-23 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (SYSDEP_CANCEL_ERRNO, + SYSDEP_CANCEL_ERROR): Define. + (PSEUDO): Use it. + +2004-05-01 Jakub Jelinek <jakub@redhat.com> + + * Versions (libpthread): Remove __pthread_cleanup_upto@@GLIBC_PRIVATE. + +2004-04-20 Jakub Jelinek <jakub@redhat.com> + + * sem_unlink.c (sem_unlink): Change EPERM into EACCES. + +2004-04-19 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/sem_timedwait.S: Add frame info. + Use HIDDEN_JUMPTARGET to jump to __pthread_unwind. + * sysdeps/unix/sysv/linux/sh/sem_wait.S: Remove unneeded frame + info. Use HIDDEN_JUMPTARGET to jump to __pthread_unwind. + +2004-04-19 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/timer_routines.c: Make sure helper + thread has all signals blocked. + +2004-04-18 Andreas Jaeger <aj@suse.de> + + * sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h + (SEM_VALUE_MAX): Add missing brace. + +2004-04-17 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/Makefile (tests): Add tst-mqueue8x + in rt subdir. + (CFLAGS-tst-mqueue8x.c): Add -fexceptions. + * sysdeps/pthread/tst-mqueue8x.c: New test. + * tst-cancel4.c: Update comment about message queues. + + * sysdeps/pthread/timer_gettime.c (timer_gettime): For expired timer + return it_value { 0, 0 }. + * sysdeps/pthread/timer_create.c (timer_create): Handle SIGEV_NONE + like SIGEV_SIGNAL. + * sysdeps/pthread/timer_routines.c (thread_expire_timer): Remove + assertion for SIGEV_NONE. + (thread_attr_compare): Compare all attributes, not just a partial + subset. + +2004-04-17 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/mq_notify.c: Include stdlib.h. + +2004-04-17 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/alpha/bits/semaphore.h (SEM_VALUE_MAX): + Just use a plain number. + * sysdeps/unix/sysv/linux/i386/bits/semaphore.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/semaphore.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/semaphore.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/semaphore.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/semaphore.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h: Likewise. + +2004-04-16 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Remove unneeded + frame info. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. + +2004-04-15 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/timer_routines.c: Include errno.h. + (timer_helper_thread): Use inline rt_sigtimedwait syscall instead + of calling sigwaitinfo. + +2004-04-16 Ulrich Drepper <drepper@redhat.com> + + * allocatestack.c (allocate_stack): Set reported_guardsize + unconditionally. + * pthread_getattr_np.c (pthread_getattr_np): Use + reported_guardsize instead of guardsize. + * descr.h (struct pthread): Add reported_guardsize field. + +2004-04-13 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/mq_notify.c: Shut up GCC warning. + +2004-04-12 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/mq-notify.c: New file. + +2004-04-08 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/bits/local_lim.h (MQ_PRIO_MAX): Define. + * sysdeps/unix/sysv/linux/alpha/bits/local_lim.h (MQ_PRIO_MAX): Define. + * sysdeps/unix/sysv/linux/ia64/bits/local_lim.h (MQ_PRIO_MAX): Define. + * sysdeps/unix/sysv/linux/sparc/bits/local_lim.h (MQ_PRIO_MAX): Define. + * sysdeps/unix/sysv/linux/bits/posix_opt.h (_POSIX_MESSAGE_PASSING): + Define. + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h + (_POSIX_MESSAGE_PASSING): Define. + * sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h + (_POSIX_MESSAGE_PASSING): Define. + * sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h + (_POSIX_MESSAGE_PASSING): Define. + +2004-04-04 Ulrich Drepper <drepper@redhat.com> + + * tst-context1.c (fct): Check whether correct stack is used. + +2004-04-03 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Never use + matching constraints for asm mem parameters. + + * tst-clock2.c (tf): Don't define unless needed. + +2004-03-30 H.J. Lu <hongjiu.lu@intel.com> + + * Makefile (link-libc-static): Use $(static-gnulib) instead of + $(gnulib). + +2004-03-30 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread-functions.h: Add ptr__nptl_deallocate_tsd. + * init.c (pthread_functions): Add ptr__nptl_deallocate_tsd. + * pthreadP.h: Declare __nptl_deallocate_tsd. + * pthread_create.c (deallocate_tsd): Remove to __nptl_deallocate_tsd. + Adjust caller. + + * Makefile (tests): Add tst-tsd5. + * tst-tsd5.c: New file. + +2004-03-29 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c + (__pthread_attr_setaffinity_old): Prepend GLIBC_ to version names + is SHLIB_COMPAT check. + * sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c + (__pthread_attr_getaffinity_old): Likewise. + * sysdeps/unix/sysv/linux/pthread_getaffinity.c + (__pthread_getaffinity_old): Likewise. + * sysdeps/unix/sysv/linux/pthread_setaffinity.c + (__pthread_setaffinity_old): Likewise. + +2004-03-26 Ulrich Drepper <drepper@redhat.com> + + * allocatestack.c (_make_stacks_executable): Call + _dl_make_stack_executable first. + +2004-03-24 Roland McGrath <roland@redhat.com> + + * sysdeps/i386/pthread_spin_lock.c (pthread_spin_lock): Use "m" + constraint instead of "0". + +2004-03-24 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h + (lll_mutex_cond_trylock): Define as wrapper around __lll_cond_trylock. + + * sysdeps/unix/sysv/linux/getpid.c (really_getpid): Reorganize + code to avoid warning. + +2004-03-24 Andreas Jaeger <aj@suse.de> + + * sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c + (__pthread_attr_setaffinity_old): Remove const. + +2004-03-23 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/smp.h: New file. + * sysdeps/unix/sysv/linux/sh/smp.h: New file. + * init.c: Define __is_smp. + (__pthread_initialize_minimal_internal): Call is_smp_system to + initialize __is_smp. + * pthreadP.h: Declare __is_smp. + Define MAX_ADAPTIVE_COUNT is necessary. + * pthread_mutex_init.c: Add comment regarding __spins field. + * pthread_mutex_lock.c: Implement adaptive mutex type. + * pthread_mutex_timedlock.c: Likewise. + * sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c: Likewise. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_mutex_t): + Add __spins field. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h: Define + lll_mutex_cond_trylock. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise. + Define BUSY_WAIT_NOP. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + + * tst-mutex5.c: Add support for testing adaptive mutexes. + * tst-mutex7.c: Likewise. + * tst-mutex5a.c: New file. + * tst-mutex7a.c: New file. + * Makefile (tests): Add tst-mutex5a and tst-mutex7a. + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S + (__lll_mutex_timedlock_wait): Preserve r8 and r9 since the + vgettimeofday call might destroy the content. + + * sysdeps/ia64/pthread_spin_lock.c (pthread_spin_lock): Use hint + @pause in the loop. + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_mutex_trylock): + No need to restrict type of ret. Make it int. Add comment. + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_mutex_trylock): + Remove unnecessary setne instruction. + +2004-03-22 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/pthread_getaffinity.c + (__pthread_getaffinity_new): Use INT_MAX instead of UINT_MAX. + * pthread_getattr_np.c (pthread_getattr_np): Double size every cycle. + If realloc fails, break out of the loop. + +2004-03-20 Andreas Jaeger <aj@suse.de> + + * sysdeps/unix/sysv/linux/pthread_setaffinity.c + (__pthread_setaffinity_old): Fix interface. + * sysdeps/unix/sysv/linux/pthread_getaffinity.c + (__pthread_getaffinity_old): Likewise. + + * sysdeps/unix/sysv/linux/pthread_setaffinity.c + (__pthread_setaffinity_new): Remove duplicate declaration. + +2004-03-20 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h (CENABLE): Save + the return value to a safe register. + (CDISABLE): Set the function argument correctly. + +2004-03-17 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h (XCHG): Define. + * sysdeps/unix/sysv/linux/sh/lowlevellock.S (__lll_mutex_lock_wait): + Rewrite so that only one locked memory operation per round is needed. + * sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S + (pthread_barrier_wait): After wakeup, release lock only when the + last thread stopped using the barrier object. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S + (__pthread_cond_wait): Don't store mutex address if the current + value is ~0l. Add correct cleanup support and unwind info. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S + (__pthread_cond_broadcast): Don't use requeue for pshared condvars. + * sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S: Update comment. + * sysdeps/unix/sysv/linux/sh/pthread_once.S (__pthread_once): + Add correct cleanup support and unwind info. + * sysdeps/unix/sysv/linux/sh/sem_wait.S (__new_sem_wait): Likewise. + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: Add unwind + information for syscall wrappers. + +2004-03-18 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/internaltypes.h (struct pthread_attr): Add + cpusetsize field, remove next. + * sysdeps/pthread/pthread.h (pthread_getaffinity_np): Add new second + parameter for size of the CPU set. + (pthread_setaffinity_np): Likewise. + (pthread_attr_getaffinity_np): Likewise. + (pthread_attr_setaffinity_np): Likewise. + * sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c: Implement + interface change, keep compatibility code. + * sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c: Likewise. + * sysdeps/unix/sysv/linux/pthread_getaffinity.c: Likewise. + * sysdeps/unix/sysv/linux/pthread_setaffinity.c: Likewise. + * pthreadP.h: Remove hidden_proto for pthread_getaffinity_np. Declare + __pthread_getaffinity_np. + * Versions: Add version for changed interfaces. + * tst-attr3.c: Adjust test for interface change. + * pthread_getattr_np.c: Query the kernel about the affinity mask with + increasing buffer sizes. + * pthread_attr_destroy.c: Remove unused list handling. + * pthread_attr_init.c: Likewise. + +2004-03-17 Roland McGrath <roland@redhat.com> + + * sysdeps/unix/sysv/linux/timer_create.c (timer_create): Pass missing + first argument to clock_getres so we ever enable kernel timers. + +2004-03-15 Ulrich Weigand <uweigand@de.ibm.com> + + * init.c (nptl_version): Add __attribute_used__ to nptl_version. + +2004-03-12 Richard Henderson <rth@redhat.com> + + * sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h: Propagate + oldvalue from CENABLE to CDISABLE. + +2004-03-12 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/bits/local_lim.h: Define HOST_NAME_MAX. + * sysdeps/unix/sysv/linux/alpha/bits/local_lim.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/local_lim.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/local_lim.h: Likewise. + +2004-03-11 Richard Henderson <rth@redhat.com> + + * sysdeps/alpha/tcb-offsets.sym (PID_OFFSET): New. + * sysdeps/unix/sysv/linux/alpha/pt-vfork.S: Save/restore PID. + * sysdeps/unix/sysv/linux/alpha/vfork.S: New file. + +2004-03-11 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/s390/s390-64/vfork.S (__vfork): Use jgnl + instead of jnl instruction to jump to SYSCALL_ERROR_LABEL. + * sysdeps/unix/sysv/linux/s390/s390-64/pt-vfork.S (__vfork): Likewise. + +2004-03-11 Jakub Jelinek <jakub@redhat.com> + + * forward.c (__pthread_cond_broadcast_2_0, + __pthread_cond_destroy_2_0, __pthread_cond_init_2_0, + __pthread_cond_signal_2_0, __pthread_cond_wait_2_0, + __pthread_cond_timedwait_2_0): Use return 0 as defaction instead of 0. + +2004-03-11 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/sh/tcb-offsets.sym: Add PID. + * sysdeps/unix/sysv/linux/sh/pt-vfork.S: Properly handle PID cache. + * sysdeps/unix/sysv/linux/sh/vfork.S: New file. + +2004-03-10 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S: No need to + include <sysdep-cancel.h>, vfork is no cancellation point. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/pt-vfork.S: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/pt-vfork.S: Likewise. + +2004-03-10 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/s390/s390-32/vfork.S (__vfork): Add + libc_hidden_def. + * sysdeps/unix/sysv/linux/s390/s390-64/vfork.S (__vfork): Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S (__vfork): + Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S (__vfork): + Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S (__vfork): Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S (__vfork): Likewise. + * sysdeps/unix/sysv/linux/ia64/pt-vfork.S: Include tcb-offsets.h. + * sysdeps/unix/sysv/linux/ia64/vfork.S (__vfork): Use DO_CALL instead + of DO_CALL_VIA_BREAK. Work around a gas problem. + + * sysdeps/unix/sysv/linux/powerpc/pt-vfork.S: Remove. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/pt-vfork.S: New file. + * sysdeps/powerpc/tcb-offsets.sym: Add PID. + + * sysdeps/unix/sysv/linux/ia64/pt-vfork.S (__vfork): Don't use + a local register for saving old PID. Negate PID in parent upon exit. + + * sysdeps/unix/sysv/linux/s390/s390-32/pt-vfork.S: Include + tcb-offsets.h. + (__vfork): Negate PID if non-zero and set to INT_MIN if zero + before syscall, set to the old value in the parent afterwards. + * sysdeps/unix/sysv/linux/s390/s390-32/vfork.S: New file. + * sysdeps/unix/sysv/linux/s390/s390-64/pt-vfork.S: Include + tcb-offsets.h. + (__vfork): Negate PID if non-zero and set to INT_MIN if zero + before syscall, set to the old value in the parent afterwards. + * sysdeps/unix/sysv/linux/s390/s390-64/vfork.S: New file. + * sysdeps/s390/tcb-offsets.sym: Add PID. + + * sysdeps/unix/sysv/linux/sparc/pt-vfork.S: Remove. + * sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S: New file. + * sysdeps/unix/sysv/linux/sparc/sparc64/pt-vfork.S: New file. + * sysdeps/sparc/tcb-offsets.sym: Add PID. + +2004-03-10 Andreas Schwab <schwab@suse.de> + + * sysdeps/ia64/tcb-offsets.sym: Add PID. + * sysdeps/unix/sysv/linux/ia64/vfork.S: New file. + * sysdeps/unix/sysv/linux/ia64/pt-vfork.S: Properly handle PID cache. + +2004-03-09 Jakub Jelinek <jakub@redhat.com> + + * tst-cancel20.c (do_one_test): Clear in_sh_body first. + * tst-cancel21.c (do_one_test): Likewise. + Reported by Gordon Jin <gordon.jin@intel.com>. + +2004-02-09 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/i386/vfork.S (SAVE_PID): Negate PID + if non-zero and set to INT_MIN if zero. + * sysdeps/unix/sysv/linux/x86_64/vfork.S (SAVE_PID): Likewise. + * sysdeps/unix/sysv/linux/i386/pt-vfork.S: Include tcb-offsets.h. + (SAVE_PID, RESTORE_PID): Define. + (__vfork): Use it. + * sysdeps/unix/sysv/linux/x86_64/pt-vfork.S: Include tcb-offsets.h. + Use relative path to avoid including NPTL i386/vfork.S. + (SAVE_PID, RESTORE_PID): Define. + * sysdeps/unix/sysv/linux/raise.c: Include limits.h. + (raise): Handle THREAD_SELF->pid INT_MIN the same as 0. + * Makefile (tests): Add tst-vfork1, tst-vfork2, tst-vfork1x and + tst-vfork2x. + (tests-reverse): Add tst-vfork1x and tst-vfork2x. + * tst-vfork1.c: New test. + * tst-vfork2.c: New test. + * tst-vfork1x.c: New test. + * tst-vfork2x.c: New test. + +2004-03-08 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/i386/tcb-offsets.sym: Add PID. + * sysdeps/x86_64/tcb-offsets.sym: Likewise. + * sysdeps/unix/sysv/linux/i386/vfork.S: New file. + * sysdeps/unix/sysv/linux/x86_64/vfork.S: New file. + +2004-03-08 Steven Munroe <sjmunroe@us.ibm.com> + + * sysdeps/unix/sysv/linux/powerpc/Versions: Remove leading tabs. + +2004-03-08 H.J. Lu <hongjiu.lu@intel.com> + + * sysdeps/s390/tls.h (INIT_SYSINFO): _dl_sysinfo is now in + _rtld_global_ro. + +2004-03-07 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/ia64/tls.h (INIT_SYSINFO): _dl_sysinfo is now in + _rtld_global_ro. + + * tst-once4.c: Remove unnecessary macro definition. + + * tst-mutex7.c (do_test): Limit thread stack size. + * tst-once2.c (do_test): Likewise. + * tst-tls3.c (do_test): Likewise. + * tst-tls1.c (do_test): Likewise. + * tst-signal3.c (do_test): Likewise. + * tst-kill6.c (do_test): Likewise. + * tst-key4.c (do_test): Likewise. + * tst-join4.c (do_test): Likewise. + * tst-fork1.c (do_test): Likewise. + * tst-context1.c (do_test): Likewise. + * tst-cond2.c (do_test): Likewise. + * tst-cond10.c (do_test): Likewise. + * tst-clock2.c (do_test): Likewise. + * tst-cancel10.c (do_test): Likewise. + * tst-basic2.c (do_test): Likewise. + * tst-barrier4.c (do_test): Likewise. + +2004-03-05 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/i386/tls.h: Use GLRO instead of GL where appropriate. + +2004-03-01 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Optimize wakeup test. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S + (__pthread_cond_wait): Likewise. + * sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): Likewise. + * sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait): + Likewise. + +2004-02-29 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S + (__lll_mutex_lock_wait): Optimize a bit more. Just one copy of + the atomic instruction needed. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S + (__lll_mutex_lock_wait): Likewise. + +2004-02-28 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-cond14 and tst-cond15. + * tst-cond14.c: New file. + * tst-cond15.c: New file. + +2004-02-27 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/createthread.c (create_thread): Remove use of + CLONE_STOPPED. We cannot use SIGCONT which means CLONE_STOPPED + needs to be implemented differently to be useful. + +2004-02-26 Ulrich Drepper <drepper@redhat.com> + + * pthread_attr_setschedparam.c: Don't test priority against limits + here. Set ATTR_FLAG_SCHED_SET flag. + * pthread_attr_setschedpolicy.c: Set ATTR_FLAG_POLICY_SET flag. + * pthread_create.c (__pthread_create_2_1): Copy scheduling attributes + from parent thread to child. If attribute is used and scheduling + parameters are not inherited, copy parameters from attribute or + compute them. Check priority value. + * pthread_getschedparam.c: If the parameters aren't known yet get + them from the kernel. + * pthread_setschedparam.c: Set ATTR_FLAG_SCHED_SET and + ATTR_FLAG_POLICY_SET flag for thread. + * sysdeps/unix/sysv/linux/internaltypes.h: Define ATTR_FLAG_SCHED_SET + and ATTR_FLAG_POLICY_SET. + + * sysdeps/pthread/createthread.c: Use tgkill if possible. + + * pthread_attr_getstackaddr.c (__pthread_attr_getstackaddr): Don't + fail if stack address hasn't been set. Just return 0. + +2004-02-25 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests-nolibpthread): Add tst-unload. Don't link with + libpthread for the files in this list. + (CFLAGS-tst-unload): Removed. + * tst-unload.c (do_test): Don't use complete path for + LIBPHREAD_SO. + + * Makefile: Define sonames for tst-tls5mod, tst-_res1mod1, and + tst-_res1mod2. + +2004-02-22 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S + (__lll_mutex_lock_wait): Rewrite so that only one locked memory + operation per round is needed. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S + (__lll_mutex_lock_wait): Likewise. + +2004-02-20 Ulrich Drepper <drepper@redhat.com> + + * tst-cancel9.c (cleanup): Don't print to stderr. + +2004-02-20 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/sh/jmpbuf-unwind.h (_JMPBUF_UNWINDS_ADJ): Fix variable name. + +2004-02-20 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h + (__syscall_error_handler2): Call CDISABLE. + * sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h + (__syscall_error_handler2): Call CDISABLE. + + * sysdeps/pthread/pthread_barrier_wait.c (pthread_barrier_wait): + Release lock before the loop, don't reacquire it. + + * sysdeps/unix/sysv/linux/ia64/dl-sysdep.h (DL_ARGV_NOT_RELRO): Define. + +2004-02-19 Andreas Schwab <schwab@suse.de> + + * sysdeps/pthread/pthread_barrier_wait.c (pthread_barrier_wait): + Fix last change. + +2004-02-18 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S + (pthread_barrier_wait): After wakeup, release lock only when the + last thread stopped using the barrier object. + * sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S + (pthread_barrier_wait): Likewise. + * sysdeps/pthread/pthread_barrier_wait.c (pthread_barrier_wait): + Likewise. + * Makefile (tests): Add tst-barrier4. + * tst-barrier4.c: New file. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Perform timeout test while holding + internal lock to prevent wakeup race. + Patch by Dinakar Guniguntala <dgunigun@in.ibm.com>. + * sysdeps/pthread/pthread_cond_timedwait.c + (__pthread_cond_timedwait): Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Likewise. + +2004-02-18 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S + (__pthread_rwlock_unlock): Access WRITER as 32-bit value. + * Makefile (tests): Add tst-rwlock13. + * tst-rwlock13.c: New test. + +2004-02-16 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__condvar_tw_cleanup): Little optimization. + Patch by Dinakar Guniguntala <dgunigun@in.ibm.com>. + +2004-02-16 Steven Munroe <sjmunroe@us.ibm.com> + + * sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c: Replace libc with + libpthread as "lib" parameter to SHLIB_COMPAT. + (__novmx_siglongjmp): Fix typo in function name. + (__novmx_longjmp): Fix typo in function name. + +2004-02-13 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): Add a + __builtin_expect. + + * sysdeps/generic/pt-longjmp.c: Moved to... + * sysdeps/pthread/pt-longjmp.c: ...here. New file. + +2004-01-29 Steven Munroe <sjmunroe@us.ibm.com> + + * Makefile (libpthread-routines): Add pt-cleanup. + * pt-longjmp.c: Removed. + * pt-cleanup.c: Copied __pthread_cleanup_upto to here. New file. + * sysdeps/generic/pt-longjmp.c: Copied longjmp to here. New file. + * sysdeps/unix/sysv/linux/powerpc/Versions: New file. + Version longjmp, siglongjmp for GLIBC_2.3.4. + * sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c: New File. + +2004-02-13 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread_cond_timedwait.c + (__pthread_cond_timedwait): Optimize. Drop internal lock earlier. + Reuse code. Add __builtin_expects. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Get internal lock in case timeout has + passed before the futex syscall. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + +2004-01-20 Ulrich Drepper <drepper@redhat.com> + + * allocatestack.c: Pretty printing. + + * sysdeps/pthread/createthread.c (create_thread): Don't add + CLONE_DETACHED bit if it is not necessary. + +2004-01-16 Ulrich Drepper <drepper@redhat.com> + + * pthread_getattr_np.c: Include ldsodefs.h. + +2004-01-16 Richard Henderson <rth@redhat.com> + + * allocatestack.c: Don't declare __libc_stack_end. + * init.c (__pthread_initialize_minimal_internal): Likewise. + * pthread_getattr_np.c (pthread_getattr_np): Likewise. + +2004-01-15 Richard Henderson <rth@redhat.com> + + * sysdeps/alpha/tls.h (tcbhead_t): Add private. + (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN, TLS_TCB_SIZE, + TLS_PRE_TCB_SIZE, TLS_TCB_ALIGN, INSTALL_DTV, INSTALL_NEW_DTV, + GET_DTV, THREAD_DTV, THREAD_SELF, DB_THREAD_SELF): Match ia64. + (TLS_TCB_OFFSET, THREAD_ID, NO_TLS_OFFSET): Remove. + (THREAD_GETMEM, THREAD_GETMEM_NC): Simplify. + (THREAD_SETMEM, THREAD_SETMEM_NC): Likewise. + * sysdeps/unix/sysv/linux/alpha/createthread.c (TLS_VALUE): Match ia64. + +2004-01-14 Ulrich Drepper <drepper@redhat.com> + + * init.c (pthread_functions): Make array const. + +2004-01-13 Ulrich Drepper <drepper@redhat.com> + + * allocatestack.c (__make_stacks_executable): Change interface. + Check parameters. Pass parameter on to libc counterpart. + * pthreadP.h: Change declaration. + +2004-01-13 Richard Henderson <rth@redhat.com> + + * pthread_attr_setstack.c (__old_pthread_attr_setstack): Use + prototype form. + * pthread_attr_setstacksize.c (__old_pthread_attr_setstacksize): + Likewise. + + * sysdeps/alpha/Makefile: New file. + * sysdeps/alpha/tcb-offsets.sym: New file. + * sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h (SINGLE_THREAD_P): + Use MULTIPLE_THREADS_OFFSET to implement !libpthread !libc version. + + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h: Rewrite based + on powerpc version. + +2004-01-08 Jakub Jelinek <jakub@redhat.com> + + * Makefile (tests): Add tst-backtrace1. + * tst-backtrace1.c: New test. + +2003-12-11 Ulrich Weigand <uweigand@de.ibm.com> + + * sysdeps/alpha/tls.h (DB_THREAD_SELF): Pass bit size of thread + register as second parameter to the REGISTER macro. + * sysdeps/ia64/tls.h (DB_THREAD_SELF): Likewise. + * sysdeps/powerpc/tls.h (DB_THREAD_SELF): Likewise. + * sysdeps/sh/tls.h (DB_THREAD_SELF): Likewise. + * sysdeps/sparc/tls.h (DB_THREAD_SELF): Likewise. + * sysdeps/s390/tls.h (DB_THREAD_SELF): Pass __WORDSIZE as bit size + of thread register as second parameter to REGISTER macro in 64 case. + +2004-01-03 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/Makefile (CFLAGS-getpid.c): Removed. + (CFLAGS-getpid.o): Defined. + (CFLAGS-getpid.os): Defined. + +2003-12-31 Ulrich Drepper <drepper@redhat.com> + + * pthread_getattr_np.c (pthread_getattr_np): Make sure stack info + returned for main thread does not overlap with any other VMA. + Patch by Jakub Jelinek. + +2003-12-29 Jakub Jelinek <jakub@redhat.com> + + * tst-raise1.c: Include stdio.h. + +2003-12-23 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/raise.c (raise): Protect pid = selftid + setting with __ASSUME_TGKILL || defined __NR_tgkill. + If pid is 0, set it to selftid. + * sysdeps/unix/sysv/linux/getpid.c (really_getpid): Make inline. + Don't set self->pid but self->tid. If self->pid == 0 and self->tid + != 0, return self->tid without doing a syscall. + * descr.h (struct pthread): Move pid field after tid. + + * Makefile (tests): Add tst-raise1. + * tst-raise1.c: New file. + +2003-12-23 Roland McGrath <roland@redhat.com> + + * tst-oddstacklimit.c: New file. + * Makefile (tests): Add it. + (tst-oddstacklimit-ENV): New variable. + + * init.c (__pthread_initialize_minimal_internal): Round stack rlimit + value up to page size for __default_stacksize. + +2003-12-21 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-eintr5. + * tst-eintr5.c: New file. + + * eintr.c (eintr_source): Prevent sending signal to self. + + * tst-eintr2.c (tf1): Improve error message. + +2003-12-20 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/Makefile (CFLAGS-getpid.c): Define. + * sysdeps/unix/sysv/linux/getpid.c: New file. + * pthread_cancel.c: Add comment explaining use of PID field. + * sysdeps/unix/sysv/linux/pthread_kill.c: Likewise. + * pthread_getattr_np.c: Use abs() when comparing PID and TID fields. + * sysdeps/unix/sysv/linux/fork.c: Negate PID field of parent + temporarily to signal the field must not be relied on and updated + by getpid(). + * sysdeps/unix/sysv/linux/pt-raise.c: Handle case where PID is + temporarily negative. + * sysdeps/unix/sysv/linux/raise.c: Likewise. + +2003-12-19 Ulrich Drepper <drepper@redhat.com> + + * eintr.c (setup_eintr): Add new parameter. Pass to thread function. + (eintr_source): If ARG != NULL, use pthread_kill. + * tst-eintr1.c: Adjust for this change. + * tst-eintr2.c: Likewise. + * Makefile (tests): Add tst-eintr3 and tst-eintr4. + * tst-eintr3.c: New file. + * tst-eintr4.c: New file. + +2003-12-19 Jakub Jelinek <jakub@redhat.com> + + * libc-cancellation.c (__libc_enable_asynccancel): Don't cancel + if CANCELSTATE_BITMASK is set. + * sysdeps/pthread/librt-cancellation.c (__librt_enable_asynccancel): + Likewise. + + * Makefile (tests): Add tst-cancel22 and tst-cancel23. + (tests-reverse): Add tst-cancel23. + * tst-cancel22.c: New test. + * tst-cancel23.c: New test. + +2003-12-18 Ulrich Drepper <drepper@redhat.com> + + * tst-eintr1.c: Better error messages. + + * Makefile (tests): Add tst-eintr2. + * tst-eintr2.c: New file. + +2003-12-18 Jakub Jelinek <jakub@redhat.com> + + * Makefile (tests): Add tst-cancel21 and tst-cancelx21. + (CFLAGS-tst-cancelx21.c): Set. + * tst-cancel21.c: New test. + * tst-cancelx21.c: New test. + + * unwind.c (FRAME_LEFT): Add adj argument. Subtract it from each + comparison operand. + (unwind_stop): Use _JMPBUF_CFA_UNWINDS_ADJ macro instead of + _JMPBUF_CFA_UNWINDS. Adjust FRAME_LEFT invocations. + * pt-longjmp.c: Include jmpbuf-unwind.h. + (__pthread_cleanup_upto): Use _JMPBUF_UNWINDS_ADJ macro instead of + _JMPBUF_UNWINDS. Adjust compared pointers. + * init.c (__pthread_initialize_minimal_internal): Initialize + pd->stackblock_size. + * sysdeps/pthread/jmpbuf-unwind.h: Removed. + * sysdeps/alpha/jmpbuf-unwind.h: New file. + * sysdeps/i386/jmpbuf-unwind.h: New file. + * sysdeps/powerpc/jmpbuf-unwind.h: New file. + * sysdeps/s390/jmpbuf-unwind.h: New file. + * sysdeps/sh/jmpbuf-unwind.h: New file. + * sysdeps/sparc/sparc32/jmpbuf-unwind.h: New file. + * sysdeps/x86_64/jmpbuf-unwind.h: New file. + * sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h: Include stdint.h. + (_JMPBUF_CFA_UNWINDS): Remove. + (_JMPBUF_CFA_UNWINDS_ADJ, _JMPBUF_UNWINDS_ADJ): Define. + +2003-12-12 Jakub Jelinek <jakub@redhat.com> + + * Makefile (tests): Add tst-cancel20 and tst-cancelx20. + (CFLAGS-tst-cancelx20.c): Set. + * tst-cancel20.c: New test. + * tst-cancelx20.c: New test. + +2003-12-17 Ulrich Drepper <drepper@redhat.com> + + * init.c (__pthread_initialize_minimal_internal): Don't treat + architectures with separate register stack special here when + computing default stack size. + +2003-12-17 Roland McGrath <roland@redhat.com> + + * Makefile (tst-cancelx7-ARGS): New variable. + Reportd by Greg Schafer <gschafer@zip.com.au>. + +2003-12-17 Jakub Jelinek <jakub@redhat.com> + + * Makefile (tests): Add tst-stack3. Depend on $(objpfx)tst-stack3-mem. + (generated): Add tst-stack3.mtrace and tst-stack3-mem. + (tst-stack3-ENV): Set. + ($(objpfx)tst-stack3-mem): New. + * tst-stack3.c: New test. + +2003-12-10 David Mosberger <davidm@hpl.hp.com> + + * sysdeps/unix/sysv/linux/ia64/pt-initfini.c (_init_EPILOG_BEGINS): + Add unwind directives. Drop unused .regstk directive. + (_fini_EPILOG_BEGINS): Add unwind directives. + +2003-12-11 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_futex_wait): + Assume parameter is a pointer. + (lll_futex_wake): Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (lll_futex_wait): + Likewise. + (lll_futex_wake): Likewise. + Reported by Boris Hu. + * sysdeps/unix/sysv/linux/unregister-atfork.c + (__unregister_atfork): Pass pointer to refcntr to lll_futex_wait. + + * sysdeps/unix/sysv/linux/sem_wait.c (__new_sem_wait): Simplify a bit. + +2003-12-10 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/bits/libc-lock.h (__rtld_lock_initialize): Define. + * sysdeps/unix/sysv/linux/fork.c (__libc_fork): Call + __rtld_lock_initialize for ld.so lock. + Patch in part by Adam Li <adam.li@intel.com>. + +2003-12-02 David Mosberger <davidm@hpl.hp.com> + + * Makefile (link-libc-static): Remove -lgcc_eh---it's already mentioned + in $(gnulib). Also, remove stale comment. + +2003-11-12 David Mosberger <davidm@hpl.hp.com> + + * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (PSEUDO): Take + advantage of new syscall stub and optimize accordingly. + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (__NR_futex): Rename + from SYS_futex, to match expectations of + sysdep.h:DO_INLINE_SYSCALL. + (lll_futex_clobbers): Remove. + (lll_futex_timed_wait): Rewrite in terms of DO_INLINE_SYSCALL. + (lll_futex_wake): Likewise. + (lll_futex_requeue): Likewise. + (__lll_mutex_trylock): Rewrite to a macro, so we can include this + file before DO_INLINE_SYSCALL is defined (proposed by Jakub + Jelinek). + (__lll_mutex_lock): Likewise. + (__lll_mutex_cond_lock): Likewise. + (__lll_mutex_timed_lock): Likewise. + (__lll_mutex_unlock): Likewise. + (__lll_mutex_unlock_force): Likewise. + + * sysdeps/ia64/tls.h: Move declaration of __thread_self up so it + comes before the include of <sysdep.h>. + (THREAD_SELF_SYSINFO): New macro. + (THREAD_SYSINFO): Likewise. + (INIT_SYSINFO): New macro. + (TLS_INIT_TP): Call INIT_SYSINFO. + + * sysdeps/ia64/tcb-offsets.sym: Add SYSINFO_OFFSET. + + * sysdeps/pthread/createthread.c (create_thread): Use + THREAD_SELF_SYSINFO and THREAD_SYSINFO instead of open code. + * allocatestack.c (allocate_stack): Use THREAD_SYSINFO and + THREAD_SELF_SYSINFO instead of open code. + * sysdeps/i386/tls.h (THREAD_SELF_SYSINFO): New macro. + (THREAD_SYSINFO): Likewise. + + * sysdeps/unix/sysv/linux/ia64/dl-sysdep.h: New file. + + * sysdeps/unix/sysv/linux/ia64/pt-vfork.S: Work around gas problem. + +2003-12-06 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/ia64/pt-initfini.c: Use .init_array + instead of .init. Patch by David Mosberger. + +2003-11-30 Thorsten Kukuk <kukuk@suse.de> + + * sysdeps/pthread/configure.in: Remove broken declaration in C + cleanup handling check. + +2003-11-30 Andreas Jaeger <aj@suse.de> + + * Makefile (CFLAGS-pt-initfini.s): Add $(fno_unit_at_a_time). + * sysdeps/unix/sysv/linux/x86_64/Makefile (CFLAGS-pt-initfini.s): + Likewise. + +2003-11-27 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/internaltypes.h (ATTR_FLAG_OLDATTR): Define. + * pthread_attr_destroy.c: Include shlib-compat.h. + (__pthread_attr_destroy): Return immediately if ATTR_FLAG_OLDATTR + is set in iattr->flags. + * pthread_attr_init.c (__pthread_attr_init_2_0): Set ATTR_FLAG_OLDATTR. + +2003-11-21 Jakub Jelinek <jakub@redhat.com> + + * Makefile (distribute): Add tst-cleanup4aux.c. + + * tst-cond12.c (prepare): Add prototype. Move after test-skeleton.c + include. + +2003-11-21 Ulrich Drepper <drepper@redhat.com> + + * tst-cond12.c (do_test): If USE_COND_SIGNAL is defined, use + pthread_cond_signal. + + * sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): Don't + store mutex address if the current value is ~0l. + * sysdeps/pthread/pthread_cond_timedwait.c + (__pthread_cond_timedwait): Likewise. + * sysdeps/pthread/pthread_cond_broadcast.c + (__pthread_cond_broadcast): Don't use requeue for pshared + condvars. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S + (__pthread_cond_wait): Don't store mutex address if the current + value is ~0l. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S + (__pthread_cond_broadcast): Don't use requeue for pshared + condvars. + + * pthread_cond_init.c (__pthread_cond_init): Initialize __mutex + element with ~0l for pshared condvars, with NULL otherwise. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S + (__pthread_cond_wait): Don't store mutex address if the current + value is ~0l. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S + (__pthread_cond_broadcast): Don't use requeue for pshared + condvars. + + * Makefile: Add rules to build and run tst-cond12 and tst-cond13. + * tst-cond12.c: New file. + * tst-cond13.c: New file. + +2003-11-17 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/configure.in: Make missing forced unwind support + fatal. + +2003-11-11 Ulrich Drepper <drepper@redhat.com> + + * pthreadP.h: Don't declare __pthread_unwind as weak inside libpthread. + +2003-11-06 Ulrich Drepper <drepper@redhat.com> + + * Makefile: Add magic to clean up correctly. + +2003-11-05 Jakub Jelinek <jakub@redhat.com> + + * unwind.c (FRAME_LEFT): Define. + (unwind_stop): Handle old style cleanups here. + (__pthread_unwind): Handle old style cleanups only if + !HAVE_FORCED_UNWIND. + * Makefile (tests): Add tst-cleanup4 and tst-cleanupx4. + (CFLAGS-tst-cleanupx4.c): Add -fexceptions. + ($(objpfx)tst-cleanup4): Depend on $(objpfx)tst-cleanup4aux.o. + ($(objpfx)tst-cleanupx4): Likewise. + * tst-cleanup4.c: New test. + * tst-cleanup4aux.c: New. + * tst-cleanupx4.c: New test. + +2003-11-04 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/bits/stdio-lock.h: Use lll_*lock instead of + lll_mutex_*lock macros to skip atomic operations on some archs. + +2003-11-03 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/tst-timer.c (main): Initialize + sigev2.sigev_value as well. + +2003-10-15 Roland McGrath <roland@redhat.com> + + * sysdeps/pthread/configure.in: Barf if visibility attribute support + is missing. + * sysdeps/pthread/configure: Regenerated. + +2003-10-09 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/unix/sysv/linux/sh/lowlevellock.h: Completely revamp the + locking macros. No distinction between normal and mutex locking + anymore. + * sysdeps/unix/sysv/linux/sh/lowlevellock.S: Rewrite mutex locking. + Merge bits from lowlevelmutex.S we still need. + * sysdeps/unix/sysv/linux/sh/libc-lowlevelmutex.S: Remove. + * sysdeps/unix/sysv/linux/sh/lowlevelmutex.S: Likewise. + * sysdeps/unix/sysv/linux/sh/not-cancel.h: New file. + * sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S: Adjust for + new mutex implementation. + * sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h (PSEUDO): Also defined + symbol for entry point to avoid cancellation. + +2003-10-07 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Backout 2003-10-02 + changes. + (SAVE_OLDTYPE_0): Fix a typo. + +2003-10-03 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/pthread_once.S (__pthread_once): + Check __sigsetjmp return value. Reported by Daniel Jacobowitz. + +2003-10-02 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (DOCARGS_1): Use + correct offset. + +2003-10-02 Jakub Jelinek <jakub@redhat.com> + + * Makefile (tests): Add tst-cancel19. + * tst-cancel19.c: New test. + +2003-10-02 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Fix saving and + restoring of the old cancellation type. + +2003-09-30 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/malloc-machine.h: Remove misleading comment. + +2003-09-27 Wolfram Gloger <wg@malloc.de> + + * sysdeps/pthread/malloc-machine.h: New file + +2003-09-24 Roland McGrath <roland@redhat.com> + + * allocatestack.c (__make_stacks_executable): Don't ignore return + value from _dl_make_stack_executable. + +2003-09-24 Ulrich Drepper <drepper@redhat.com> + + * allocatestack.c (__make_stacks_executable): Also change + permission of the currently unused stacks. + + * allocatestack.c (change_stack_perm): Split out from + __make_stacks_executable. + (allocate_stack): If the required permission changed between the time + we started preparing the stack and queueing it, change the permission. + (__make_stacks_executable): Call change_stack_perm. + + * Makefile: Build tst-execstack-mod locally. + * tst-execstack-mod.c: New file. + +2003-09-23 Jakub Jelinek <jakub@redhat.com> + + * Makefile (tests): Only add tst-execstack if have-z-execstack is yes. + +2003-09-23 Roland McGrath <roland@redhat.com> + + * tst-execstack.c: New file. + * Makefile (tests): Add it. + ($(objpfx)tst-execstack, $(objpfx)tst-execstack.out): New targets. + (LDFLAGS-tst-execstack): New variable. + + * allocatestack.c (allocate_stack): Use GL(dl_stack_flags) to decide + whether to use PROT_EXEC for stack mmap. + (__make_stacks_executable): New function. + * pthreadP.h: Declare it. + * init.c (__pthread_initialize_minimal_internal): Set + GL(dl_make_stack_executable_hook) to that. + +2003-09-22 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Adjust for latest + recommendation from AMD re avoidance of lock prefix. + +2003-09-22 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/lowlevellock.c (__lll_timedlock_wait): Use + lll_futex_timed_wait instead of lll_futex_wait. + * sysdeps/unix/sysv/linux/s390/lowlevellock.c: Removed. + * sysdeps/unix/sysv/linux/s390/lowlevelmutex.c: Removed. + * sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c: Removed. + * sysdeps/unix/sysv/linux/s390/libc-lowlevelmutex.c: Removed. + * sysdeps/unix/sysv/linux/s390/sem_trywait.c: Removed. + * sysdeps/unix/sysv/linux/s390/sem_wait.c: Removed. + * sysdeps/unix/sysv/linux/s390/sem_post.c: Removed. + * sysdeps/unix/sysv/linux/s390/sem_timedwait.c: Removed. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h: Include atomic.h. + Completely revamp the locking macros. No distinction between + normal and mutex locking anymore. + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (__lll_lock_wait, + __lll_lock_timedwait): Fix prototypes. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (__lll_lock_wait, + __lll_lock_timedwait): Likewise. + (lll_mutex_lock, lll_mutex_cond_lock): Use _val instead of _bool + macros, add __builtin_expect. + (lll_mutex_timedlock): Likewise. Fix return value. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevelmutex.S: Removed. + * sysdeps/unix/sysv/linux/i386/i586/libc-lowlevelmutex.S: Removed. + * sysdeps/unix/sysv/linux/i386/i586/lowlevelmutex.S: Removed. + * sysdeps/unix/sysv/linux/i386/i686/libc-lowlevelmutex.S: Removed. + * sysdeps/unix/sysv/linux/i386/i686/lowlevelmutex.S: Removed. + * sysdeps/unix/sysv/linux/x86_64/libc-lowlevelmutex.S: Removed. + * sysdeps/unix/sysv/linux/lowlevelmutex.c: Removed. + * sysdeps/unix/sysv/linux/libc-lowlevelmutex.c: Removed. + +2003-09-22 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S + (__lll_mutex_lock_wait): Minor optimization to avoid one atomic + operation if possible. + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Don't play tricks + like jumping over the lock prefix. + +2003-09-21 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Completely revamp the + locking macros. No distinction between normal and mutex locking + anymore. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Rewrite mutex + locking. Merge bits from lowlevelmutex.S we still need. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/lowlevellock.c: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S: Removed. + * sysdeps/unix/sysv/linux/x86_64/lowlevelmutex.S: Removed. + * Makefile (routines): Remove libc-lowlevelmutex. + (libpthread-rountines): Remove lowlevelmutex. + * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: Adjust + for new mutex implementation. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S: Likewise + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise. + Don't use requeue. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise. + * sysdeps/pthread/pthread_cond_signal.c: Don't use requeue. + +2003-09-20 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Don't match memory + in parameters of asm with output parameters. + + * pthread_mutex_unlock.c (__pthread_mutex_unlock_usercnt): Change + type of DECR parameter to int. + * pthreadP.h: Adjust prototype of __pthread_mutex_unlock_usercnt. + +2003-09-18 Jakub Jelinek <jakub@redhat.com> + + * tst-attr3.c (tf, do_test): Print stack start/end/size and + guardsize for each thread. + +2003-09-17 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/pthread.h (pthread_getattr_np): Clarify usage. + * sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c + (pthread_attr_setaffinity_np): Handle cpuset == NULL. + + * sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c + (pthread_attr_getaffinity_np): Don't segfault if iattr->cpuset is + NULL. + * pthread_getattr_np.c: Set cpuset using pthread_getaffinity_np. + * pthreadP.h (pthread_getaffinity_np): Add hidden_proto. + * sysdeps/unix/sysv/linux/pthread_getaffinity.c + (pthread_getaffinity_np): Add hidden_def. + + * Makefile (tests): Add tst-attr3. + * tst-attr3.c: New test. + + * sysdeps/i386/Makefile (CFLAGS-tst-align.c): Remove. + +2003-09-15 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/i386/Makefile (CFLAGS-pthread_create.c, + CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4. + +2003-09-17 Jakub Jelinek <jakub@redhat.com> + + * Makefile (CFLAGS-tst-align.c): Add $(stack-align-test-flags). + * tst-align.c: Include tst-stack-align.h. + (tf, do_test): Use TEST_STACK_ALIGN macro. + +2003-09-17 Ulrich Drepper <drepper@redhat.com> + + * pthread_attr_init.c (__pthread_attr_init_2_0): Remove unused + variable. + +2003-09-16 Ulrich Drepper <drepper@redhat.com> + + * pthread_getattr_np.c (pthread_getattr_np): Correctly fill in the + stack-related values for the initial thread. + +2003-09-15 Jakub Jelinek <jakub@redhat.com> + + * Makefile (CFLAGS-pthread_once.c): Add $(uses-callbacks). + +2003-09-11 Ulrich Drepper <drepper@redhat.com> + + * pthread_mutex_lock.c: Minor code rearrangements. + +2003-09-05 Roland McGrath <roland@redhat.com> + + * pthread_create.c (__pthread_pthread_sizeof_descr): Removed. + Instead, include ../nptl_db/db_info.c to do its magic. + * pthread_key_create.c (__pthread_pthread_keys_max): Removed. + (__pthread_pthread_key_2ndlevel_size): Likewise. + * sysdeps/alpha/tls.h (DB_THREAD_SELF): New macro. + * sysdeps/i386/tls.h (DB_THREAD_SELF): New macro. + * sysdeps/ia64/tls.h (DB_THREAD_SELF): New macro. + * sysdeps/powerpc/tls.h (DB_THREAD_SELF): New macro. + * sysdeps/s390/tls.h (DB_THREAD_SELF): New macro. + * sysdeps/sh/tls.h (DB_THREAD_SELF): New macro. + * sysdeps/sparc/tls.h (DB_THREAD_SELF): New macro. + * sysdeps/x86_64/tls.h (DB_THREAD_SELF): New macro. + * sysdeps/alpha/td_ta_map_lwp2thr.c: File removed. + * sysdeps/generic/td_ta_map_lwp2thr.c: File removed. + * sysdeps/i386/td_ta_map_lwp2thr.c: File removed. + * sysdeps/ia64/td_ta_map_lwp2thr.c: File removed. + * sysdeps/powerpc/td_ta_map_lwp2thr.c: File removed. + * sysdeps/s390/td_ta_map_lwp2thr.c: File removed. + * sysdeps/sh/td_ta_map_lwp2thr.c: File removed. + * sysdeps/sparc/td_ta_map_lwp2thr.c: File removed. + * sysdeps/x86_64/td_ta_map_lwp2thr.c: File removed. + +2003-09-08 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Change type + of pthread_t to be compatible with LT. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise. + +2003-09-04 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/not-cancel.h (fcntl_not_cancel): Define. + +2003-09-04 Jakub Jelinek <jakub@redhat.com> + + * unwind-forcedunwind.c: Move to... + * sysdeps/pthread/unwind-forcedunwind.c: ...here. + (pthread_cancel_init): Use ARCH_CANCEL_INIT if defined. + * sysdeps/pthread/jmpbuf-unwind.h: New file. + * sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c: New file. + * sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h: New file. + * unwind.c: Include jmpbuf-unwind.h. + (unwind_stop): Use _JMPBUF_CFA_UNWINDS macro. + +2003-09-02 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/ia64/bits/local_lim.h: New file. + * sysdeps/unix/sysv/linux/ia64/Versions (libpthread): Export + pthread_attr_setstack and pthread_attr_setstacksize @@GLIBC_2.3.3. + * sysdeps/unix/sysv/linux/alpha/bits/local_lim.h: New file. + * sysdeps/unix/sysv/linux/alpha/Versions: New file. + * sysdeps/unix/sysv/linux/sparc/bits/local_lim.h: New file. + * sysdeps/unix/sysv/linux/sparc/Versions: New file. + * pthread_attr_setstack.c (__old_pthread_attr_setstack): New function. + (pthread_attr_setstack): If PTHREAD_STACK_MIN != 16384, export + as @@GLIBC_2.3.2 and also export compatibility @GLIBC_2.2. + * pthread_attr_setstacksize.c (__old_pthread_attr_setstacksize): New + function. + (pthread_attr_setstacksize): If PTHREAD_STACK_MIN != 16384, export + as @@GLIBC_2.3.2 and also export compatibility @GLIBC_2.1. + * Makefile (tests): Add tst-stack2. + * tst-stack2.c: New test. + * tst-stack1.c: Include limits.h and sys/param.h. + (do_test): Set size to MAX (4 * getpagesize (), PTHREAD_STACK_MIN). + + * pthread_condattr_setpshared.c: Include errno.h. + (pthread_condattr_setpshared): Return EINVAL if pshared + is neither PTHREAD_PROCESS_PRIVATE nor PTHREAD_PROCESS_SHARED. + + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h (PSEUDO): Also + defined symbol for entry point to avoid cancellation. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h (PSEUDO): + Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h (PSEUDO): + Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h (PSEUDO): + Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h (PSEUDO): + Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h (PSEUDO): + Likewise. + * sysdeps/unix/sysv/linux/i386/not-cancel.h (__open_nocancel, + __close_nocancel, __read_nocancel, __write_nocancel, + __waitpid_nocancel): Add attribute_hidden. If not in libc.so, + libpthread.so or librt.so, define to corresponding function + without _nocancel suffix. + * sysdeps/unix/sysv/linux/s390/not-cancel.h: New file. + * sysdeps/unix/sysv/linux/powerpc/not-cancel.h: New file. + * sysdeps/unix/sysv/linux/sparc/not-cancel.h: New file. + + * sysdeps/unix/sysv/linux/x86_64/not-cancel.h: Fix a typo. + +2003-09-02 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/not-cancel.h: New file. + * sysdeps/unix/sysv/linux/x86_64/not-cancel.h: New file. + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Make sure the code + in subsections has a symbol associated with it. + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (PSEUDO): Also + defined symbol for entry point to avoid cancellation. + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h (PSEUDO): Likewise. + +2003-09-01 Jakub Jelinek <jakub@redhat.com> + + * Makefile (tests): Add tst-tls5. + (module-names): Add tst-tls5mod{,a,b,c,d,e,f}. + ($(objpfx)tst-tls5mod{,a,b,c,d,e,f}.so-no-z-defs): Set to yes. + ($(objpfx)tst-tls5): New. + ($(objpfx)tst-tls6.out): Likewise. + (tests): Depend on $(objpfx)tst-tls6.out. + * tst-tls3.c: Include stdint.h and pthreaddef.h. + (do_test): Check pthread_self () return value alignment. + * tst-tls3mod.c: Include stdint.h and pthreaddef.h. + (tf): Check pthread_self () return value alignment. + * tst-tls5.c: New test. + * tst-tls5.h: New. + * tst-tls5mod.c: New. + * tst-tls5moda.c: New. + * tst-tls5modb.c: New. + * tst-tls5modc.c: New. + * tst-tls5modd.c: New. + * tst-tls5mode.c: New. + * tst-tls5modf.c: New. + * tst-tls6.sh: New test. + + * sysdeps/pthread/pthread-functions.h (struct pthread_functions): Add + ptr___pthread_cond_timedwait and ptr___pthread_cond_timedwait_2_0. + * init.c (pthread_functions): Initialize them. + * forward.c (pthread_cond_timedwait@GLIBC_2.0, + pthread_cond_timedwait@@GLIBC_2.3.2): New forwards. + * Versions (libc): Export pthread_cond_timedwait@GLIBC_2.0, + pthread_cond_timedwait@@GLIBC_2.3.2. + +2003-09-01 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/alpha/timer_create.c: New file. + * sysdeps/unix/sysv/linux/alpha/timer_delete.c: New file. + * sysdeps/unix/sysv/linux/alpha/timer_getoverr.c: New file. + * sysdeps/unix/sysv/linux/alpha/timer_gettime.c: New file. + * sysdeps/unix/sysv/linux/alpha/timer_settime.c: New file. + * sysdeps/unix/sysv/linux/alpha/Versions: New file. + + * sysdeps/unix/sysv/linux/alpha/aio_cancel.c: New file. + + * sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: Define + _POSIX_THREAD_PRIORITY_SCHEDULING. + * sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: Likewise. + +2003-08-31 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/bits/stdio-lock.h (_IO_acquire_lock): Avoid + nested function, use static inline function from libio.h. + Code by Richard Henderson. + + * sysdeps/pthread/bits/libc-lock.h: Mark pthread_setcancelstate as + weak. + +2003-08-30 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/sparc/sparc64/Versions: New file. + * sysdeps/unix/sysv/linux/sparc/sparc64/timer_create.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc64/timer_delete.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc64/timer_getoverr.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc64/timer_gettime.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc64/timer_settime.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h: New file. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: New file. + * sysdeps/unix/sysv/linux/sparc/bits/semaphore.h: New file. + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h: New file. + * sysdeps/unix/sysv/linux/sparc/pthread_once.c: New file. + * sysdeps/unix/sysv/linux/sparc/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/sparc/fork.c: New file. + * sysdeps/unix/sysv/linux/sparc/aio_cancel.c: New file. + * sysdeps/sparc/sparc32/sparcv9/pthread_spin_lock.c: New file. + * sysdeps/sparc/sparc32/sparcv9/pthread_spin_trylock.c: New file. + * sysdeps/sparc/sparc32/sparcv9/pthread_spin_unlock.c: New file. + * sysdeps/sparc/sparc32/pthread_spin_lock.c: New file. + * sysdeps/sparc/sparc32/pthread_spin_trylock.c: New file. + * sysdeps/sparc/sparc32/pthreaddef.h: New file. + * sysdeps/sparc/sparc64/pthread_spin_lock.c: New file. + * sysdeps/sparc/sparc64/pthread_spin_trylock.c: New file. + * sysdeps/sparc/sparc64/pthread_spin_unlock.c: New file. + * sysdeps/sparc/sparc64/pthreaddef.h: New file. + * sysdeps/sparc/tls.h: New file. + * sysdeps/sparc/tcb-offsets.sym: New file. + * sysdeps/sparc/Makefile: New file. + * sysdeps/sparc/td_ta_map_lwp2thr.c: New file. + * init.c [__sparc__] (__NR_set_tid_address): Define. + +2003-08-29 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/bits/stdio-lock.h (_IO_acquire_lock, + _IO_release_lock): Define. + +2003-08-29 Jakub Jelinek <jakuB@redhat.com> + + * tst-cancel4.c (tf_sigwait, tf_sigwaitinfo, tf_sigtimedwait): Add + sigemptyset before sigaddset. Reported by jreiser@BitWagon.com. + +2003-08-27 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread.h (pthread_exit): Remove __THROW. + (__pthread_cleanup_class): Add missing return types of member + functions. + +2003-08-26 Steven Munroe <sjmunroe@us.ibm.com> + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h + (lll_mutex_unlock_force): Add memory barrier between store and futex + syscall. + +2003-08-25 Ulrich Drepper <drepper@redhat.com> + + * tst-cancel4.c (do_test): Also unlink tempfname and remove + tempmsg in first loop. + +2003-08-18 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Define + _POSIX_THREAD_PRIORITY_SCHEDULING. + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise. + +2003-08-07 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/bits/libc-lock.h [_LIBC && SHARED] + (__rtld_lock_default_lock_recursive, + __rtld_lock_default_unlock_recursive): Define. + [_LIBC && SHARED] (__rtld_lock_lock_recursive, + __rtld_lock_unlock_recursive): Define using + GL(_dl_rtld_*lock_recursive). + * init.c (__pthread_initialize_minimal_internal): Initialize + _dl_rtld_lock_recursive and _dl_rtld_unlock_recursive. + Lock GL(_dl_load_lock) the same number of times as + GL(_dl_load_lock) using non-mt implementation was nested. + + * pthreadP.h (__pthread_cleanup_upto): Add hidden_proto. + * pt-longjmp.c (__pthread_cleanup_upto): Add hidden_def. + +2003-08-06 Jakub Jelinek <jakub@redhat.com> + + * tst-cancel17.c (do_test): Make len2 maximum of page size and + PIPE_BUF. + +2003-08-07 Jakub Jelinek <jakub@redhat.com> + + * pthread_create.c (__pthread_create_2_0): Clear new_attr.cpuset. + +2003-08-03 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/createthread.c (do_clone): Move error handling + to first syscall error check. Move syscall error check for tkill + into __ASSUME_CLONE_STOPPED #ifdef. + +2003-08-02 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/createthread.c (do_clone): If __ASSUME_CLONE_STOPPED + is not defined, do explicit synchronization. + (create_thread): Do not lock pd->lock here. If __ASSUME_CLONE_STOPPED + is not defined also unlock pd->lock for non-debugging case in case + it is necessary. + * pthread_create.c (start_thread): Always get and release pd->lock + if __ASSUME_CLONE_STOPPED is not defined. + (start_thread_debug): Removed. Adjust users. + * allocatestack.c (allocate_stack): Always initialize lock if + __ASSUME_CLONE_STOPPED is not defined. + * Makefile (tests): Add tst-sched1. + * tst-sched1.c: New file. + + * sysdeps/pthread/createthread.c (do_clone): Only use + sched_setschduler and pass correct parameters. + +2003-07-31 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/pthread.h (pthread_attr_setstackaddr, + pthread_attr_setstacksize): Change PTHREAD_STACK_SIZE to + PTHREAD_STACK_MIN in comments. + +2003-07-31 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait): + Shut up warnings if INTERNAL_SYSCALL_ERROR_P does not use its first + argument. + * sysdeps/unix/sysv/linux/timer_create.c (timer_create): Likewise. + * pthread_condattr_setclock.c (pthread_condattr_setclock): Likewise. + * sysdeps/unix/sysv/linux/s390/jmp-unwind.c: Include pthreaddef.h. + (__pthread_cleanup_upto): Fix prototype. + (_longjmp_unwind): Adjust caller. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h (__lll_mutex_timedlock): + Change second argument to const struct pointer. + * tst-sem8.c (main): Remove unused s2 and s3 variables. + * tst-sem9.c (main): Likewise. + * unwind.c: Include string.h for strlen prototype. + +2003-07-31 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Don't use cmov unless HAVE_CMOV is defined. + * sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S: + Define HAVE_CMOV. + Patch by Nicholas Miell <nmiell@attbi.com>. + +2003-07-30 Jakub Jelinek <jakub@redhat.com> + + * init.c (__pthread_initialize_minimal_internal): Initialize + GL(dl_init_static_tls). + * pthreadP.h (__pthread_init_static_tls): New prototype. + * allocatestack.c (init_one_static_tls, __pthread_init_static_tls): + New functions. + * Makefile (tests): Add tst-tls4. + (modules-names): Add tst-tls4moda and tst-tls4modb. + ($(objpfx)tst-tls4): Link against libdl and libpthread. + ($(objpfx)tst-tls4.out): Depend on tst-tls4moda.so and + tst-tls4modb.so. + * tst-tls4.c: New file. + * tst-tls4moda.c: New file. + * tst-tls4modb.c: New file. + +2003-06-19 Daniel Jacobowitz <drow@mvista.com> + + * sysdeps/pthread/timer_create.c (timer_create): Call timer_delref + before __timer_dealloc. + * sysdeps/pthread/timer_routines.c (__timer_thread_find_matching): + Don't call list_unlink. + +2003-07-29 Roland McGrath <roland@redhat.com> + + * Makefile [$(build-shared) = yes] (tests): Depend on $(test-modules). + +2003-07-25 Jakub Jelinek <jakub@redhat.com> + + * tst-cancel17.c (do_test): Check if aio_cancel failed. + Don't reuse struct aiocb A if it failed. + Write fpathconf (fds[1], _PC_PIPE_BUF) + 2 bytes using aio_write, + not just one byte, as that does not block. + +2003-07-22 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/unwind-resume.c: New file. + * sysdeps/pthread/Makefile (routines, shared-only-routines): Add + unwind-resume in csu subdir. + (CFLAGS-unwind-resume.c, CFLAGS-rt-unwind-resume.c): Compile with + exceptions. + (librt-sysdep_routines, librt-shared-only-routines): Add + rt-unwind-resume. + * sysdeps/pthread/rt-unwind-resume.c: New file. + * unwind-forcedunwind.c: New file. + * Makefile (libpthread-routines): Add unwind-forcedunwind. + (libpthread-shared-only-routines): Likewise. + (CFLAGS-unwind-forcedunwind.c): Compile with exceptions. + * pthreadP.h (pthread_cancel_init): New prototype. + * pthread_cancel.c (pthread_cancel): Call pthread_cancel_init. + + * sysdeps/pthread/createthread.c (do_thread, create_thread): Make + attr argument const struct pthread_attr *. + + * res.c (__res_state): Return __resp. + * descr.h: Include resolv.h. + (struct pthread): Add res field. + * pthread_create.c: Include resolv.h. + (start_thread): Initialize __resp. + * Makefile (tests): Add tst-_res1. + (module-names): Add tst-_res1mod1, tst-_res1mod2. + ($(objpfx)tst-_res1mod2.so): Depend on $(objpfx)tst-_res1mod1.so. + ($(objpfx)tst-_res1): Depend on $(objpfx)tst-_res1mod2.so and + libpthread. + * tst-_res1.c: New file. + * tst-_res1mod1.c: New file. + * tst-_res1mod2.c: New file. + +2003-07-21 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/createthread.c: Don't define CLONE_STOPPED. + + * Makefile: Define various *-no-z-defs variables for test DSOs + which has undefined symbols. + +2003-07-21 Steven Munroe <sjmunroe@us.ibm.com> + + * sysdeps/unix/sysv/linux/powerpc/pthread_once.c (__pthread_once): + Retry if the stwcx fails to store once_control. + +2003-07-20 Ulrich Drepper <drepper@redhat.com> + + * Makefile (libpthread-routines): Add pthread_attr_getaffinity and + pthread_attr_setaffinity. + * Versions [libpthread] (GLIBC_2.3.3): Likewise. + * sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c: New file. + * sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c: New file. + * pthread_attr_destroy.c: Free cpuset element if allocated. + * pthread_create.c: Pass iattr as additional parameter to + create_thread. + * sysdeps/pthread/createthread.c: If attribute is provided and + a new thread is created with affinity set or scheduling parameters, + start thread with CLONE_STOPPED. + * sysdeps/pthread/pthread.h: Declare pthread_attr_getaffinity and + pthread_attr_setaffinity. + * sysdeps/unix/sysv/linux/internaltypes.h (struct pthread_attr): Add + cpuset element. + +2003-07-15 Ulrich Drepper <drepper@redhat.com> + + * tst-tcancel-wrappers.sh: lseek and llseek are not cancelation points. + +2003-07-14 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/configure.in: Require CFI directives also for + ppc and s390. + +2003-07-15 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h (PSEUDO): + Add cfi directives. + +2003-07-12 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/sh/tcb-offsets.sym: Add RESULT, TID, CANCELHANDLING and + CLEANUP_JMP_BUF. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Use more + registers as variables. Call __pthread_mutex_unlock_usercnt. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: Store TID + not self pointer in __writer. Compare with TID to determine + deadlocks. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/sh/sem_wait.S: Add cancellation support. + * sysdeps/unix/sysv/linux/sh/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: Define all the nice + macros also when compiling librt. + +2003-07-11 Jakub Jelinek <jakub@redhat.com> + + * Makefile (CFLAGS-pthread_once.c): Add -fexceptions + -fasynchronous-unwind-tables. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h + (PSEUDO): Add cfi directives. + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h (PSEUDO): + Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h (PSEUDO): + Likewise. + +2003-07-08 Jakub Jelinek <jakub@redhat.com> + + * pthreadP.h (__pthread_unwind_next, __pthread_register_cancel, + __pthread_unregister_cancel): Add prototypes and hidden_proto. + * unwind.c (__pthread_unwind_next): Add hidden_def. + * cleanup.c (__pthread_register_cancel, __pthread_unregister_cancel): + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S (__new_sem_wait): + Use HIDDEN_JUMPTARGET to jump to __pthread_unwind. + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S (sem_timedwait): + Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S (sem_wait): Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S (sem_timedwait): + Likewise. + * sysdeps/unix/sysv/linux/i386/pthread_once.S (__pthread_once): Use + HIDDEN_JUMPTARGET to call __pthread_register_cancel, + __pthread_unregister_cancel and __pthread_unwind_next. + +2003-07-04 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (PSEUDO): Use + different symbol for the cancellation syscall wrapper and + non-cancellation syscall wrapper. + (PSEUDO_END): Define. + +2003-07-05 Richard Henderson <rth@redhat.com> + + * sysdeps/alpha/elf/pt-initfini.c: Avoid .ent/.end. + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h (lll_futex_wait, + lll_futex_timed_wait, lll_futex_wake, lll_futex_requeue): On success + return actual return value from the syscall, not 0. + +2003-07-07 Ulrich Drepper <drepper@redhat.com> + + * descr.h (struct pthread): Add pid field. + * allocatestack.c (allocate_stack): Initialize pid field in descriptor. + (__reclaim_stacks): Likewise. + * init.c (sigcancel_handler): If __ASSUME_CORRECT_SI_PID is defined + also check for PID of the signal source. + (__pthread_initialize_minimal_internal): Also initialize pid field + of initial thread's descriptor. + * pthread_cancel.c: Use tgkill instead of tkill if possible. + * sysdeps/unix/sysv/linux/fork.c: Likewise. + * sysdeps/unix/sysv/linux/pt-raise.c: Likewise. + * sysdeps/unix/sysv/linux/pthread_kill.c: Likewise. + * sysdeps/unix/sysv/linux/raise.c: Likewise. + +2003-07-05 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/bits/libc-lock.h (__libc_cleanup_push): Renamed. + Fix use of parameter. + (__libc_cleanup_pop): Likewise. + +2003-07-04 Ulrich Drepper <drepper@redhat.com> + + * init.c (sigcancel_handler): Change parameters to match handler + for SA_SIGACTION. Check signal number and code to recognize + invalid invocations. + +2003-07-03 Roland McGrath <roland@redhat.com> + + * sysdeps/ia64/td_ta_map_lwp2thr.c (td_ta_map_lwp2thr): + Apply sizeof (struct pthread) bias to r13 value. + +2003-07-03 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/configure.in: Require CFI directives. + + * sysdeps/pthread/librt-cancellation.c (__pthread_unwind): Remove + definition. + * pthreadP.h (__pthread_unwind): Add hidden_proto if used in + libpthread compilation. + * unwind.c (__pthread_unwind): Add hidden_def. + * Versions (libpthread) [GLIBC_PRIVATE]: Add __pthread_unwind. + +2003-07-01 Ulrich Drepper <drepper@redhat.com> + + * libc-cancellation.c (__libc_cleanup_routine): Define. + * sysdeps/pthread/bits/libc-lock.h (__pthread_cleanup_push): Define. + (__pthread_cleanup_pop): Define. + +2003-07-01 Richard Henderson <rth@redhat.com> + + * sysdeps/alpha/elf/pt-initfini.c: New file. + * sysdeps/alpha/pthread_spin_lock.S: New file. + * sysdeps/alpha/pthread_spin_trylock.S: New file. + * sysdeps/alpha/pthreaddef.h: New file. + * sysdeps/alpha/td_ta_map_lwp2thr.c: New file. + * sysdeps/alpha/tls.h: New file. + * sysdeps/unix/sysv/linux/alpha/Makefile: New file. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h: New file. + * sysdeps/unix/sysv/linux/alpha/bits/semaphore.h: New file. + * sysdeps/unix/sysv/linux/alpha/createthread.c: New file. + * sysdeps/unix/sysv/linux/alpha/fork.c: New file. + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h: New file. + * sysdeps/unix/sysv/linux/alpha/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/alpha/pthread_once.c: New file. + * sysdeps/unix/sysv/linux/alpha/sem_post.c: New file. + * sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h: New file. + +2003-07-01 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Add correct + cleanup support and unwind info. + +2003-06-30 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/pthread_once.S (__pthread_once): + Use correct cleanup handler registration. Add unwind info. + * sysdeps/unix/sysv/linux/unwindbuf.sym: New file. + * sysdeps/unix/sysv/linux/Makefile: Add rule to build unwindbuf.h. + * tst-once3.c: Add cleanup handler and check it is called. + * tst-once4.c: Likewise. + * tst-oncex3.c: New file. + * tst-oncex4.c: New file. + * Makefile: Add rules to build and run tst-oncex3 and tst-oncex4. + +2003-06-29 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/configure.in: Check for C cleanup handling in gcc. + +2003-06-27 Ulrich Drepper <drepper@redhat.com> + + * tst-cancel4.c (tf_msgrcv): Use IPC_PRIVATE in msgget call. + (tf_msgsnd): Likewise. + + * tst-cancel4.c (tf_msgrcv): Strengthen test against valid + premature returns a bit more. + +2003-06-26 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/librt-cancellation.c: Move __pthread_unwind + definition to the front. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Rename + the cleanup functions to make the names unique. Fix dwarf opcode + un unwind table. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Rename cleanup + functions to make the names unique. Fix CFA offset for two blocks. + +2003-06-25 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread.h (class __pthread_cleanup_class): Add + missing closing braces. + Patch by Christophe Saout <christophe@saout.de>. + +2003-06-24 Roland McGrath <roland@redhat.com> + + * pthread_mutex_trylock.c (__pthread_mutex_trylock): Typo fix. + +2003-06-24 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: New file. + * sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: New file. + + * pthreadP.h: Declare __find_thread_by_id. + * allocatestack.c [HP_TIMING_AVAIL]: Define __find_thread_by_id. + * pthread_clock_gettime.c: Allow using other thread's clock. + * pthread_clock_settime.c: Likewise. + * sysdeps/pthread/pthread_getcpuclockid.c: Likewise. + * Makefile: Add rules to build and run tst-clock2. + * tst-clock2.c: New file. + +2003-06-23 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Rewrite + to use exception-based cleanup handler. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + + * tst-cond8.c (ch): Announce that we are done. + + * pthreadP.h (__pthread_mutex_cond_lock): Mark with internal_function. + + * tst-cancel17.c (tf): Retry aio_suspend in case of EINTR. + Also test aio_suspend with timeout value. + +2003-06-22 Ulrich Drepper <drepper@redhat.com> + + * pthreadP.h: Mark __pthread_mutex_unlock_usercnt also hidden. + * pthread_mutex_unlock.c (__pthread_mutex_unlock_usercnt): Add + attribute_hidden. + + * pthreadP.h (__pthread_mutex_init_internal): Mark hidden. + (__pthread_mutex_lock_internal): Likewise. + (__pthread_mutex_unlock_internal): Likewise. + (__pthread_mutex_unlock_usercnt): Declare. + * pthread_mutex_destroy.c: Always fail if used in any way. + * pthread_mutex_init.c: Update comment. + * pthread_mutex_lock.c: If NO_INCR is not defined adjust __nusers. + * pthread_mutex_timedlock.c: Adjust __nusers. + * pthread_mutex_trylock.c: Adjust __nusers. + * pthread_mutex_unlock.c: Old code is in __pthread_mutex_unlock_usercnt + and public interfaces are wrapper with pass additional parameter. + __pthread_mutex_unlock_usercnt does not adjust __nusers if second + parameter zero. + * tst-mutex8.c: New file. + * Makefile (tests): Add tst-mutex8. + * sysdeps/pthread/pthread_cond_timedwait.c: Call + __pthread_mutex_unlock_usercnt. + * sysdeps/pthread/pthread_cond_wait.c: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c: Define NO_INCR. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_mutex_t): + Add __nusers. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + + * pthread_mutex_lock.c: Don't store THREAD_ID in __owner, use TID. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_trylock.c: Adjust __nusers. + * pthread_mutex_unlock.c: Compare with TID not THREAD_ID. + * tst-mutex9.c: New file. + * Makefile (tests): Add tst-mutex9. + * sysdeps/i386/tls.h: Remove THREAD_ID definition. + * sysdeps/ia64/tls.h: Likewise. + * sysdeps/powerpc/tls.h: Likewise. + * sysdeps/s390/tls.h: Likewise. + * sysdeps/sh/tls.h: Likewise. + * sysdeps/x86_64/tls.h: Likewise. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_mutex_t): + Change type of __owner. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + +2003-06-19 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/ia64/sem_post.c: Move to... + * sysdeps/unix/sysv/linux/sem_post.c: ...here. + + * sysdeps/unix/sysv/linux/sem_post.c: Move to... + * sysdeps/unix/sysv/linux/powerpc/sem_post.c: ... here. Pass nr + 1 + instead of nr to lll_futex_wake. Only set errno and return -1 + if err < 0. + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (lll_futex_wait, + lll_futex_timed_wait, lll_futex_wake, lll_futex_requeue): On success + return actual return value from the syscall, not 0. + +2003-06-18 Ulrich Drepper <drepper@redhat.com> + + * tst-cancel4.c (tf_msgsnd): Don't always use 100 as the type, + find a random value. + (tf_msgrcv): Likewise. Also don't report msgrcv returns if + errno==EIDRM. + + * sysdeps/unix/sysv/linux/timer_settime.c: Add prototype for + compat_timer_settime. + * sysdeps/unix/sysv/linux/timer_gettime.c: Add prototype for + compat_timer_gettime. + * sysdeps/unix/sysv/linux/timer_getoverr.c: Add prototype for + compat_timer_getoverrun. + * sysdeps/unix/sysv/linux/timer_delete.c: Add prototype for + compat_timer_delete. + + * pthread_mutex_destroy.c (__pthread_mutex_destroy): For + error-checking mutex detect busy mutexes. + +2003-06-17 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (lll_mutex_lock): + Add ax to clobber list. + (lll_mutex_cond_lock): Likewise. + (lll_mutex_unlock): Likewise. + (lll_lock): Likewise. + (lll_unlock): Likewise. + + * Makefile: Add rules to build and run tst-cancel18 and tst-cancelx18. + * tst-cancel18.c: New file. + * tst-cancelx18.c: New file. + + * tst-cancel4.c: Test connect, creat, msgrcv, msgsnd, sendmsg, sendto, + and tcdrain. + + * Makefile: Add rules to build and run tst-cancel17 and tst-cancel17x. + * tst-cancel17.c: New file. + * tst-cancelx17.c: New file. + + * sysdeps/unix/sysv/linux/sigtimedwait.c: New file. + * sysdeps/unix/sysv/linux/sigwait.c: New file. + * sysdeps/unix/sysv/linux/sigwaitinfo.c: New file. + + * tst-cancel4.c: Test open, close, pread, pwrite, fsync, and msync. + +2003-06-16 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/createthread.c (create_thread): Set + header.multiple_threads unconditionally. + * allocatestack.c (allocate_stack): Likewise. + * descr.h (struct pthread): Add header.multiple_threads + unconditionally. + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (CENABLE, CDISABLE): + Define for librt. #error if neither libpthread, libc nor librt. + * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (CENABLE, CDISABLE): + Likewise. + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h (CENABLE, + CDISABLE): Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h (CENABLE, + CDISABLE): Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h (CENABLE, + CDISABLE): Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h (CENABLE, + CDISABLE): Likewise. Access header.multiple_threads outside of + libc and libpthread. + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h (CENABLE, CDISABLE): + Likewise. + * sysdeps/x86_64/tls.h (tcbhead_t): Add multiple_threads. + * sysdeps/x86_64/tcb-offsets.sym (MULTIPLE_THREADS_OFFSET): Define. + +2003-06-17 Ulrich Drepper <drepper@redhat.com> + + * tst-cancel4.c: Add tests for the socket and signal functions, pause. + Also test early cancellation before the thread reaches the cancellation + point. + + * Makefile: Compile forward.c with exceptions. + + * sysdeps/unix/sysv/linux/sleep.c: New file. + +2003-06-16 Ulrich Drepper <drepper@redhat.com> + + * Makefile: Add CFLAGS definition to compile function wrappers + duplicated from libc with exceptions. + * tst-cancel4.c: Also check cancellation handlers. + + * Makefile: Add rules to build and run tst-cancel16 and + tst-cancelx16. Add missing CFLAGS definitions. + * tst-cancel16.c: New file. + * tst-cancelx16.c: New file. + +2003-06-15 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h + (DL_SYSINFO_IMPLEMENTATION): Use CFI opcodes. + * sysdeps/unix/sysv/linux/i386/i686/dl-sysdep.h + (DL_SYSINFO_IMPLEMENTATION): Likewise. + + * pthreadP.h (LIBC_CANCEL_ASYNC): Also define for librt. + (LIBC_CANCEL_RESET): Likewise. + Declare __librt_enable_asynccancel and __librt_disable_asynccancel. + * sysdeps/pthread/Makefile (librt-sysdep_routines): Add + librt-cancellation. + (CFLAGS-libcrt-cancellation.c): Define. + * sysdeps/pthread/librt-cancellation.c: New file. + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Define all the nice + macros also when compiling librt. + * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Likewise. + + * sysdeps/unix/sysv/linux/timer_create.c: Add prototype for + compat_timer_create. + +2003-06-14 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/posix-timer.h (timespec_compare): Always inline. + + * sysdeps/unix/sysv/linux/fork.h: Add libc_hidden_proto for + __register_atfork. + * sysdeps/unix/sysv/linux/register-atfork.c (__register_atfork): + Add libc_hidden_def. + +2003-06-13 Roland McGrath <roland@redhat.com> + + * sysdeps/x86_64/td_ta_map_lwp2thr.c (td_ta_map_lwp2thr): Pass FS + constant from <sys/reg.h> to ps_get_thread_area, not register contents. + +2003-06-11 Ulrich Drepper <drepper@redhat.com> + + * allocatestack.c (queue_stack): Always inline. + * ptreadhP.h (__do_cancel): Likewise. + +2003-06-10 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/s390/sem_timedwait.c (sem_timedwait): Fix + a typo. + +2003-06-10 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S + (__pthread_cond_signal): Remove incorrect second addition for + cond_lock!=0. + +2003-06-09 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S + (__pthread_cond_signal): Use correct futex pointer in + __lll_mutex_lock_wait call. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S + (__pthread_cond_signal): Some more tweaks to handle cond_lock!=0. + +2003-06-08 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/s390/sem_wait.c (__new_sem_wait): Make + cancelable. + * sysdeps/unix/sysv/linux/s390/sem_timedwait.c (sem_timedwait): + Likewise. + + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Remove + hand-written CFI generation code. Since ENTRY/END also initiated + CFI frames this caused two CFI sets to be generated. + +2003-06-07 Ulrich Drepper <drepper@redhat.com> + + * cleanup_routine.c: New file. + * Versions (libpthread) [GLIBC_2.3.3]: Add __pthread_cleanup_routine. + * sysdeps/pthread/pthread.h: Add support for fully exception-based + cleanup handling. + * Makefile (libpthread-routines): Add cleanup_routine. + Add more CFLAGS variables to compile with exceptions. Add comments + why which file needs unwind tables. + (tests) [have-forced-unwind==yes]: Add tst-cancelx* and tst-cleanupx* + tests. + * tst-cancelx1.c: New file. + * tst-cancelx2.c: New file. + * tst-cancelx3.c: New file. + * tst-cancelx4.c: New file. + * tst-cancelx5.c: New file. + * tst-cancelx6.c: New file. + * tst-cancelx7.c: New file. + * tst-cancelx8.c: New file. + * tst-cancelx9.c: New file. + * tst-cancelx10.c: New file. + * tst-cancelx11.c: New file. + * tst-cancelx12.c: New file. + * tst-cancelx13.c: New file. + * tst-cancelx14.c: New file. + * tst-cancelx15.c: New file. + * tst-cleanupx0.c: New file. + * tst-cleanupx0.expect: New file. + * tst-cleanupx1.c: New file. + * tst-cleanupx2.c: New file. + * tst-cleanupx3.c: New file. + + * tst-cleanup0.c: Make standard compliant. + * tst-cleanup1.c: Likewise. + + * sysdeps/unix/sysv/linux/sem_timedwait.c: Add cancellation support. + * sysdeps/unix/sysv/linux/sem_wait.c: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise. + * sysdeps/i386/tcb-offsets.sym: Add RESULT, CANCELHANDLING, and + CLEANUP_JMP_BUF. + * sysdeps/x86_64/tcb-offsets.sym: Likewise. + * tst-cancel12.c: New file. + * tst-cancel13.c: New file. + * tst-cancel14.c: New file. + * tst-cancel15.c: New file. + * Makefile (tests): Add tst-cancel12, tst-cancel13, tst-cancel14, + and tst-cancel15. + + * tst-cancel1.c: Add some comments. + + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Compute relative + timeout correctly. + +2003-06-06 Ulrich Drepper <drepper@redhat.com> + + * Makefile (CFLAGS-pthread_cancel.c): Define. + +2003-06-05 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_rwlock_t): + Change type of __writer element to int. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + * sysdeps/i386/tcb-offsets.sym: Replace SELF entry with TID entry. + * sysdeps/x86_64/tcb-offsets.sym: Likewise. + * pthread_rwlock_trywrlock.c: Store TID not self pointer in __writer. + Compare with TID to determine deadlocks. + * sysdeps/pthread/pthread_rwlock_rdlock.c: Likewise. + * sysdeps/pthread/pthread_rwlock_timedrdlock.c: Likewise. + * sysdeps/pthread/pthread_rwlock_timedwrlock.: Likewise. + * sysdeps/pthread/pthread_rwlock_wrlock.c: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: Likewise. + * Makefile (tests): Add tst-rwlock12. + * tst-rwlock12.c: New file. + +2003-06-05 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/lowlevellock.c (__lll_lock_wait, + __lll_timedlock_wait, lll_unlock_wake_cb, __lll_timedwait_tid): + Remove bogus hidden_proto. + * sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c (___lll_lock): + Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevellock.c (___lll_lock, + lll_unlock_wake_cb, ___lll_timedwait_tid): Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevelmutex.c (___lll_mutex_lock, + ___lll_mutex_timedlock): Likewise. + +2003-06-04 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S + (__pthread_cond_signal): Add some code to eventually handle + cond_lock!=0. + +2003-06-01 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-exec4. + (tst-exec4-ARGS): Define. + * tst-exec4.c: New file. + +2003-05-31 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/lowlevellock.c (__lll_timedlock_wait): + Also fail if tv_nsec < 0. + (__lll_timedwait_tid): Likewise. + * sysdeps/unix/sysv/linux/sem_timedwait.c (sem_timedwait): Likewise. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_timedwait_tid): + Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevellock.c (___lll_timedwait_tid): + Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevelmutex.c (__lll_mutex_timedlock): + Likewise. + * sysdeps/unix/sysv/linux/s390/sem_timedwait.c (sem_timedwait): + Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (lll_timedwait_tid): + Likewise. + * sysdeps/unix/sysv/linux/sh/lowlevellock.h (lll_timedwait_tid): + Likewise. + + * Makefile (tests): Add tst-sem8 and tst-sem9. + * tst-sem8.c: New file. + * tst-sem9.c: New file. + * sem_open.c: Fix creation of in_use record if the file exists but + no internal record. + + * posix-timer.h: Remove old, unused timer_id2ptr and timer_ptr2id + definitions. + + * sysdeps/pthread/timer_create.c (timer_create): In case + evp==NULL, assign timer ID to sival_ptr. + + * descr.h (struct pthread_unwind_buf): Change type of prev element to + struct pthread_unwind_buf *. + (struct pthread): Likewise for cleanup_jmp_buf element. + + * cleanup.c (__pthread_register_cancel): Add cast to avoid warning. + * cleanup_defer.c (__pthread_register_cancel_defer): Likewise. + * unwind.c (__pthread_unwind_next): Likewise. + +2003-05-30 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h + (lll_futex_timed_wait): Use int for futex value parameter. + (lll_futex_wake): Likewise. + (lll_futex_requeue): Likewise. + + * sysdeps/unix/sysv/linux/lowlevellock.c (__lll_lock_wait): + Replace one memory operation with one register operation. + + * tst-join4.c (do_test): Fix error message. + + * tst-rwlock6.c (do_test): Use correct format specifier. + + * sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S + (__lll_mutex_lock_wait): Replace one memory operation with one + register operation. + * sysdeps/unix/sysv/linux/x86_64/lowlevelmutex.S + (__lll_mutex_lock_wait): Likewise. + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h + (__lll_mutex_cond_lock): Add one to value parameter of + __lll_lock_wait to reflect reality in the futex syscall. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h + (lll_mutex_cond_lock): Likewise. + +2003-05-30 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/s390/lowlevellock.h (__lll_mutex_cond_lock): + New function. + (lll_mutex_cond_lock): Define. + +2003-05-29 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-signal6. + * tst-signal6.c: New file. + + * sysdeps/unix/sysv/linux/s390/lowlevellock.h + (__lll_mutex_unlock_force): New function + (lll_mutex_unlock_force): Use __lll_mutex_unlock_force. + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h + (__lll_mutex_unlock_force): New function. + (lll_mutex_unlock_force): Use __lll_mutex_unlock_force. + + * tst-rwlock7.c (do_test): Use correct format specifier. + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (lll_futex_requeue): + Find break parameter in correct asm argument. + +2003-05-27 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (lll_futex_clobbers): + Remove out4. + (lll_futex_requeue): Fix __o3 constraint, return negative errno if + error occured. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h (pthread_cond_t): + Add __mutex. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h (FUTEX_REQUEUE, + lll_futex_requeue, lll_mutex_unlock_force): Define. + +2003-05-30 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h + (pthread_cond_t): Add __mutex. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (FUTEX_REQUEUE, + lll_futex_requeue, lll_mutex_unlock_force): Define. + +2003-05-28 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/sh/tcb-offsets.sym: Define MUTEX_FUTEX. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h (pthread_cond_t): + Add __mutex field. + * sysdeps/unix/sysv/linux/sh/lowlevellock.h (SYSCALL_WITH_INST_PAD): + Define. + (lll_futex_wait, lll_futex_wake): Define. + * sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h: New file. + * sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S: Try using + FUTEX_REQUEUE instead of FUTEX_WAIT. + * sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Remember + mutex which was used in condvar structure. Call + __pthread_mutex_cond_lock instead of __pthread_mutex_lock_internal. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Likewise. + + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: Don't + include tcb-offsets.h. Read wakeup value in locked region. + Use the value of gbr register as THREAD_ID. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: Likewise. + + * sysdeps/unix/sysv/linux/sh/sem_trywait.S: Remove futex related + macros. + +2003-05-28 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread_cond_broadcast.c + (__pthread_cond_broadcast): Fix typo: MAX_INT -> INT_MAX. + +2003-05-26 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: Fix + typo in register name. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Use parameters + correctly. Actually use requeue. Little optimization. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Store + mutex address early. Handle cancellation state as 32-bit value. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + Remove unnecessary label. + +2003-05-25 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread_cond_broadcast.c: Try using FUTEX_REQUEUE + instead of FUTEX_WAIT. + * sysdeps/pthread/pthread_cond_signal.c: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise. + * sysdeps/pthread/pthread_cond_timedwait.c: Remember mutex which was + used in condvar structure. Call __pthread_mutex_cond_lock instead + of __pthread_mutex_lock_internal. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + * sysdeps/pthread/pthread_cond_wait.c: Likewise. + (__condvar_cleanup): Always call __pthread_mutex_cond_lock. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/Makefile (libpthread-sysdep_routines): + Add pthread_mutex_cond_lock. + * sysdeps/unix/sysv/linux/lowlevelcond.sym: Add dep_mutex. + * sysdeps/unix/sysv/linux/pthread_cond_mutex_lock.c: New file. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Define + lll_mutex_cond_lock. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_cond_t): + Add __mutex field. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + + * sysdeps/i386/tcb-offsets.sym: Define MUTEX_FUTEX. + * sysdeps/x86_64/tcb-offsets.sym: Likewise. + + * pthreadP.h: Declare __pthread_mutex_cond_lock. + * pthread_mutex_lock.c: Define LLL_MUTEX_LOCK if not already defined. + Use it instead of lll_mutex_lock. If __pthread_mutex_lock is a + macro don't define aliases. + + * cancellation.c: Remove __pthread_enable_asynccancel_2. + * pthreadP.h: Remove declaration of __pthread_enable_asynccancel_2. + * sysdeps/pthread/pthread_cond_timedwait.c: Use + __pthread_enable_asynccancel instead of __pthread_enable_asynccancel_2. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + * sysdeps/pthread/pthread_cond_wait.c: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + +2003-05-17 Ulrich Drepper <drepper@redhat.com> + + * sem_open.c: Fix one endless loop. Implement correct semantics + wrt opening the same semaphore more then once. + * sem_close.c: Adjust for sem_open change. + * semaphoreP.h: Include <semaphore.h>. Define struct inuse_sem. + Declare __sem_mappings, __sem_mappings_lock, __sem_search. + * Makefile (tests): Add tst-sem7. + * tst-sem7.c: New file. + +2003-05-16 Roland McGrath <roland@redhat.com> + + * sysdeps/unix/sysv/linux/register-atfork.c (libc_freeres_fn): Fix + uninitialized variable braino. + +2003-05-16 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/timer_gettime.c (timer_gettime): Correct + test for syscall availability. + + * sysdeps/unix/sysv/linux/timer_settime.c (timer_settime): Set + __no_posix_timers to -1 if the syscalls don't exist. + + * pthread_join.c (pthread_join): Set tid field of the joined + thread to -1. This isn't necessary but helps to recognize some + error conditions with almost no cost. + + * allocatestack.c (FREE_P): Also negative values indicate an + unused stack. + + * unwind.c: Include <unistd.h>. + +2003-05-14 Ulrich Drepper <drepper@redhat.com> + + * Makefile ($(objpfx)$(multidir)): Add rule to create the directory. + +2003-05-14 Jakub Jelinek <jakub@redhat.com> + + * Makefile (crti-objs, crtn-objs): New variables. + (omit-deps, extra-objs): Add crtn. + ($(objpfx)libpthread.so): Depend on both crti and crtn + and links to them in multidir. + ($(objpfx)crtn.S, $(objpfx)crtn.o): New rules. + +2003-05-12 Steven Munroe <sjmunroe@us.ibm.com> + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h + (lll_mutex_unlock): Use atomic_exchange_rel. + +2003-05-11 Ulrich Drepper <drepper@redhat.com> + + * cond-perf.c (cons): Add missing locking around setting of alldone. + +2003-05-10 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S: Remove futex + related macros. + * sysdeps/unix/sysv/linux/x86_64/sem_trywait.S: Likewise. + +2003-05-09 Ulrich Drepper <drepper@redhat.com> + + * tst-sem6.c: New file. + * Makefile (tests): Add tst-sem6. + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (___lll_mutex_unlock): + Use atomic_exchange_rel instead of atomic_exchange. + * sysdeps/unix/sysv/linux/lowlevellock.c (lll_unlock_wake_cb): + Likewise. + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Improve quality of + code for lll_futex_wait and lll_futex_wake in static apps. Use + vsyscall is possible. + + * sysdeps/unix/sysv/linux/pthread_getaffinity.c: New file. + * sysdeps/unix/sysv/linux/pthread_setaffinity.c: New file. + * sysdeps/pthread/pthread.h: Declare pthread_getaffinity_np and + pthread_setaffinity_np. + * Versions [libpthread] (GLIBC_2.3.3): Add pthread_getaffinity_np + and pthread_setaffinity_np. + * Makefile (libpthread-routines): Add pthread_getaffinity and + pthread_setaffinity. + + * allocatestack.c (allocate_stack): If ARCH_RETRY_MMAP is defined, + use it in case mmap to allocate the stack fails. + * sysdeps/unix/sysv/linux/x86_64/Makefile: Don't define + ARCH_MAP_FLAGS here. + * sysdeps/x86_64/pthreaddef.h: Define ARCH_MAP_FLAGS and + ARCH_RETRY_MMAP. + +2003-05-08 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/fork.c: Complete rewrite of the atfork + handler implementation. It is now lockless in fork(). + * sysdeps/unix/sysv/linux/register-atfork.c: Likewise. + * sysdeps/unix/sysv/linux/unregister-atfork.c: Likewise. + * sysdeps/unix/sysv/linux/fork.h: Don't include <link.h>. Don't + declare the __fork_*_lists. + (struct fork_handler): Include pointers to all three functions. + Add next, refcntr and need_signal elements. + (__fork_handlers): New declaration. + (__register_atfork_malloc): Remove declaration. + (HAVE_register_atfork_malloc): Remove definition. + * sysdeps/unix/sysv/linux/libc_pthread_init.c: Remove + __pthread_child_handler variable. + (__libc_pthread_init): Use __register_atfork instead of explicitly + adding to the list. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Define lll_futex_wait + and lll_futex_wake. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. + + * unwind.c (unwind_cleanup): Print error message and then abort. This + function must never be reached. + + * cond-perf.c: New file. + +2003-05-05 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/i386/tls.h (TLS_INIT_TP): Include \n in error message. + +2003-05-04 Roland McGrath <roland@redhat.com> + + * Makefile ($(objpfx)../libc.so): New target. + +2003-05-02 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h + (pthread_condattr_t): Size is only an int, don't use long for + alignment. + (pthread_mutexattr_t): Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + +2003-05-01 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/i386/tls.h: Define THREAD_ID. + * sysdeps/ia64/tls.h: Likewise. + * sysdeps/powerpc/tls.h: Likewise. + * sysdeps/s390/tls.h: Likewise. + * sysdeps/sh/tls.h: Likewise. + * sysdeps/x86_64/tls.h: Likewise. + * pthread_mutex_lock.c: Use THREAD_ID instead of THREAD_SELF to + record ownership. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_trylock.c: Likewise. + * pthread_mutex_unlock.c: Likewise. + * pthread_rwlock_trywrlock.c: Likewise. + * sysdeps/pthread/pthread_rwlocklock_rdlock.c: Likewise. + * sysdeps/pthread/pthread_rwlock_timedrdlock.c: Likewise. + * sysdeps/pthread/pthread_rwlock_timedwrlock.c: Likewise. + * sysdeps/pthread/pthread_rwlock_wrlock.c: Likewise. + + * sysdeps/pthread/createthread.c (create_thread): Use CLONE_SYSVSEM + flag. + +2003-04-29 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h + (__SIZEOF_PTHREAD_COND_T): Define to 48. + (pthread_rwlock_t): Add 16 bytes of pad instead of 8 before __flags. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h (pthread_cond_t): + Make __align long long instead of long. + (pthread_rwlock_t): Formatting. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h + (pthread_rwlock_t): Formatting. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h + (pthread_cond_t): Make __align long long instead of long. + (pthread_rwlock_t): Move __flags field to the same position as in + linuxthreads. + +2003-04-30 Ulrich Drepper <drepper@redhat.com> + + * tst-rwlock6.c (do_test): Use correct printf format specifiers. + * tst-rwlock7.c (do_test): Likewise. + +2003-04-26 Roland McGrath <roland@redhat.com> + + * Makefile ($(test-modules)): Depend on $(common-objpfx)shlib.lds. + +2003-04-22 Jakub Jelinek <jakub@redhat.com> + + * allocatestack.c (TLS_TPADJ): Add TLS_PRE_TCB_SIZE instead of + sizeof (struct pthread). + (allocate_stack): Subtract TLS_PRE_TCB_SIZE bytes instead of + 1 struct pthread. + * sysdeps/powerpc/tls.h (TLS_INIT_TCB_SIZE, TLS_TCB_SIZE): Define + to 0. + (TLS_INIT_TCB_ALIGN, TLS_TCB_ALIGN): Define to alignment of + struct pthread. + (TLS_PRE_TCB_SIZE): Increase to cover tcbhead_t preceeded by pad + to 32-bit bytes. + (INSTALL_DTV, GET_DTV, THREAD_DTV): tcbhead_t is immediately before + tcbp. + (TLS_INIT_TP, THREAD_SELF, INIT_THREAD_SELF): Don't add TLS_TCB_SIZE + unneccessarily. + (NO_TLS_OFFSET): Define. + * sysdeps/unix/sysv/linux/powerpc/createthread.c (TLS_VALUE): Don't + add TLS_TCB_SIZE unnecessarily. + +2003-04-22 Roland McGrath <roland@redhat.com> + + * Makeconfig (shared-thread-library): Reverse link order to work + around linker bug. + +2003-04-22 Ulrich Drepper <drepper@redhat.com> + + * semaphore.h: Fix typo in comment. + +2003-04-21 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/sigfillset.c: New file. + + * init.c (__pthread_initialize_minimal): Don't block SIGTIMER. + * pthreadP.h: Make SIGTIMER and SIGCANCEL the same. + * sysdeps/pthread/pthread_sigmask.c: Remove handling of SIGTIMER. + * sysdeps/pthread/sigaction.c: Likewise. + * sysdeps/pthread/sigprocmask.c: New file. + * sysdeps/unix/sysv/linux/allocrtsig.c (current_rtmin): Define as + __SIGRTMIN+1. + * sysdeps/unix/sysv/linux/timer_routines.c (timer_helper_thread): + Block SIGTIMER. Also handle SI_TKILL events and terminate thread + in this case. + +2003-04-19 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h + (DL_SYSINFO_IMPLEMENTATION): Add .eh_frame information. + + * sysdeps/unix/sysv/linux/unregister-atfork.c + (__unregister_atfork): Don't free memory not allocated dynamically. + + * semaphore.h: Remove __THROW marker from cancellation points. + * nptl/sysdeps/pthread/pthread.h: Likewise. + +2003-04-18 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread.h: Don't mark pthread_testcancel, + pthread_cancel, pthread_setcancelstate, and pthread_setcanceltype with + __THROW. + +2003-04-16 Jakub Jelinek <jakub@redhat.com> + + * tst-cancel4.c (do_test): Use %zd instead of %d when printing cnt. + +2003-04-15 Roland McGrath <roland@redhat.com> + + * forward.c (__pthread_unwind): Tweak to avoid warning. + +2003-04-15 Ulrich Drepper <drepper@redhat.com> + + * pthreadP.h: Move THREAD_ATOMIC_* replacements to the top. + +2003-04-14 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Don't + overflow CFA advance instructions. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + +2003-04-14 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/i386/tls.h: Rename LOCK to LOCK_PREFIX. + * sysdeps/i386/pthread_spin_lock.c: Likewise. + * sysdeps/x86_64/tls.h: Likewise. Define LOCK_PREFIX if not already + defined. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Use + DW_CFA_advance_loc2 for .Laddl-.Lsubl. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Use + DW_CFA_advance_loc for .Laddl-.Lsubl. + +2003-04-13 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Don't use + position-independent unwind data for static libraries. + Add missing unwind info. Add comments. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Add unwind info. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + +2003-04-12 Ulrich Drepper <drepper@redhat.com> + + * Makefile: Make sure all cancellation points are compiled with + exception and asynchronous unwind tables. + + * sysdeps/x86_64/tls.h (THREAD_SETMEM): Word around compiler bug + which mishandles loading of global object addresses in PIC. + (THREAD_SETMEM_NC): Likewise. + +2003-04-11 Ulrich Drepper <drepper@redhat.com> + + * pthread.h: Define new data structure for cleanup buffer. Declare + new cleanup handler interfaces. + * descr.h: Include <unwind.h> if necessary. Define pthread_unwind_buf. + (struct pthread): Add cleanup_jmp_buf pointer. Define + HAVE_CLEANUP_JMP_BUF and not HAVE_CANCELBUF. + * pthreadP.h: Declare __pthread_unwind. Define __do_cancel to use + it. Declare old cleanup handler installation functions. + * cleanup.c: Rewrite. Install handler for unwind-based cleanup + handling. + * cleanup_defer.c: Likewise. + * cleanup_compat.c: New file. Old cleanup code. + * cleanup_def_compat.c: New file. Old cleanup code. + * pthread_create.c (start_thread): Initialize cleanup_jmp_buf element + if own thread descriptor. + * unwind.c: New file. + * forward.c: Add __pthread_unwind. + * init.c (pthread_functions): Add __pthread_unwind. + * sysdeps/pthread/pthread-functions.s (struct pthread_functions): + Add ptr___pthread_unwind. + * Versions [GLIBC_2.3.3] (libpthread): Export new cleanup handling + and unwind function. + * Makefile (libpthread-routines): Add cleanup_compat, + cleanup_def_compat, and unwind. Define CFLAGS to enable unwind + table generation if necessary. + * version.c: Record whether unwind support is compiled in. + * sysdeps/pthread/configure.in: Add checks for unwind unterfaces. + * sysdeps/pthread/bits/libc-lock.h: Add prototypes of the old cleanup + handler interfaces. + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Add quite a bit of + complication to generate unwind information for syscall wrappers. + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Define + __cleanup_fct_attribute. + + * Makefile: Add rules to build and run tst-cleanup0. + * tst-cleanup0.c: New file. + * tst-cleanup0.expect: New file. + + * pthread_create.c (deallocate_tsd): Don't take parameter. Adjust + caller. Optimize to avoid often unecessary local variable. + +2003-04-11 Roland McGrath <roland@redhat.com> + + * Makefile ($(objpfx)multidir.mk): New target, generated makefile that + sets variable `multidir'; include that. + (generated): Add it. + ($(objpfx)$(multidir)/crti.o): New target. + [$(multidir) != .] (generated-dirs, extra-objs, omit-deps): Add it. + +2003-04-11 Ulrich Drepper <drepper@redhat.com> + + * tst-attr2.c (do_test): Add cast to avoid warning. + * tst-mutex4.c (do_test): Likewise. + +2003-04-10 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/fork.c (__libc_fork): Reset CPU clocks + in child. + +2003-04-09 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-detach1. + * tst-detach1.c: New file. + +2003-04-08 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread.h: Remove duplicate + pthread_cleanup_{push,pop} definitions. + + * tst-barrier2.c: Eliminate warnings. + * tst-cancel4.c: Likewise. + * tst-cond4.c: Likewise. + * tst-cond6.c: Likewise. + * tst-detach1.c: Likewise. + * tst-rwlock4.c: Likewise. + * tst-rwlock6.c: Likewise. + * tst-rwlock7.c: Likewise. + * tst-sem3.c: Likewise. + * tst-spin2.c: Likewise. + * tst-umask1.c: Likewise. + +2003-04-07 Ulrich Drepper <drepper@redhat.com> + + * pthread_detach.c (pthread_detach): Fix test for invalid TID. + +2003-04-06 Ulrich Drepper <drepper@redhat.com> + + * descr.h (struct pthread): Move cancelhandling member to the front. + +2003-04-05 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/register-atfork.c: Define malloc_prepare, + malloc_parent, and malloc_child statically. + (__register_atfork_malloc): New function. + (free_mem): Don't free any of the malloc_* variables on the list. + * sysdeps/unix/sysv/linux/fork.h: Declare __register_atfork_malloc. + Define HAVE_register_atfork_malloc. + +2003-04-04 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/createthread.c (create_thread): Add some more + comments explaining when to set multiple_threads and when not. + + * pthreadP.h: Define THREAD_ATOMIC_CMPXCHG_VAL and + THREAD_ATOMIC_BIT_SET if not already defined. + * sysdeps/i386/tls.h: Define THREAD_ATOMIC_CMPXCHG_VAL and + THREAD_ATOMIC_BIT_SET: + * sysdeps/x86_64/tls.h: Likewise. + * cleanup_defer.c (_pthread_cleanup_push_defer): Rewrite to use + THREAD_ATOMIC_CMPXCHG_VAL. + (_pthread_cleanup_pop_restore): Likewise. + * cancellation.c (__pthread_enable_asynccancel): Likewise. + (__pthread_enable_asynccancel_2): Likewise. + (__pthread_disable_asynccancel): Likewise. + * libc-cancellation.c (__libc_enable_asynccancel): Likewise. + (__libc_disable_asynccancel): Likewise. + * init.c (sigcancel_handler): Likewise. + * pthread_setcancelstate.c (__pthread_setcancelstate): Likewise. + * pthread_setcanceltype.c (__pthread_setcanceltype): Likewise. + +2003-04-03 Ulrich Drepper <drepper@redhat.com> + + * init.c (sigcancel_handler): Don't set EXITING_BIT here. + * libc-cancellation.c (__libc_enable_asynccancel): Likewise. + * pthreadP.h (__do_cancel): Set EXITING_BIT here. + * Makefile (tests): Add tst-cancel11. + * tst-cancel11.c: New file. + +2003-04-01 Ulrich Drepper <drepper@redhat.com> + + * pthread_create.c (deallocate_tsd): Clear/free memory after the last + round, not the first. Use specific_used flag instead of local + found_nonzero variable. Use THREAD_[SG]ETMEM where possible. + (__free_tcb): Don't call deallocate_tsd here. + (start_thread): Call deallocate_tsd here. + * pthread_setspecific.c: Set specific_used flag really only when + needed. + * Makefile (tests): Add tst-tsd3.c and tst-tsd4. + * tst-tsd3.c: New file. + * tst-tsd4.c: New file. + +2003-03-31 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (__lll_mutex_lock): + Use atomic_exchange_and_add instead of __lll_add. + (__lll_mutex_timedlock): Likewise. + Patch by Ian Wienand. + +2003-03-24 Steven Munroe <sjmunroe@us.ibm.com> + + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h + (SINGLE_THREAD_P): Fix typo. + * tst-cancel-wrappers.sh: Handle '.'ed symbols. + +2003-03-31 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-align. + * tst-align.c: New file. + * sysdeps/i386/Makefile: Define CFLAGS-tst-align. + + * sysdeps/i386/tls.h (CALL_THREAD_FCT): Align stack of called + function correctly. + + * tst-tsd2.c: Add casts to avoid warnings. + +2003-03-30 Ulrich Drepper <drepper@redhat.com> + + * descr.h (struct pthread): Move most often used elements to the front. + +2003-03-29 Ulrich Drepper <drepper@redhat.com> + + * Makefile (libpthread-routines): Add pthread_atfork. + (libpthread-static-only-routines): Add pthread_atfork. + +2003-03-28 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/sh/tls.h: Include nptl/descr.h after the definition + of TLS_DTV_AT_TP. + (INSTALL_DTV): Add parens. + (THREAD_GETMEM, THREAD_GETMEM_NC, THREAD_SETMEM, THREAD_SETMEM_NC): + Use passed descr instead of THREAD_SELF. + * sysdeps/unix/sysv/linux/sh/lowlevelmutex.S + (__lll_mutex_timedlock_wait): Correct expected value after + spurious wakeup. + * sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S: + Release lock before waking up the waiters. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Correct exit + criteria. Reorderstruct passed to cleanup handler. Fix + handling of cancellation and failung pthread_mutex_unlock call. + Use __pthread_enable_asynccancel_2 instead of + __pthread_enable_asynccancel. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. + Return result of lock re-get if it fails. + * sysdeps/unix/sysv/linux/sh/pthread_once.S: Fix wrong argument + for __pthread_cleanup_push. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: Fix + completely broken rwlock implementation. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/sem_post.S: Fix error value. Use + versioned_symbol macro. + * sysdeps/unix/sysv/linux/sh/sem_trywait.S: Use versioned_symbol macro. + * sysdeps/unix/sysv/linux/sh/sem_wait.S: Likewise. + +2003-03-27 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/kernel-posix-timers.h: Don't declare + __timer_helper_thread. Declare __start_helper_thread, __helper_once, + and __helper_tid. + (struct timer): Remove th and bar field. + * sysdeps/unix/sysv/linux/timer_create.c (timer_create): Remove + debugging code. Create only one helper thread. + * sysdeps/unix/sysv/linux/timer_delete.c (timer_delete): Don't kill + helper thread. + * sysdeps/unix/sysv/linux/timer_routines.c (timer_helper_thread): + Renamed. Define statically. Use thread info from siginfo. + (__helper_once): New variable. + (__helper_tid): New variable. + (__reset_helper_control): New function. + (__start_helper_thread): New function. + + * pthread_create.c (start_thread): Don't use setjmp inside + __builtin_expect to work around gcc bug. + + * sysdeps/unix/sysv/linux/timer_delete.c (timer_delete): Even if + timer_delete syscall fails, but not with ENOSYS, set + __no_posix_timers. + + * sysdeps/unix/sysv/linux/timer_settime.c [!__ASSUME_POSIX_TIMERS] + (timer_settime): Fix typo. + * sysdeps/unix/sysv/linux/timer_getoverr.c + [!__ASSUME_POSIX_TIMERS] (timer_getoverrun): Likewise. + +2003-03-27 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Fix + offset of cleanupbuf.__prev. + +2003-03-26 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/timer_getoverr.c: Fix typo in name + of included file. + +2003-03-26 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/timer_create.c (timer_create): If EVP == + NULL provide default definition to syscall. + +2003-03-25 Roland McGrath <roland@redhat.com> + + * sysdeps/pthread/posix-timer.h (TIMER_MAX): Define if not defined. + (timer_id2ptr): Fix typo. + +2003-03-25 Ulrich Drepper <drepper@redhat.com> + + * pthreadP.h: Define SIGCANCEL and SIGTIMER. + * sysdeps/i386/pthreaddef.h: Remove SIGCANCEL definition. + * sysdeps/ia64/pthreaddef.h: Likewise. + * sysdeps/powerpc/pthreaddef.h: Likewise. + * sysdeps/s390/pthreaddef.h: Likewise. + * sysdeps/sh/pthreaddef.h: Likewise. + * sysdeps/x86_64/pthreaddef.h: Likewise. + * init.c (__pthread_initialize_minimal): Block SIGTIMER. + * sysdeps/pthread/sigaction.c: Also prevent SIGTIMER handler from + being changed. + * sysdeps/pthread/pthread_sigmask.c (pthread_sigmask): Make sure + SIGTIMER is not unblocked. + * sysdeps/unix/sysv/linux/allocrtsig.c (current_rtmin): One more + RT signal taken. + * sysdeps/unix/sysv/linux/pthread_kill.c: Do not allow SIGTIMER to + be send. + * sysdeps/pthread/posix-timer.h (timer_id2ptr, timer_ptr2id): Just + pass pointer through as ID. + * sysdeps/unix/sysv/linux/bits/local_lim.h (TIMER_MAX): Removed. + * sysdeps/unix/sysv/linux/kernel-posix-timers.h: New file. + * sysdeps/unix/sysv/linux/timer_create.c: New file. + * sysdeps/unix/sysv/linux/timer_delete.c: New file. + * sysdeps/unix/sysv/linux/timer_getoverr.c: New file. + * sysdeps/unix/sysv/linux/timer_gettime.c: New file. + * sysdeps/unix/sysv/linux/timer_routines.c: New file. + * sysdeps/unix/sysv/linux/timer_settime.c: New file. + * sysdeps/unix/sysv/linux/ia64/Versions: New file. + * sysdeps/unix/sysv/linux/ia64/timer_create.c: New file. + * sysdeps/unix/sysv/linux/ia64/timer_delete.c: New file. + * sysdeps/unix/sysv/linux/ia64/timer_getoverr.c: New file. + * sysdeps/unix/sysv/linux/ia64/timer_gettime.c: New file. + * sysdeps/unix/sysv/linux/ia64/timer_settime.c: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/Versions: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_create.c: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_delete.c: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_getoverr.c: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_gettime.c: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_settime.c: New file. + * sysdeps/unix/sysv/linux/s390/s390-64/Versions: New file. + * sysdeps/unix/sysv/linux/s390/s390-64/timer_create.c: New file. + * sysdeps/unix/sysv/linux/s390/s390-64/timer_delete.c: New file. + * sysdeps/unix/sysv/linux/s390/s390-64/timer_getoverr.c: New file. + * sysdeps/unix/sysv/linux/s390/s390-64/timer_gettime.c: New file. + * sysdeps/unix/sysv/linux/s390/s390-64/timer_settime.c: New file. + * sysdeps/unix/sysv/linux/x86_64/Versions: New file. + * sysdeps/unix/sysv/linux/x86_64/compat-timer.h: New file. + * sysdeps/unix/sysv/linux/x86_64/timer_create.c: New file. + * sysdeps/unix/sysv/linux/x86_64/timer_delete.c: New file. + * sysdeps/unix/sysv/linux/x86_64/timer_getoverr.c: New file. + * sysdeps/unix/sysv/linux/x86_64/timer_gettime.c: New file. + * sysdeps/unix/sysv/linux/x86_64/timer_settime.c: New file. + + * pthreadP.h: Remove FRAME_LEFT definition. + * cleanup.c (_pthread_cleanup_push): Don't check for reference to + already left frame. Programs which have this problem are not POSIX + compliant. + * cleanup_defer.c (_pthread_cleanup_push_defer): Likewise. + +2003-03-24 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/tst-timer.c: Check return values of the + functions we test. + +2003-03-23 Roland McGrath <roland@redhat.com> + + * tst-tls3.c (do_test) [! HAVE___THREAD]: Don't test anything. + * tst-tls3mod.c: Likewise. + * tst-tls1.c: Likewise. + * tst-tls2.c: Likewise. + + * tst-mutex5.c (do_test): Unlock before destroy, otherwise we invoke + undefined behavior. + + * tst-join5.c (tf1, tf2): Add a cast. + + * Makeconfig (includes): Append -I$(..)nptl to this variable. + + * tst-barrier2.c (do_test) [! _POSIX_THREAD_PROCESS_SHARED]: + Don't test anything. + * tst-cond4.c: Likewise. + * tst-cond6.c: Likewise. + * tst-flock2.c: Likewise. + * tst-mutex4.c: Likewise. + * tst-rwlock4.c: Likewise. + * tst-signal1.c: Likewise. + * tst-spin2.c: Likewise. + * tst-cond11.c [! _POSIX_CLOCK_SELECTION]: Likewise. + + * tst-mutex4.c: Use test-skeleton.c. + * tst-spin2.c: Likewise. + * tst-sysconf.c: Likewise. + * tst-barrier2.c: Likewise. + * tst-cond4.c: Likewise. + * tst-cond6.c: Likewise. + * tst-rwlock4.c: Likewise. + * tst-unload.c: Likewise. + * tst-flock2.c (do_test): Use return instead of exit. + +2003-03-22 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/fork.c (__fork): Add libc_hidden_def. + +2003-03-21 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h + (__lll_mutex_trylock): Use atomic_compare_and_exchange_val_acq + instead of __lll_compare_and_swap. + * sysdeps/unix/sysv/linux/ia64/pthread_once.c (__pthread_once): + Likewise. + Removed definition if __lll_compare_and_swap. + + * cancellation.c: Adjust for new form of compare&exchange macros. + * cleanup_defer.c: Likewise. + * init.c: Likewise. + * libc-cancellation.c: Likewise. + * old_pthread_cond_broadcast.c: Likewise. + * old_pthread_cond_signal.c: Likewise. + * old_pthread_cond_timedwait.c: Likewise. + * old_pthread_cond_wait.c: Likewise. + * pthread_cancel.c: Likewise. + * pthread_create.c: Likewise. + * pthread_detach.c: Likewise. + * pthread_join.c: Likewise. + * pthread_key_delete.c: Likewise. + * pthread_setcancelstate.c: Likewise. + * pthread_setcanceltype.c: Likewise. + * pthread_timedjoin.c: Likewise. + * pthread_tryjoin.c: Likewise. + * sysdeps/pthread/createthread.c: Likewise. + +2003-03-20 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Include <atomic.h>. + Remove __lll_add, __lll_dec_if_positive, and __lll_test_and_set + definitions. Replace uses with calls to atomic_* functions. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/lowlevellock.c: Replace __lll_add and + __lll_test_and_set calls with atomic_exchange_and_add and + atomic_exchange calls respectively. + * sysdeps/unix/sysv/linux/sem_post.c: Likewise. + * sysdeps/unix/sysv/linux/sem_timedwait.c: Likewise. + * sysdeps/unix/sysv/linux/sem_trywait.c: Likewise. + * sysdeps/unix/sysv/linux/sem_wait.c: Likewise. + * sysdeps/unix/sysv/linux/ia64/pthread_once.c: Likewise. + * sysdeps/unix/sysv/linux/ia64/sem_port.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/pthread_once.c: Likewise. + + * allocatestack.c (allocate_stack): Assume atomic_exchange_and_add + returns the old value. + +2003-03-20 Martin Schwidefsky <sky@mschwid3.boeblingen.de.ibm.com> + + * sysdeps/s390/pthread_spin_lock.c (pthread_spin_lock): Use type + int for variable OLDVAL and correct inline assembler contraint. + * sysdeps/s390/pthread_spin_trylock.c (pthread_spin_trylock): Use + type int for variable OLD. + + * sysdeps/s390/tls.h (TLS_MULTIPLE_THREADS_IN_TCB): Define it + only for s390-32. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h + (SINGLE_THREAD_P): Use global variable __local_multiple_threads + instead of multiple_threads field in the TCB. + +2003-03-19 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/i386/i686/bits/atomic.h: Removed. + * sysdeps/i386/i586/bits/atomic.h: Removed. + * sysdeps/i386/i486/bits/atomic.h: Removed. Moved to glibc. + * sysdeps/x86_64/bits/atomic.h: Removed. Moved to glibc. + * sysdeps/s390/bits/atomic.h: Removed. Moved to glibc. + * sysdeps/sh/bits/atomic.h: Removed. Moved to glibc. + * sysdeps/ia64/bits/atomic.h: Removed. Moved to glibc. + * sysdeps/powerpc/bits/atomic.h: Removed. Moved to glibc. + * atomic.h: Removed. Moved to glibc. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Add + support for clock selection. + + * sysdeps/pthread/pthread_cond_broadcast.c: Release lock before + signalling waiters. + +2003-03-18 Roland McGrath <roland@redhat.com> + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (__lll_test_and_set): + Add __lll_rel_instr first. Add memory clobber. + (lll_mutex_unlock): Use __lll_test_and_set. + From Paul Mackerras <paulus@samba.org>. + + * sysdeps/powerpc/tls.h (TLS_MULTIPLE_THREADS_IN_TCB): Define + unconditionally. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h + (SINGLE_THREAD_P): Add `header.' prefix. + From Paul Mackerras <paulus@samba.org>. + + * Versions (libpthread: GLIBC_2.3.2): Move pthread_tryjoin_np and + pthread_timedjoin_np to ... + (libpthread: GLIBC_2.3.3): ... here. + (libpthread: GLIBC_2.2): Move pthread_barrierattr_getpshared there too. + + * sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait): + Avoid shadowing VAL variable. + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (__lll_test_and_set): + New macro. + +2003-03-18 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-cond11. + * tst-cond11.c: New file. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Reorder + struct passed to cleanup handler to eliminate one more + instruction. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h + (pthrad_cond_t): Replace __unused field with __clock. + + * sysdeps/pthread/pthread_cond_wait.c: Release condvar lock before + waken all waiters in cleanup handler. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + + * pthread_condattr_getclock.c: New file. + * pthread_condattr_setclock.c: New file. + * sysdeps/pthread/pthread.h: Declare these new functions. + * Versions [GLIBC_2.3.3] (libpthread): Add the new functions. + * Makefile (libpthread-routines): Add the new functions. + * sysdeps/unix/sysv/linux/internaltypes.h (struct pthread_condattr): + Renamed field to value. Document use of the bits. + * pthread_condattr_getpshared.c: Adjust for struct pthread_condattr + change. + * pthread_condattr_setpshared.c: Likewise. + * pthread_cond_init.c (__pthread_cond_init): Initialized __clock field. + * sysdeps/unix/sysv/linux/lowlevelcond.sym: Add cond_clock symbol. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_cond_t): + Add __clock field. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: + Implement clock selection. + * sysdeps/pthread/pthread_cond_timedwait.c: Likewise. + * pthread-errnos.sym: Add ENOSYS. + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Define + _POSIX_CLOCK_SELECTION. + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Remove + invalid .size directive. + +2003-03-17 Roland McGrath <roland@redhat.com> + + * sysdeps/unix/sysv/linux/lowlevellock.c (__lll_lock_wait): + Formatting tweaks. + +2003-03-17 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/ia64/pthread_once.c: Use __builtin_expect. + Use __lll_add instead of spelling it out. Use protected symbol names. + * sysdeps/unix/sysv/linux/ia64/sem_post.c: Use __builtin_expect. + Use __lll_add. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (__lll_compare_and_swap): + Renamed from lll_compare_and_swap. Use new name where necessary. + (__lll_add): Defined. + (__lll_dec_if_positive): Defined. + (__lll_test_and_set): Defined. + * sysdeps/ia64/pthread_spin_init.c: Removed. + * sysdeps/unix/sysv/linux/ia64/lowlevelmutex.c: Removed. + * sysdeps/unix/sysv/linux/ia64/sem_trywait.c: Removed. + * sysdeps/unix/sysv/linux/ia64/sem_wait.c: Removed. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.c: Removed. + * sysdeps/unix/sysv/linux/ia64/libc-lowlevellock.c: Removed. + * sysdeps/unix/sysv/linux/ia64/libc-lowlevelmutex.c: Removed. + * sysdeps/unix/sysv/linux/ia64/sem_timedwait.c: Removed. + * sysdeps/ia64/bits/atomic.h: Add __builtin_expect where appropriate. + * sysdeps/ia64/pthread_spin_unlock.c (pthread_spin_unlock): Use + __sync_lock_release_si. + Patch by Jakub Jelinek. + + * sysdeps/unix/sysv/linux/lowlevellock.c (__lll_timedlock_wait): + Fix timeout handling. + (__lll_timedwait_tid): Likewise. + (lll_unlock_wake_cb): Wake up other waiters if necessary. + Patch by Jakub Jelinek. + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Pretty printing. + +2003-03-17 Roland McGrath <roland@redhat.com> + + PowerPC port contributed by Paul Mackerras <paulus@samba.org>. + * sysdeps/pthread/pthread_spin_init.c: New file. + * sysdeps/pthread/pthread_spin_unlock.c: New file. + * sysdeps/powerpc/Makefile: New file. + * sysdeps/powerpc/pthread_spin_lock.c: New file. + * sysdeps/powerpc/pthread_spin_trylock.c: New file. + * sysdeps/powerpc/pthreaddef.h: New file. + * sysdeps/powerpc/tcb-offsets.sym: New file. + * sysdeps/powerpc/td_ta_map_lwp2thr.c: New file. + * sysdeps/powerpc/tls.h: New file. + * sysdeps/powerpc/bits/atomic.h: New file. + * sysdeps/unix/sysv/linux/libc-lowlevelmutex.c: New file. + * sysdeps/unix/sysv/linux/libc-lowlevellock.c: New file. + * sysdeps/unix/sysv/linux/lowlevellock.c: New file. + + * sysdeps/unix/sysv/linux/lowlevelmutex.c: New file. + * sysdeps/unix/sysv/linux/sem_post.c: New file. + * sysdeps/unix/sysv/linux/sem_timedwait.c: New file. + * sysdeps/unix/sysv/linux/sem_trywait.c: New file. + * sysdeps/unix/sysv/linux/sem_wait.c: New file. + * sysdeps/unix/sysv/linux/powerpc/Makefile: New file. + * sysdeps/unix/sysv/linux/powerpc/createthread.c: New file. + * sysdeps/unix/sysv/linux/powerpc/fork.c: New file. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: New file. + * sysdeps/unix/sysv/linux/powerpc/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/powerpc/pthread_once.c: New file. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: New file. + * sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h: New file. + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.c: Use __gettimeofday, + not gettimeofday. + * sysdeps/unix/sysv/linux/ia64/lowlevelmutex.c: Likewise. + * sysdeps/unix/sysv/linux/ia64/sem_timedwait.c: Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevellock.c: Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevelmutex.c: Likewise. + * sysdeps/unix/sysv/linux/s390/sem_timedwait.c: Likewise. + +2003-03-17 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread_cond_wait.c: Correct exit criteria. + * sysdeps/pthread/pthread_cond_timedwait.c: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + Patch by Ewald Snel <ewald@rambo.its.tudelft.nl>. + +2003-03-16 Roland McGrath <roland@redhat.com> + + * tst-fork4.c: Include <string.h>. + * tst-signal2.c: Likewise. + * tst-mutex5.c (do_test): exit -> return. + * tst-mutex2.c: Include <stdlib.h>. + +2003-03-16 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S + (__lll_mutex_timedlock_wait): Correct expected value after + spurious wakeup. Otherwise we would never wait again. + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Work around red + zone versus inline asm stupidity. Use correct instructions. + + * tst-rwlock6.c: Add some more status output. + +2003-03-15 Roland McGrath <roland@redhat.com> + + * sysdeps/pthread/configure.in: New file. + * sysdeps/pthread/configure: New file (generated). + +2003-03-15 Ulrich Drepper <drepper@redhat.com> + + * allocatestack.c (allocate_stack): Store the exact stack size of + user allocated stacks. + +2003-03-15 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h + (SINGLE_THREAD): Use `header' prefix instead of `header.data'. + * sysdeps/sh/tcb-offsets.sym (MULTIPLE_THREADS_OFFSET): Likewise. + * sysdeps/sh/tls.h (TLS_MULTIPLE_THREADS_IN_TCB): Define. + * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (SINGLE_THREAD_P): + Use `header.' prefix. + * sysdeps/ia64/tcb-offsets.sym (MULTIPLE_THREADS_OFFSET): Likewise. + +2003-03-15 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/x86_64/pthreaddef.h (CURRENT_STACK_FRAME): Don't use + __builtin_frame_address, use stack pointer. + + * sysdeps/unix/sysv/linux/jmp-unwind.c: Use CURRENT_STACK_FRAME + instead of __builtin_frame_pointer. + +2003-03-14 Ulrich Drepper <drepper@redhat.com> + + * tst-basic1.c (do_test): Add cast to avoid warning. + * tst-basic2.c (do_test): Likewise. + + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Use correct + amount of stack correction. + + * tst-fork4.c: Use test-skeleton.c. + +2003-03-14 Roland McGrath <roland@redhat.com> + + * init.c: Fix typo "#eli" for "#else". + +2003-03-14 Steven Munroe <sjmunroe@us.ibm.com> + + * allocatestack.c (__stack_user): Use hidden_data_def. + * pthread_create.c (__pthread_keys): Likewise. + + * init.c [__powerpc__] (__NR_set_tid_address): Define it. + +2003-03-14 Roland McGrath <roland@redhat.com> + + * tst-fork4.c: New file. + * Makefile (tests): Add it. + + * descr.h (struct pthread): Move the union out of [!TLS_DTV_AT_TP], so + we always define the padding space. + [!TLS_DTV_AT_TP]: Give tcbhead_t field a name, `header', since GCC + stopped supporting its own extensions fully. + [TLS_MULTIPLE_THREADS_IN_TCB]: Put `multiple_threads' inside a wrapper + struct also called `header', so `header.multiple_threads' is the field + name to use on all machines. + * allocatestack.c (allocate_stack): Use `header.' prefix. + * sysdeps/pthread/createthread.c (create_thread): Likewise. + * pthread_create.c (__pthread_create_2_1): Likewise. + * sysdeps/i386/tls.h (INSTALL_NEW_DTV, THREAD_DTV): Likewise. + (THREAD_SELF): Likewise. + * sysdeps/x86_64/tls.h: Likewise. + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h + (SINGLE_THREAD_P): Likewise. + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h + (SINGLE_THREAD_P): Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h + (SINGLE_THREAD_P): Likewise. + + * sysdeps/s390/td_ta_map_lwp2thr.c (td_ta_map_lwp2thr): Use REGS[18] + value directly. + +2003-03-14 Ulrich Drepper <drepper@redhat.com> + + * pthread_create.c (start_thread): Use CALL_THREAD_FCT if defined. + * sysdeps/i386/tls.h: Define CALL_THREAD_FCT. + + * pthread_create.c (start_thread): setjmp is expected to return 0. + + * sysdeps/x86_64/tls.h (THREAD_GETMEM): Mark asms volatile. + (THREAD_GETMEM_NC): Likewise. + +2003-03-13 Ulrich Drepper <drepper@redhat.com> + + * allocatestack.c (allocate_stack): If MULTI_PAGE_ALIASING is defined + and the size of the stack which must be allocated is a multiple, + allocate one more page. + * sysdeps/i386/i686/Makefile: Don't define COLORING_INCREMENT, but + MULTI_PAGE_ALIASING. + +2003-03-13 Roland McGrath <roland@redhat.com> + + * pthread_create.c (start_thread): Set EXITING_BIT after the + event-reporting (and destructors), not before. + +2003-03-13 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (lll_futex_timed_wait, + lll_futex_wake): Declare register variables as long int instead of + unsigned long int. Patch by Ian Wienand <ianw@gelato.unsw.edu.au>. + Make syscall arguments clobbered by the syscall. + (lll_futex_wait): Define using lll_futex_timed_wait. + + * sysdeps/ia64/td_ta_map_lwp2thr.c (td_ta_map_lwp2thr): Cast regs[13] + to void *. + + * sysdeps/unix/sysv/linux/fork.c (__libc_fork): Only declare and set + PPID if [! NDEBUG]. + + * allocatestack.c (nptl_ncreated): Only declare if + COLORING_INCREMENT != 0. + + * pthreadP.h (__pthread_enable_asynccancel_2): New prototype. + (__libc_enable_asynccancel_2): Remove prototype. + + * sysdeps/unix/sysv/linux/ia64/fork.c (ARCH_FORK): Swap ptid and + ctid to match kernel. + +2003-03-12 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/Makefile (sysdep_routines): Add + libc_multiple_threads. + * sysdeps/unix/sysv/linux/libc_pthread_init.c: Move definition of + __libc_multiple_threads to... + * sysdeps/unix/sysv/linux/libc_multiple_threads.c: ...here. New file. + + * sysdeps/unix/sysv/linux/x86_64/sem_post.S: Remove unnecessary + versioning. + * sysdeps/unix/sysv/linux/x86_64/sem_trywait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise. + + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S + (__pthread_once_internal): Define. + + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Use shlib-compat.h + macros instead of .symver directly. + * sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Likewise. + + * sysdeps/x86_64/tls.h [__ASSEMBLER__]: Include tcb-offsets.h. + * sysdeps/x86_64/tcb-offsets.sym: New file. + * sysdeps/x86_64/Makefile: New file. + + * sysdeps/i386/tcb-offsets.sym: Add SELF. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Use SELF + to access own pthread_t in TCB. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. + +2003-03-12 Roland McGrath <roland@redhat.com> + + * pthread-errnos.sym: New file. + * Makefile (gen-as-const-headers): New variable, list that file. + * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Include generated + header <pthread-errnos.h> instead of defining errno values here. + * sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_trywait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_post.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevelmutex.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/sem_trywait.S: Likewise. + * sysdeps/unix/sysv/linux/sh/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/sh/sem_post.S: Likewise. + * sysdeps/unix/sysv/linux/sh/sem_wait.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/lowlevelmutex.S: Likewise. + * sysdeps/i386/i486/pthread_spin_trylock.S: Likewise. + * sysdeps/x86_64/pthread_spin_trylock.S: Likewise. + * sysdeps/sh/pthread_spin_trylock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: Likewise. + + * sysdeps/unix/sysv/linux/fork.c: Add an assert to check that + CLONE_CHILD_SETTID worked. + +2003-03-12 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S: New + file. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S: New + file. + + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h + (pthread_cond_t): Add padding. + + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: New file. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: New file. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S: New file. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S + (__pthread_rwlock_timedwrlock): Add missing opcode suffix. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S + (__pthread_rwlock_timedrdlock): Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S + (__pthread_rwlock_wrlock): Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S + (__pthread_rwlock_rdlock): Likewise. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: New file. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Return + result of lock re-get if it fails. + +2003-03-11 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Fix asm syntax. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevelmutex.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_post.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_trywait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise. + + * sysdeps/x86_64/tls.h (THREAD_SELF, THREAD_GETMEM, THREAD_GETMEM_NC, + THREAD_SETMEM, THREAD_SETMEM_NC): Correct asm syntax. + + * allocatestack.c [! TLS_MULTIPLE_THREADS_IN_TCB] (allocate_stack): + Initialize *__libc_multiple_threads_ptr not __libc_multiple_threads. + * sysdeps/pthread/createthread.c [! TLS_MULTIPLE_THREADS_IN_TCB] + (create_thread): Likewise. + Define __pthread_multiple_threads and __libc_multiple_threads_ptr. + * init.c (__pthread_initialize_minimal_internal): Initialize + __libc_multiple_threads_ptr if necessary. + * pthreadP.h: Adjust prototype for __libc_pthread_init. Declare + __pthread_multiple_threads and __libc_multiple_threads_ptr. + * sysdeps/unix/sysv/linux/libc_pthread_init.c: Define + __libc_multiple_threads. + (__libc_pthread_init): Return pointer to __libc_pthread_init if + necessary. + + * sysdeps/i386/tls.h (THREAD_SETMEM): Fix one-byte variant. + (THREAD_SETMEM_NC): Likewise. + + * sysdeps/x86_64/pthread_spin_trylock.c: Removed. + * sysdeps/x86_64/pthread_spin_trylock.S: New file. + * sysdeps/x86_64/pthread_spin_unlock.c: Removed. + * sysdeps/x86_64/pthread_spin_unlock.S: New file. + + * sysdeps/i386/i486/pthread_spin_trylock.S (pthread_spin_trylock): + Eliminate one entire instruction. + + * cancellation.c (__pthread_enable_asynccancel_2): New function. + * pthreadP.h: Declare __pthread_enable_asynccancel_2. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Use __pthread_enable_asynccancel_2 + instead of __pthread_enable_asynccancel. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S + (__pthread_cond_wait): Likewise. + * sysdeps/pthread/pthread_cond_timedwait.c + (__pthread_cond_timedwait): Likewise. + * sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): Likewise. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S + (__condvar_cleanup): Wake up all waiters in case we got signaled + after being woken up but before disabling asynchronous + cancellation. + * sysdeps/pthread/pthread_cond_wait.c (__condvar_cleanup): Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S + (__condvar_cleanup): Likewise. + + * init.c (__NR_set_tid_address): If already defined, don't redefine. + Make it an error if architecture has no #if case. Add x86-64. + + * sysdeps/unix/sysv/linux/x86_64/Makefile: Add flags for + pt-initfini.s generation. + + * sysdeps/x86_64/tls.h: Include <asm/prctl.h>. + (TLS_INIT_TP): Fix typo. + +2003-03-11 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/ia64/bits/atomic.h (atomic_exchange_and_add): Swap 2nd and + 3rd argument of __arch_compare_and_exchange_{32,64}_val_acq. + + * sysdeps/unix/sysv/linux/ia64/sem_post.c: Include semaphore.h. + * sysdeps/unix/sysv/linux/ia64/sem_timedwait.c: Likewise. + * sysdeps/unix/sysv/linux/ia64/sem_trywait.c: Likewise. + * sysdeps/unix/sysv/linux/ia64/sem_wait.c: Likewise. + * sysdeps/unix/sysv/linux/s390/sem_post.c: Likewise. + * sysdeps/unix/sysv/linux/s390/sem_timedwait.c: Likewise. + * sysdeps/unix/sysv/linux/s390/sem_trywait.c: Likewise. + * sysdeps/unix/sysv/linux/s390/sem_wait.c: Likewise. + +2003-03-11 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread_cond_timedwait.c + (__pthread_cond_timedwait): Return the result of the final + locking. If it succeeds, the regular function return value. + + * sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): + Return result of the final locking. + * version.c (__nptl_main): Work around problems with the strange + INTERNAL_SYSCALL macro on ppc32. + * init.c (__pthread_initialize_minimal_internal): Unblock + SIGCANCEL in case the parent blocked it. + Reported by Paul Mackerras <paulus@samba.org>. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: New file. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: New file. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: New file. + +2003-03-11 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/pthread_cond_timedwait.c + (__pthread_cond_timedwait): Unlock and fail if + __pthread_mutex_unlock_internal failed. + + * sysdeps/pthread/createthread.c (ARCH_CLONE): Define if not defined. + (create_thread): Only assert PD->tcb != NULL under [TLS_TCB_AT_TP]. + Use ARCH_CLONE. + * allocatestack.c (ALLOCATE_STACK_PARMS): New macro. + [NEED_SEPARATE_REGISTER_STACK] (STACK_VARIABLES, + STACK_VARIABLES_ARGS, STACK_VARIABLES_PARMS, ALLOCATE_STACK_PARMS, + ALLOCATE_STACK): New macros. + (TLS_TPADJ): New macro. + (get_cached_stack, queue_stack, __deallocate_stack): Use TLS_TPADJ. + (allocate_stack): Handle TLS_DTV_AT_TP and + NEED_SEPARATE_REGISTER_STACK. Use TLS_TPADJ. + * pthread_create.c (__pthread_create_2_1) [! TLS_TCB_AT_TP]: + Don't set PD->self. + * init.c [__ia64__] (__NR_set_tid_address): Define. + + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: New file. + * sysdeps/unix/sysv/linux/ia64/bits/semaphore.h: New file. + * sysdeps/unix/sysv/linux/ia64/fork.c: New file. + * sysdeps/unix/sysv/linux/ia64/createthread.c: New file. + * sysdeps/unix/sysv/linux/ia64/libc-lowlevellock.c: New file. + * sysdeps/unix/sysv/linux/ia64/libc-lowlevelmutex.c: New file. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.c: New file. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: New file. + * sysdeps/unix/sysv/linux/ia64/lowlevelmutex.c: New file. + * sysdeps/unix/sysv/linux/ia64/pt-initfini.c: New file. + * sysdeps/unix/sysv/linux/ia64/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/ia64/pthread_once.c: New file. + * sysdeps/unix/sysv/linux/ia64/sem_post.c: New file. + * sysdeps/unix/sysv/linux/ia64/sem_timedwait.c: New file. + * sysdeps/unix/sysv/linux/ia64/sem_trywait.c: New file. + * sysdeps/unix/sysv/linux/ia64/sem_wait.c: New file. + * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h: New file. + * sysdeps/ia64/bits/atomic.h: New file. + * sysdeps/ia64/Makefile: New file. + * sysdeps/ia64/pthread_spin_init.c: New file. + * sysdeps/ia64/pthread_spin_lock.c: New file. + * sysdeps/ia64/pthread_spin_trylock.c: New file. + * sysdeps/ia64/pthread_spin_unlock.c: New file. + * sysdeps/ia64/pthreaddef.h: New file. + * sysdeps/ia64/tcb-offsets.sym: New file. + * sysdeps/ia64/td_ta_map_lwp2thr.c: New file. + * sysdeps/ia64/tls.h: New file. + + * sysdeps/s390/pthreaddef.h (__exit_thread_inline): Pass 1 argument + to syscall instead of no arguments. + +2003-03-10 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/sem_post.S: New file. + * sysdeps/unix/sysv/linux/x86_64/sem_trywait.S: New file. + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: New file. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: New file. + + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Fix error value in + unused code. + + * sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S: New file + + * sysdeps/unix/sysv/linux/Makefile (gen-as-const-headers): Add + lowlevelbarrier.sym. + * sysdeps/unix/sysv/linux/lowlevelbarrier.sym: New file. + * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: + Include lowlevelbarrier.h and don't define offsets locally. + * sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S: Likewise. + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h + (__lll_mutex_lock_wait): Reverse order of first two parameters. + (__lll_mutex_timedlock_wait): Likewise. + (lll_mutex_lock): Adjust asm for that. + (lll_mutex_timedlock): Likewise. Mark cx, cc, r10 as clobbered. + (lll_lock): Adjust asm for operand order change. + * sysdeps/unix/sysv/linux/x86_64/lowlevelmutex.S: New file. + * sysdeps/unix/sysv/linux/x86_64/libc-lowlevelmutex.S: New file. + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (__lll_lock_wait): + Reverse order of parameters. + (__lll_timedwait_tid): Remove regparms attribute. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: New file. + * sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S: New file. + + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S + (__lll_timedwait_tid): Remove one unnecessary instruction. + + * sysdeps/unix/sysv/linux/sh/lowlevelmutex.S: Define + __lll_mutex_timedlock_wait only for NOT_IN_libc. + * sysdeps/unix/sysv/linux/sh/libc-lowlevelmutex.S: Include + lowlevelmutex.S. + + * sysdeps/unix/sysv/linux/sh/lowlevellock.S: Define + lll_unlock_wake_cb, __lll_wait_tid, and __lll_timedwait_tid only + for NOT_IN_libc. + * sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S: Include + lowlevellock.S. + + * sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S: Don't define + LOCK is already defined. Don't define __lll_mutex_timedlock_wait + for libc.so. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevelmutex.S: Only + define LOCK here (if UP is not defined). The actual code is in + lowlevelmutex.S. + + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Don't define + LOCK is already defined. Don't define lll_unlock_wake_cb and + __lll_timedwait_tid for libc.so. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Only + define LOCK here (if UP is not defined). The actual code is in + lowlevellock.S. + + * sysdeps/unix/sysv/linux/i386/lowlevelsem.h: Not needed anymore. + * sysdeps/unix/sysv/linux/s390/lowlevelsem.h: Likewise. + * sysdeps/unix/sysv/linux/s390/sem_post.c: Include lowlevellock.h + instead of lowlevelsem.h. + * sysdeps/unix/sysv/linux/s390/sem_timedwait.c: Likewise. + * sysdeps/unix/sysv/linux/s390/sem_trywait.c: Likewise. + * sysdeps/unix/sysv/linux/s390/sem_wait.c: Likewise. + + * sysdeps/unix/sysv/linux/Makefile (gen-as-const-headers): Add + lowlevelrwlock.sym. + * sysdeps/unix/sysv/linux/lowlevelrwlock.sym: New file. + * sysdeps/unix/sysv/linux/i386/lowlevelrwlock.h: Removed. + * sysdeps/unix/sysv/linux/sh/lowlevelrwlock.h: Removed. + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (lll_trylock): Fix + register loading. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_trylock): Undo + last changed. D'oh. + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: New file. + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Remove declaration + of __libc_locking_needed. + (lll_trylock): Initialize %eax to zero. + + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Update + pthread_cond_t definition. + +2003-03-10 Roland McGrath <roland@redhat.com> + + * sysdeps/unix/sysv/linux/lowlevelcond.sym: New file. + * sysdeps/unix/sysv/linux/Makefile (gen-as-const-headers): Add it. + * sysdeps/unix/sysv/linux/sh/lowlevelcond.h: File removed. + * sysdeps/unix/sysv/linux/i386/lowlevelcond.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevelcond.h: Likewise. + + * allocatestack.c (allocate_stack) [!TLS_MULTIPLE_THREADS_IN_TCB]: + Instead of setting PD->multiple_threads, set globals + __pthread_multiple_threads and __libc_multiple_threads. + * sysdeps/pthread/createthread.c (create_thread): Likewise. + * sysdeps/i386/tls.h (TLS_MULTIPLE_THREADS_IN_TCB): Define it. + * sysdeps/s390/tls.h (TLS_MULTIPLE_THREADS_IN_TCB): Likewise. + + * descr.h (struct pthread): Conditionalize first member on + [!TLS_DTV_AT_TP]. Replace the `header' member with an anonymous union + containing an anonymous tcbhead_t. Move `list' member out. + [TLS_MULTIPLE_THREADS_IN_TCB]: Define a `multiple_threads' member. + * allocatestack.c: Remove use of `header.data.' prefix. + * pthread_create.c: Likewise. + * init.c (__pthread_initialize_minimal_internal): Likewise. + * sysdeps/pthread/createthread.c (create_thread): Likewise. + * sysdeps/i386/tls.h (INSTALL_DTV): Add parens. + (THREAD_SELF, THREAD_DTV, INSTALL_NEW_DTV): No `header.data.' prefix. + * sysdeps/x86_64/tls.h: Likewise. + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h + (SINGLE_THREAD_P): Likewise. + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h + (SINGLE_THREAD_P): Likewise. + * sysdeps/i386/tls.h (tcbhead_t): Remove `list' member. + * sysdeps/s390/tls.h (tcbhead_t): Likewise. + +2003-03-09 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/lowlevelcond.h: New file. + + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: New file. + * sysdeps/unix/sysv/linux/x86_64/fork.c: New file. + + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Fix many + leftovers from the ia32 code. + + * sysdeps/unix/sysv/linux/i386/pthread_once.S: Remove unneccessary + memory load. + (clear_once_control): Don't load %esi. + + * sysdeps/x86_64/tls.h: Remove all traces of segment descriptor + handling. + + * sysdeps/unix/sysv/linux/x86_64/fork.c: New file. + + * sysdeps/unix/sysv/linux/s390/createthread.c: Moved to... + * sysdeps/unix/sysv/linux/createthread.c: ...here. + + * Makefile (tests): Add tst-cond10. + * tst-cond10.c: New file. + +2003-03-08 Ulrich Drepper <drepper@redhat.com> + + * tst-tls2.c (do_test): Add TEMP_FAILURE_RETRY around sem_wait call. + * tst-signal3.c (do_test): Likewise. + * tst-sem5.c (do_test): Likewise. + * tst-kill6.c (do_test): Likewise. + * tst-tls3.c (do_test): Likewise. Include <errno.h>. + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Use add/sub instead + of inc/dec. + * sysdeps/unix/sysv/linux/i386/lowlevelsem.h: Likewise. + * sysdeps/unix/sysv/linux/i386/pthread_once.S: Likewise + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Likewise. + + * allocatestack.c (allocate_stack): If mprotect() fails free the + TLS memory. + +2003-03-07 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/i386/i486/bits/atomic.h: Fix a few unused definitions. + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Remove all trace of + lll_wake_tid. This was used only to work around kernel limits in + the early days. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/lowlevellock.h: Likewise. + + * init.c (__static_tls_align_m1): Renamed from __static_tls_align. + (__pthread_initialize_minimal_internal): Change initialization of + __static_tls_align_m1 appropriately. + * pthreadP.h (__static_tls_align_m1): Renamed from + __static_tls_align. + * allocatestack.c (allocate_stack): Use __static_tls_align_m1 + instead of __static_tls_align-1. + +2003-03-04 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/x86_64/Makefile: New file. + + * pthread_create.c: Define __pthread_keys using nocommon + attribute, not by placing it explicitly in bss. + Remove DEFINE_DEALLOC definition. Not needed anymore. + + * allocatestack.c: Define ARCH_MAP_FLAGS if not already defined. + Use it in mmap call to allocate stacks. + + * sysdeps/pthread/createthread.c (create_thread): Fix comment. + + * pthread_create.c (start_thread): Use THREAD_SETMEM to store + result of the thread function. + +2003-03-03 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/s390/dl-sysdep.h: Removed. The generic + version is just fine. + + * sysdeps/unix/sysv/linux/libc_pthread_init.c + (__pthread_child_handler): Renamed from pthread_child_handler, + exported, and marked hidden. Change all users. + * sysdeps/unix/sysv/linux/register-atfork.c (free_mem): Do not + free __pthread_child_handler from child list. + +2003-03-03 Martin Schwidefsky <schwidefsky@de.ibm.com> + + * atomic.h (atomic_exchange_and_add): Return newval, not oldval. + + * sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait): + Fix handling of cancellation and failing pthread_mutex_unlock call. + * sysdeps/pthread/pthread_cond_wait.c (__condvar_cleanup): Likewise. + (__pthread_cond_wait): Likewise. + + * sysdeps/pthread/pthread_rwlock_timedrdlock.c + (pthread_rwlock_timedrdlock): Fix clobber of result variable by + lll_futex_timed_wait call. + * sysdeps/pthread/pthread_rwlock_timedwrlock.c + (pthread_rwlock_timedwrlock): Likewise. + + * sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c (___lll_lock): + Don't define lll_unlock_wake_cb and ___lll_timedwait_tid in libc.so. + * sysdeps/unix/sysv/linux/s390/lowlevellock.c: Remove XXX comments. + + * sysdeps/unix/sysv/linux/s390/sem_post.c (__new_sem_post): Fix + check of lll_futex_wake return value. + +2003-03-03 Roland McGrath <roland@redhat.com> + + * forward.c: Fix typo in __pthread_attr_init_2_0 compat_symbol decl. + + * sysdeps/pthread/pthread-functions.h (struct pthread_functions): + Argument to ptr___pthread_cleanup_upto is __jmp_buf, not jmp_buf. + * sysdeps/unix/sysv/linux/jmp-unwind.c: Likewise. + +2003-03-02 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/timer_create.c (timer_create): Return correct + error for CPU clocks. + + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Define + _POSIX_MONOTONIC_CLOCK. + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise. + + * tst-cancel4.c (tf_sleep): Lower sleep time a bit to not upset + recent kernels. + +2003-03-01 Ulrich Drepper <drepper@redhat.com> + + * descr.h (struct pthread): Move cleanup field to the front. + +2003-03-01 Roland McGrath <roland@redhat.com> + + * sem_open.c (sem_open): Braino fix. + +2003-03-01 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/i386/tcb-offsets.sym: Add CLEANUP and CLEANUP_PREV. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Inline + __pthread_cleanup_pop functionality. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + + * descr.h (struct pthread): Move tid field to the front now that + it is often used. + + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevelmutex.S + (__lll_mutex_timedlock_wait): Remove. + (__lll_mutex_unlock_wake): Don't save, load, and restore %esi. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S + (__lll_mutex_unlock_wake): Don't save, load, and restore %esi. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S + (lll_unlock_wake_cb): Don't save and restore %esi. + (__lll_unlock_wake): Add alignment. Don't save, load, and restore + %esi. + (__lll_timedwait_tid): Add alignment. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S + (__lll_unlock_wake): Add alignment. Don't save, load, and restore + %esi. + (__lll_timedwait_tid): Removed. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S + (__pthread_cond_broadcast): Don't save, load, and restore %esi. + * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S + (pthread_barrier_wait): Don't save, load, and restore %esi for + last thread. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S + (__pthread_cond_signal): Don't save, load, and restore %esi. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S + (__pthread_rwlock_unlock): Don't save, load, and restore %esi. + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S (__new_sem_post): + Don't save, load, and restore %esi. + +2003-02-27 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: + Release lock before waking up the waiters. + + * tst-exit1.c (do_test): Don't start more than one thread in parallel. + + * tst-rwlock9.c (writer_thread): Correct adding TIMEOUT. + (reader_thread): Likewise. + + * sysdeps/pthread/pthread_rwlock_unlock.c + (__pthread_rwlock_unlock): Release internal lock early. Don't try + to wake up readers if there are none. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: + Release internal lock before wake threads. + +2003-02-26 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-rwlock10 and tst-rwlock11. + * tst-rwlock8.c: Initialize lock with INIT. Allow INIT to be + predefined. + * tst-rwlock9.c: Likewise. + * tst-rwlock10.c: New file. + * tst-rwlock11.c: New file. + + * Makefile (tests): Add tst-dlsym1. + * tst-dlsym1.c: New file. + + * init.c (__pthread_initialize_minimal_internal): Set + GL(dl_error_catch_tsd) to __libc_dl_error_tsd. + * Versions (libc:GLIBC_PRIVATE): Export __libc_dl_error_tsd. + +2003-02-24 Ulrich Drepper <drepper@redhat.com> + + * sem_open.c (sem_open): Fix handling of O_CREAT without O_EXCL. + + * tst-cond2.c: Fix sychronization with child. + + * tst-rwlock8.c (reader_thread): Remove unused variable. + + * Makefile: Add rules to build and run tst-tls3. + * tst-tls3.c: New file. + * tst-tls3mod.c: New file. + + * Makefile (tests): Add tst-rwlock8 and tst-rwlock9. + * tst-rwlock8.c: New file. + * tst-rwlock9.c: New file. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Fix + complete broken rwlock implementation. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/pthread/pthread_rwlock_rdlock.c: Likewise. + * sysdeps/pthread/pthread_rwlock_timedrdlock.c: Likewise. + * sysdeps/pthread/pthread_rwlock_timedwrlock.c: Likewise. + * sysdeps/pthread/pthread_rwlock_unlock.c: Likewise. + * sysdeps/pthread/pthread_rwlock_wrlock.c: Likewise. + +2003-02-23 Roland McGrath <roland@redhat.com> + + * Makefile (nptl-version): Change regexp so case sensitivity is ok. + +2003-02-23 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-context1. + * tst-context1.c: New file. + + * Makefile (tests): Add tst-tls1 and tst-tls2. + * tst-tls1.c: New file. + * tst-tls2.c: New file. + + * libc-cancellation.c (__libc_enable_asynccancel): Correct test + for failed cmpxchg. + + * pthread_create.c (start_thread): Set EXITING_BIT early. + + * sysdeps/i386/tls.h (THREAD_GETMEM): Mark asm as volatile. + (THREAD_GETMEM_NC): Likewise. + +2003-02-22 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: Shave + off 3 more bytes by using offset-less instructions when possible. + + * Makefile: Add dependency for $(objpfx)version.d. + + * eintr.c (eintr_source): Add unnecessary return but the compiler + insists. + + * tst-kill3.c: Include <unistd.h>. + +2003-02-21 Roland McGrath <roland@redhat.com> + + * pthread_create.c (start_thread): Call __libc_thread_freeres. + +2003-02-21 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-eintr1. + (distribute): Add eintr.c. + * tst-eintr1.c: New file. + * eintr.c: New file. + + * pthread_cancel.c (pthread_cancel): Use tkill directly. + + * sysdeps/unix/sysv/linux/pthread_kill.c (__pthread_kill): + Disallow sending SIGCANCEL. + + * Makefile (tests): Remove tst-basic7. Add tst-kill1, tst-kill2, + tst-kill3, tst-kill4, tst-kill5, tst-kill6. + * tst-kill1.c: New file. + * tst-kill2.c: New file. + * tst-kill3.c: New file. + * tst-kill5.c: New file. + * tst-kill6.c: New file. + * tst-basic7.c: Renamed to... + * tst-kill4.c: ...this. + +2003-02-21 Roland McGrath <roland@redhat.com> + + * Makefile (install-lib-ldscripts): New variable. + +2003-02-21 Ulrich Drepper <drepper@redhat.com> + + * pthreadP.h: Define INVALID_TD_P and INVALID_NOT_TERMINATED_TD_P. + * pthread_cancel.c: Use INVALID_TD_P. + * pthread_detach.c: Likewise. + * pthread_getschedparam.c: Likewise. + * pthread_setschedparam.c: Likewise. + * sysdeps/pthread/pthread_getcpuclockid.c: Likewise. + * sysdeps/unix/sysv/linux/pthread_kill.c: Likewise. + * pthread_join.c: Use INVALID_NOT_TERMINATED_TD_P. + * pthread_timedjoin.c: Likewise. + + * tst-basic7.c: Include <signal.h>. + + * pthread_join.c (pthread_join): Limited checking for invalid + descriptors. + * pthread_timedjoin.c (pthread_timedjoin_np): Likewise. + +2003-02-20 Ulrich Drepper <drepper@redhat.com> + + * pthread_create.c (deallocate_tsd): Reset found_nonzero at the + beginning of the loop. Clear the entire first block of TSD. + * Makefile (tests): Add tst-key4. + * tst-key4.c: New file. + +2003-02-18 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-basic7. + * tst-basic7.c: New file. + + * pthread_create.c (deallocate_tsd): Mark as internal_function. + Add some more __builtin_expect. + + * pthreadP.h: Define dummy version of DEBUGGING_P. + +2003-02-17 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Remnove + _POSIX_THREAD_PRIORITY_SCHEDULING. + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Remove + _XOPEN_REALTIME_THREADS. + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Likewise. + + * sysdeps/unix/sysv/linux/pthread_kill.c (__pthread_kill): The + kernel returns EINVAL for PID <= 0, work around it. + + * Makefile (tests): Add tst-signal5. + * tst-signal5.c: New file. + + * sysdeps/unix/sysv/linux/bits/local_lim.h: Define TTY_NAME_MAX + and LOGIN_NAME_MAX. + + * tst-cancel1.c (tf): Block all signals. + + * Makefile (tests): Add tst-basic6. + * tst-basic6.c: New file. + + * tst-basic1.c: Add test for process ID. + + * Makefile (tests): Add tst-cancel10. + * tst-cancel10.c: New file. + + * Makefile (tests): Add tst-signal4. + * tst-signal4.c: New file. + + * sysdeps/pthread/pthread_sigmask.c (pthread_sigmask): Use + __sigismember instead of sigismember. Add __builtin_expect. + +2003-02-16 Ulrich Drepper <drepper@redhat.com> + + * tst-attr1.c (do_test): Add tests for pthread_setcanceltype, + pthread_setcancelstate, and pthread_rwlock_setpshared. + + * tst-cancel7.c (do_test): Make sure the pid file exists before + canceling the thread. + + * tst-rwlock6.c: More pthread_rwlock_timedwrlock and + pthread_rwlock_timedrdlock tests. + * tst-rwlock7.c: More pthread_rwlock_timedwrlock tests. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Check for invalid tv_nsec field. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + + * pthread_mutex_trylock.c (__pthread_mutex_trylock): Protect + recursive mutex of overflow. + + * tst-attr1.c (do_test): Add test for pthread_mutexattr_setpshared. + + * libc-cancellation.c (__libc_enable_asynccancel): Rewrite to avoid + going into an endless loop. + * Makefile (tests): Add tst-cancel9. + * tst-cancel9.c: New file. + + * pthread_cancel.c (pthread_cancel): Use the result of __pthread_kill. + +2003-02-15 Ulrich Drepper <drepper@redhat.com> + + * tst-mutex5.c (do_test): Add more timedlock tests. + + * tst-mutex2.c: Tests of trylock and unlock with ERROR mutexes. + * tst-mutex3.c (do_test): Add tests for trylock with RECURSIVE mutexes. + + * sysdeps/unix/sysv/linux/pthread_kill.c (__pthread_kill): Don't + use INLINE_SYSCALL. Error number is returned, not -1. + + * pthreadP.h: Mark declarations of __find_in_stack_list, __free_tcb, + and __deallocate_stack with internal_function. + * pthread_create.c: Adjust definitions appropriately. + * allocatestack.c: Likewise. + + * pthread_join.c: Add one more __builtin_expect. + * pthread_timedjoin.c: Likewise. + + * pthread_getspecific.c (__pthread_getspecific): Clear data->data + not data of sequence number does not match. + Add one __builtin_expect. + + * Makefile (tests): Add tst-clock1. + * tst-clock1.c: New file. + + * pthread_setconcurrency.c (pthread_setconcurrency): Fail for + negative arguments. + * Makefile (tests): Add tst-basic5. + * tst-basic5.c: New file. + +2003-02-14 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-basic4. + * tst-basic4.c: New file. + + * pthreadP.h: Add declaraction for __nptl_nthreads. + * pthread_create.c: Define __nptl_nthreads + (start_thread): Increment __nptl_nthreads at beginning. Decrement + after thread is done. If then zero, call exit(0). + * sysdeps/pthread/pthread-functions.h (struct pthread_functions): + Add ptr_nthreads. Define HAVE_PTR_NTHREADS. + * init.c (pthread_functions): Initialize ptr_nthreads. + * allocatestack.c (nptl_nthreads): Remove definition and all uses. + (__reclaim_stacks): Decrement __nptl_nthreads. + * sysdeps/pthread/Makefile [$(subdir)==csu] (CFLAGS-libc-start.c): + Define. + * Makefile (tests): Add tst-basic3. + * tst-basic3.c: New file. + + * descr.h: Define CANCELING_BIT and CANCELING_BITMASK. Introduce + after CANCELTYPE_BIT, move the other bits up. Update CANCEL_RESTMASK. + * init.c (sigcancel_handler): Also set CANCELING_BITMASK bit in newval. + * pthread_cancel.c (pthread_cancel): Likewise. Also set CANCELING_BIT + if asynchronous canceling is enabled. + * pthread_join.c (pthread_join): When recognizing circular joins, + take into account the other thread might be already canceled. + * Makefile (tests): Add tst-join5. + * tst-join5.c: New file. + + * Makefile (tests): Add tst-join4. + * tst-join4.c: New file. + +2003-02-13 Ulrich Drepper <drepper@redhat.com> + + * tst-cond4.c (main): Add test of pthread_attr_getpshared. + +2003-02-13 Martin Schwidefsky <schwidefsky@de.ibm.com> + + * sysdeps/s390/tls.h (THREAD_GETMEM, THREAD_GETMEM_NC, THREAD_SETMEM, + THREAD_SETMEM_NC): Use passed descr instead of THREAD_SELF. + * sysdeps/unix/sysv/linux/s390/jmp-unwind.c (_longjmp_unwind): Avoid + warning. + * sysdeps/unix/sysv/linux/s390/lowlevellock.c: Include <sys/time.h> + to avoid warning. + * sysdeps/unix/sysv/linux/s390/sem_post.c (__new_sem_post): Return + error if lll_futex_wake failed. + +2003-02-13 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Fix + handling of cancellation and failung pthread_mutex_unlock call. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * Makefile (tests): Add tst-cond8 and tst-cond9. + * tst-cond8.c: New file. + * tst-cond9.c: New file. + + * tst-cond7.c (do_test): Unlock the mutex before canceling the thread. + + * sysdeps/pthread/pthread.h: Add missing initializers. Protect + non-standard initializers with __USE_GNU. + + * Makefile (tests): Add tst-cleanup3. + * tst-cleanup3.c: New file. + +2003-02-12 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-attr1 and tst-attr2. + * tst-attr1.c: New file. + * tst-attr2.c: New file. + + * Makefile: Add rules to build and run tst-atfork2 test. + * tst-atfork2.c: New file. + * tst-atfork2mod.c: New file. + + * sysdeps/unix/sysv/linux/unregister-atfork.c + (__unregister_atfork): Free the memory allocated for the handlers + after removing them from the lists. + + * sysdeps/unix/sysv/linux/register-atfork.c: Define memeory + cleanup function. + + * tst-atfork1.c (do_test): Wait for the child we forked. + Report error in child. + + * sysdeps/unix/sysv/linux/fork.c (__libc_fork): Fix comment. + + * sysdeps/pthread/Makefile: Define CFLAGS-confstr.c. + +2003-02-10 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-cancel8. + * tst-cancel8.c: New file. + + * sysdeps/unix/sysv/linux/i386/pthread_once.S (clear_once_control): Fix + clearing of control variable. + * Makefile (tests): Add tst-once3 and tst-once4. + * tst-once3.c: New file. + * tst-once4.c: New file. + +2003-02-08 kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/sh/Makefile: New file. + * sysdeps/sh/bits/atomic.h: New file. + * sysdeps/sh/pthread_spin_init.c: New file. + * sysdeps/sh/pthread_spin_lock.c: New file. + * sysdeps/sh/pthread_spin_trylock.S: New file. + * sysdeps/sh/pthread_spin_unlock.S: New file. + * sysdeps/sh/pthreaddef.h: New file. + * sysdeps/sh/tcb-offsets.sym: New file. + * sysdeps/sh/td_ta_map_lwp2thr.c: New file. + * sysdeps/sh/tls.h: New file. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: New file. + * sysdeps/unix/sysv/linux/sh/bits/semaphore.h: New file. + * sysdeps/unix/sysv/linux/sh/createthread.c: New file. + * sysdeps/unix/sysv/linux/sh/fork.c: New file. + * sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S: New file. + * sysdeps/unix/sysv/linux/sh/libc-lowlevelmutex.S: New file. + * sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h: New file. + * sysdeps/unix/sysv/linux/sh/lowlevelcond.h: New file. + * sysdeps/unix/sysv/linux/sh/lowlevellock.S: New file. + * sysdeps/unix/sysv/linux/sh/lowlevellock.h: New file. + * sysdeps/unix/sysv/linux/sh/lowlevelmutex.S: New file. + * sysdeps/unix/sysv/linux/sh/lowlevelrwlock.h: New file. + * sysdeps/unix/sysv/linux/sh/pt-initfini.c: New file. + * sysdeps/unix/sysv/linux/sh/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_once.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: New file. + * sysdeps/unix/sysv/linux/sh/sem_post.S: New file. + * sysdeps/unix/sysv/linux/sh/sem_timedwait.S: New file. + * sysdeps/unix/sysv/linux/sh/sem_trywait.S: New file. + * sysdeps/unix/sysv/linux/sh/sem_wait.S: New file. + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: New file. + +2003-02-08 Ulrich Drepper <drepper@redhat.com> + + * tst-cond2.c: Rearrange code to not rely on behavior undefined + according to POSIX. + + * tst-basic2.c (do_test): Lock mutex before creating the thread. + +2003-02-07 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/x86_64/tls.h: Remove unnecessary macros, left over from x86. + (TLS_GET_FS): New #define. + (TLS_SET_FS): New #define. + Correct value of __NR_set_thread_area. + + * sysdeps/x86_64/td_ta_map_lwp2thr.c: New file. + +2003-02-06 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-popen1. + * tst-popen1.c: New file. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Remove wrong + but inactive generalization. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise. + Minor optimization, remove one instruction. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Likewise. + +2003-02-04 Martin Schwidefsky <schwidefsky@de.ibm.com> + + * sysdeps/unix/sysv/linux/s390/fork.c: Correct order of parameters. + +2003-01-31 Martin Schwidefsky <schwidefsky@de.ibm.com> + + * init.c (__NR_set_tid_address): Add #ifdef for s390. + * sysdeps/pthread/pthread_barrier_wait.c: New file. + * sysdeps/pthread/pthread_cond_broadcast.c: New file. + * sysdeps/pthread/pthread_cond_signal.c: New file. + * sysdeps/pthread/pthread_cond_timedwait.c: New file. + * sysdeps/pthread/pthread_cond_wait.c: New file. + * sysdeps/pthread/pthread_rwlock_rdlock.c: New file. + * sysdeps/pthread/pthread_rwlock_timedrdlock.c: New file. + * sysdeps/pthread/pthread_rwlock_timedwrlock.c: New file. + * sysdeps/pthread/pthread_rwlock_unlock.c: New file. + * sysdeps/pthread/pthread_rwlock_wrlock.c: New file. + * sysdeps/s390/Makefile: New file. + * sysdeps/s390/bits/atomic.h: New file. + * sysdeps/s390/pthread_spin_init.c: New file. + * sysdeps/s390/pthread_spin_lock.c: New file. + * sysdeps/s390/pthread_spin_trylock.c: New file. + * sysdeps/s390/pthread_spin_unlock.c: New file. + * sysdeps/s390/pthreaddef.h: New file. + * sysdeps/s390/tcb-offsets.sym: New file. + * sysdeps/s390/td_ta_map_lwp2thr.c: New file. + * sysdeps/s390/tls.h: New file. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: New file. + * sysdeps/unix/sysv/linux/s390/bits/semaphore.h: New file. + * sysdeps/unix/sysv/linux/s390/createthread.c: New file. + * sysdeps/unix/sysv/linux/s390/dl-sysdep.h: New file. + * sysdeps/unix/sysv/linux/s390/fork.c: New file. + * sysdeps/unix/sysv/linux/s390/jmp-unwind.c: New file. + * sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c: New file. + * sysdeps/unix/sysv/linux/s390/libc-lowlevelmutex.c: New file. + * sysdeps/unix/sysv/linux/s390/lowlevellock.c: New file. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h: New file. + * sysdeps/unix/sysv/linux/s390/lowlevelmutex.c: New file. + * sysdeps/unix/sysv/linux/s390/lowlevelsem.h: New file. + * sysdeps/unix/sysv/linux/s390/pthread_once.c: New file. + * sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c: New file. + * sysdeps/unix/sysv/linux/s390/s390-32/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h: New file. + * sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c: New file. + * sysdeps/unix/sysv/linux/s390/s390-64/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h: New file. + * sysdeps/unix/sysv/linux/s390/sem_post.c: New file. + * sysdeps/unix/sysv/linux/s390/sem_timedwait.c: New file. + * sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c: New file. + * sysdeps/unix/sysv/linux/s390/sem_wait.c: New file. + +2003-02-04 Ulrich Drepper <drepper@redhat.com> + + * atomic.h: Add a couple more default implementations. + (atomic_compare_and_exchange_acq): Use + __arch_compare_and_exchange_32_acq in return value definition. It + always exists. + (atomic_bit_set): Renamed from atomic_set_bit. + Add missing atomic_ prefixes. + + * sysdeps/pthread/bits/libc-lock.h (__libc_once): In case no + thread library is available, use correct value to mark initialized + once variable. + +2003-02-03 Ulrich Drepper <drepper@redhat.com> + + * allocatestack.c (allocate_stack): Use __getpagesize instead of + __sysconf to determine pagesize. + + * pthread_create.c: Include <atomic.h>. + * allocatestack.c (allocate_stack): Implement coloring of the + allocated stack memory. Rename pagesize to pagesize_m1. It's the + size minus one. Adjust users. + * sysdeps/i386/i686/Makefile: New file. + +2003-02-02 Ulrich Drepper <drepper@redhat.com> + + * allocatestack.c: Improve comment throughout the file. + + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S + (__lll_lock_wait): Add branch prediction. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S + (__lll_lock_wait): Likewise. + (lll_unlock_wake_cb): Removed. + +2003-01-31 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Remove + _POSIX_THREAD_PRIORITY_SCHEDULING. + +2003-01-30 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/pthread-functions.h (struct pthread_functions): + Fix return type of ptr___pthread_getspecific. + +2003-01-29 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-umask1. + (tst-umask1-ARGS): Define. + * tst-umask1.c: New file. + +2003-01-28 Ulrich Drepper <drepper@redhat.com> + + * Makefile (libpthread-routines): Remove lowlevelrwlock. Add + pthread_rwlock_rdlock, pthread_rwlock_timedrdlock, + pthread_rwlock_wrlock, pthread_rwlock_timedwrlock, and + pthread_rwlock_unlock. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S: Removed + * sysdeps/unix/sysv/linux/i386/i586/lowlevelrwlock.S: Removed + * sysdeps/unix/sysv/linux/i386/i686/lowlevelrwlock.S: Removed + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: New file. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + New file. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: New file. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + New file. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_rdlock.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedrdlock.S: + New file. + * sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_wrlock.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedwrlock.S: + New file. + * sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_unlock.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_rdlock.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedrdlock.S: + New file. + * sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_wrlock.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedwrlock.S: + New file. + * sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_unlock.S: New file. + + * Makefile (libpthread-routines): Remove lowlevelcond and + lowlevelsem. Add sem_wait, sem_trywait, sem_timedwait, sem_post, + pthread_cond_wait, pthread_cond_timedwait, pthread_cond_signal, + and pthread_cond_broadcast. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S: Removed + * sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S: Removed + * sysdeps/unix/sysv/linux/i386/i586/lowlevelsem.S: Removed + * sysdeps/unix/sysv/linux/i386/i586/lowlevelcond.S: Removed + * sysdeps/unix/sysv/linux/i386/i686/lowlevelsem.S: Removed + * sysdeps/unix/sysv/linux/i386/i686/lowlevelcond.S: Removed + * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: New file. + * sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S: New file. + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: New file. + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: New file. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: New file. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: New file. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: New file. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/sem_wait.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/sem_post.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/pthread_cond_signal.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/pthread_cond_broadcast.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/sem_wait.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/sem_post.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/pthread_cond_signal.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/pthread_cond_broadcast.S: New file. + * sysdeps/unix/sysv/linux/i386/lowlevelcond.h: New file. + + * sysdeps/unix/sysv/linux/i386/createthread.c: Define + PREPARE_CREATE and TLS_VALUE with x86-specific bits. All the rest + of the code is moved to ... + * sysdeps/pthread/createthread.c: ...here. New file. + +2003-01-27 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S + (__new_sem_post): Clear %eax before returning. + Reported by MAEDA Naoaki <maeda.naoaki@jp.fujitsu.com>. + + * Makefile (tests): Add tst-cleanup2. + * tst-cleanup2.c: New file. + + * sysdeps/pthread/bits/libc-lock.h (__libc_cleanup_region_start): + Interpret first parameter correctly. + +2003-01-17 Ulrich Drepper <drepper@redhat.com> + + * Makefile (headers): Add bits/semaphore.h. + +2003-01-16 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/i386/tls.h (INIT_SYSINFO): Initialize _head->sysinfo even + if not SHARED. + +2003-01-14 Ulrich Drepper <drepper@redhat.com> + + * sem_open.c (sem_open): Return SEM_FAILED if existing semaphore + must be used and mapping failed. + Reported by Luke Elliott <luke.elliott@activfinancial.com>. + + * Makefile (CFLAGS-pthread_self.os): Define this, not + CFLAGS-pthread_self.c. + +2003-01-13 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Don't export + lll_unlock_wake_cb. + + * Makefile (libpthread-routines): Add version. Add rules to build + version.os and banner.h. + * version.c: New file. + +2003-01-13 Jakub Jelinek <jakub@redhat.com> + + * pthread_mutex_lock.c (__pthread_mutex_lock_internal): Make + the alias unconditional. + * pthread_mutex_unlock.c (__pthread_mutex_unlock_internal): Likewise. + +2003-01-13 Ulrich Drepper <drepper@redhat.com> + + * Makefile (CFLAGS-pthread_self.c): New definition. + +2003-01-06 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/pthread_sigmask.c (pthread_sigmask): Add + INTERNAL_SYSCALL_DECL, add err argument to INTERNAL_SYSCALL* macros. + * sysdeps/unix/sysv/linux/raise.c (raise): Likewise. + * init.c (__pthread_initialize_minimal_internal): Likewise. + +2003-01-07 Jakub Jelinek <jakub@redhat.com> + + * pthreadP.h (__pthread_cond_timedwait): Add prototype. + + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h + (RTLD_CORRECT_DYNAMIC_WEAK): Remove. + (DL_SYSINFO_IMPLEMENTATION): Change into .text section and back. + * sysdeps/unix/sysv/linux/i386/i686/dl-sysdep.h + (RTLD_CORRECT_DYNAMIC_WEAK): Remove. + (DL_SYSINFO_IMPLEMENTATION): Change into .text section and back. + +2003-01-06 Jakub Jelinek <jakub@redhat.com> + + * pthreadP.h (LIBC_CANCEL_HANDLED): Define. + * pt-system.c (LIBC_CANCEL_HANDLED): Add. + * tst-cancel-wrappers.sh: Remove all exceptions. + +2003-01-05 Ulrich Drepper <drepper@redhat.com> + + * tst-cancel-wrappers.sh: Invoke gawk not awk since we use GNU awk + features. Reported by Marijn Ros <marijn@mad.scientist.com>. + + * sysdeps/unix/sysv/linux/jmp-unwind.c: Include <pthread-functions.h>. + Use __libc_pthread_functions array if SHARED. + + * pthreadP.h: Move pthread_cond_2_0_t definition to... + * sysdeps/unix/sysv/linux/internaltypes.h: ...here. + + * sysdeps/pthread/bits/libc-lock.h (__libc_ptf_call): New #define. + (__libc_rwlock_rdlock, __libc_rwlock_wrlock, __libc_rwlock_unlock, + __libc_key_create, __libc_getspecific, __libc_setspecific): Use + __libc_ptf_call instead of __libc_maybe_call. + (PTF): New #define. + (__libc_cleanup_region_start): Wrap function name with PTF call. + (__libc_cleanup_region_end): Likewise. + (__libc_cleanup_end): Likewise. + + * pthread_getspecific.c: Add __pthread_getspecific_internal alias. + * pthread_setspecific.c: Add __pthread_setspecific_internal alias. + * pthread_key_create.c: Add __pthread_key_create_internal alias. + * pthreadP.h: Add prototypes. + + * sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S: Add + __pthread_rwlock_rdlock, __pthread_rwlock_wrlock, and + __pthread_rwlock_unlock aliases. + * pthreadP.h: Add prototypes for new aliases. + + * pthreadP.h (struct pthead_functions): Moved to... + * sysdeps/pthread/pthread-functions.h: ...here. New file. + * init.c (pthread_functions): Add initializers for new elements. + + * cleanup_defer.c: Add __pthread_cleanup_push_defer and + __pthread_cleanup_pop_restore aliases. + * pthreadP.h: Add prototypes. + + * cleanup.c: Rename _GI_pthread_cleanup_push to __pthread_cleanup_push + and _GI_pthread_cleanup_pop to __pthread_cleanup_pop. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S: Adjust caller. + * sysdeps/unix/sysv/linux/i386/pthread_once.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Likewise. + * pthreadP.h: Adjust prototypes and callers. + +2003-01-04 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-cancel7. + (tst-cancel7-ARGS): New variable. + * tst-cancel7.c: New file. + + * old_pthread_cond_broadcast.c: Optimize initialization a bit to work + around gcc defficiencies. + * old_pthread_cond_signal.c: Likewise. + * old_pthread_cond_timedwait.c: Likewise. + * old_pthread_cond_wait.c: Likewise. + + * pthreadP.h (pthread_cond_2_0_t): Remove unneeded lock element. + +2003-01-03 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-cond7. + * tst-cond7.c: New file. + + * sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S + (condvar_cleanup): Get condvar address from the right place. + + * atomic.h: Correct definitions of atomic_full_barrier, + atomic_read_barrier, atomic_write_barrier. + + * old_pthread_cond_broadcast.c: Make memory allocate and initialization + race-free. + * old_pthread_cond_signal.c: Likewise. + * old_pthread_cond_timedwait.c: Likewise. + * old_pthread_cond_wait.c: Likewise. + +2003-01-03 Jakub Jelinek <jakub@redhat.com> + + * Makefile ($(objpfx)libpthread.so): Depend on ld.so. + +2003-01-03 Ulrich Drepper <drepper@redhat.com> + + * pthreadP.h (pthread_cond_2_0_t): New type. + (struct pthread_functions): Use new type for 2.0 condvar callbacks. + Use new type for the 2.0 condvar function prototypes. + * forward.c: Use pthread_cond_2_0_t for 2.0 condvar functions. + * old_pthread_cond_init.c: Use pthread_cond_2_0_t for condvar + parameter. + * old_pthread_cond_destroy.c: Likewise. + * old_pthread_cond_broadcast.c: Likewise. Lock appropriately. + * old_pthread_cond_signal.c: Likewise. + * old_pthread_cond_timedwait.c: Likewise. + * old_pthread_cond_wait.c: Likewise. + + * sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S + (__pthread_cond_wait): Don't save cancellation mode and seq value + in same location. + + * herrno.c (__h_errno_location): Don't define as weak. + +2003-01-02 Jakub Jelinek <jakub@redhat.com> + + * Versions [libc] (GLIBC_2.3.2): Export pthread_cond_broadcast, + pthread_cond_destroy, pthread_cond_init, pthread_cond_signal + and pthread_cond_wait. + * old_pthread_cond_broadcast.c (__old_pthread_cond_broadcast): + Renamed to... + (__pthread_cond_broadcast_2_0): ... this. + * old_pthread_cond_destroy.c (__old_pthread_cond_destroy): + Renamed to... + (__pthread_cond_destroy_2_0): ... this. + * old_pthread_cond_init.c (__old_pthread_cond_init): + Renamed to... + (__pthread_cond_init_2_0): ... this. + * old_pthread_cond_signal.c (__old_pthread_cond_signal): + Renamed to... + (__pthread_cond_signal_2_0): ... this. + * old_pthread_cond_wait.c (__old_pthread_cond_wait): + Renamed to... + (__pthread_cond_wait_2_0): ... this. + * pthread_cond_destroy.c: Include shlib-compat.h. + (pthread_cond_destroy): Change strong_alias into versioned_symbol. + * pthread_cond_init.c: Include shlib-compat.h. + (pthread_cond_init): Change strong_alias into versioned_symbol. + * pthreadP.h (struct pthread_functions): Rename ptr_pthread_cond_* + fields to ptr___pthread_cond_* and add ptr___pthread_cond_*_2_0 + fields. + (__pthread_cond_broadcast_2_0, __pthread_cond_destroy_2_0, + __pthread_cond_init_2_0, __pthread_cond_signal_2_0, + __pthread_cond_wait_2_0): New prototypes. + (__old_pthread_cond_broadcast, __old_pthread_cond_destroy, + __old_pthread_cond_init, __old_pthread_cond_signal, + __old_pthread_cond_wait): Removed. + * init.c: Include shlib-compat.h. + (pthread_functions): Guard ptr___pthread_attr_init_2_0 + initialization with SHLIB_COMPAT (GLIBC_2_0, GLIBC_2_1). + Rename ptr_pthread_cond_* to ptr___pthread_cond_*, initialize + ptr___pthread_cond_*_2_0 fields. + * forward.c: Export both pthread_cond_*@@GLIBC_2.3.2 and + pthread_cond_*@GLIBC_2.0 compatibility symbols. + + * sysdeps/pthread/sigaction.c (SIGCANCEL): Only define if + LIBC_SIGACTION was not yet defined. + [!defined LIBC_SIGACTION]: Define LIBC_SIGACTION, #include self. + [!defined LIBC_SIGACTION] (__sigaction): New function and + libc_hidden_weak. + [!defined LIBC_SIGACTION] (sigaction): New weak_alias. + [defined LIBC_SIGACTION]: #include_next <sigaction.c>. + +2003-01-02 Jakub Jelinek <jakub@redhat.com> + + * Makefile (CFLAGS-pthread_atfork.c): Add -DNOT_IN_libc. + +2003-01-02 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_cond_t): + New, larger type definition. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S: New condvar + implementation. + * Versions [libpthread]: Add definitions for new pthread_cond_* + interfaces for version GLIBC_2.3.2. + * pthread_cond_init.c: Update initialization for new type definition. + * Makefile (libpthread-routines): Remove pthread_cond_wait, + pthread_cond_timedwait, pthread_cond_signal, and + pthread_cond_broadcast. Add old_pthread_cond_init, + old_pthread_cond_destroy, old_pthread_cond_wait, + old_pthread_cond_timedwait, old_pthread_cond_signal, and + old_pthread_cond_broadcast. + * old_pthread_cond_broadcast.c: New file. + * old_pthread_cond_destroy.c: New file. + * old_pthread_cond_init.c: New file. + * old_pthread_cond_signal.c: New file. + * old_pthread_cond_timedwait.c: New file. + * old_pthread_cond_wait.c: New file. + * pthreadP.h: Add prototypes for the compatibility interfaces. + + * pthread_cond_destroy.c: Don't include <errno.h>. + +2003-01-01 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S: Avoid + unnecessary zero offset when addressing MUTEX. + +2002-12-31 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/fork.h: Add libc_hidden_proto for + __register_atfork. + * sysdeps/unix/sysv/linux/register-atfork.c: Add libc_hidden_def + for __register_atfork. + +2002-12-31 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Use __ASSEMBLER__ + instead of ASSEMBLER test macro. + + * sysdeps/unix/sysv/linux/allocrtsig.c (__libc_current_sigrtmin, + __libc_current_sigrtmax): Add libc_hidden_def. + + * sysdeps/pthread/list.h: Remove assert.h include. + +2002-12-31 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pt-initfini.c (call_initialize_minimal): Use + __pthread_initialize_minimal_internal not + __pthread_initialize_minimal. + +2002-12-30 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pt-initfini.c (call_initialize_minimal): Mark + __pthread_initialize_minimal as hidden. + + * init.c (__pthread_initialize_minimal_internal): Don't mark as + constructor. + +2002-12-31 Jakub Jelinek <jakub@redhat.com> + + * Makefile ($(inst_libdir)/libpthread.so): Depend on + $(common-objpfx)format.lds, include that into the output script. + Fix comment. + (extra-B-pthread.so): Change linuxthreads/ into nptl/. + +2002-12-28 Andreas Jaeger <aj@suse.de> + + * sysdeps/unix/sysv/linux/xstatconv.c (xstat_conv): Adjust for + nsec resolution changes. + (xstat64_conv): Likewise. + (xstat32_conv): Likewise. + * sysdeps/unix/sysv/linux/kernel_stat.h: Add nsec resolution for + struct kernel_stat. + * sysdeps/unix/sysv/linux/bits/stat.h: Add nsec resolution for + structs stat and stat64. + * time/time.h (__timespec_defined): Define for __USE_MISC. + * io/sys/stat.h [__USE_MISC]: Define __need_timespec for struct stat. + +2002-12-30 Jakub Jelinek <jakub@redhat.com> + + * forward.c (FORWARD2): Renamed from FORWARD3. Remove unused export + argument. + (pthread_attr_init_2_0, pthread_attr_init_2_1): Use FORWARD macro. + (pthread_exit): Use strong_alias to avoid warnings. + * pthreadP.h (struct pthread_functions): Rename ptr_pthread_exit + and ptr_pthread_attr_init_2_* to ptr___pthread_exit and + ptr___pthread_attr_init_2_*. + * init.c (pthread_functions): Adjust. + +2002-12-29 Ulrich Drepper <drepper@redhat.com> + + * forward.c: Make all functions available by default again. It + caused too much trouble. + + * pt-siglongjmp.c: Removed. + +2002-12-28 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/i386/tls.h: Include tcb-offsets.h in assembler. + (SYSINFO_OFFSET, MULTIPLE_THREADS_OFFSET): Remove. + * sysdeps/i386/Makefile: New file. + * sysdeps/i386/tcb-offsets.sym: New file. + * sysdeps/pthread/tcb-offsets.h: New file. + * sysdeps/unix/sysv/linux/libc_pthread_init.c (__libc_pthread_init): + Remove MULTIPLE_THREADS_OFFSET and SYSINFO_OFFSET checks. + + * sysdeps/unix/sysv/linux/Versions [libc] (GLIBC_PRIVATE): Move + __register_atfork... + (GLIBC_2.3.2): ...here. + +2002-12-28 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread.h: Mark pthread_attr_getstackaddr and + pthread_attr_setstackaddr with __attribute_deprecated__. + +2002-12-27 Jakub Jelinek <jakub@redhat.com> + + * pt-system.c (system): Remove cancellation handling. + * tst-cancel-wrappers.sh: Allow pt-system.o* to not use the + cancellation routines. + +2002-12-28 Ulrich Drepper <drepper@redhat.com> + + * descr.h: Include <dl-sysdep.h>. + (struct pthread): Move header.data.list to the back of the struct. + * sysdeps/i386/tls.h (tcbhead_t): Move list to the back of the struct. + (MULTIPLE_THREADS_OFFSET): Adjust offset. + (SYSINFO_OFFSEET): Likewise. + +2002-12-27 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i686/dl-sysdep.h (USE_DL_SYSINFO): + Define. + (DL_SYSINFO_DEFAULT): Cast to uintptr_t to avoid warnings. + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h (NEED_DL_SYSINFO, + DL_SYSINFO_DEFAULT, DL_SYSINFO_IMPLEMENTATION): Define. + (USE_DL_SYSINFO): Undef. + +2002-12-22 Jakub Jelinek <jakub@redhat.com> + + * Makefile (tests-reverse): Use $(objpfx)../libc.so instead of + $(common-objpfx)libc.so. + * tst-cancel4.c (tf_write, tf_writev): Increase buf sizes so that + it is bigger than pipe buffer size even on arches with bigger + page size. + (tf_usleep): Cast usleep argument to useconds_t to avoid warnings. + +2002-12-25 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S: Implement + correct errno access for case that USE___THREAD is not defined. + +2002-12-24 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h: Add missing #endif. + Patch by Marijn Ros <marijn@mad.scientist.com>. + +2002-12-22 Roland McGrath <roland@redhat.com> + + * Makefile (omit-deps): Add $(unix-syscalls:%=ptw-%). + +2002-12-20 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/bits/stdio-lock.h (_IO_lock_inexpensive): Define. + +2002-12-19 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h: Don't define + NEED_DL_SYSINFO since no processor < i686 had the sysenter opcode. + * sysdeps/unix/sysv/linux/i386/i686/dl-sysdep.h: New file. + + * sysdeps/unix/sysv/linux/i386/pthread_once.S: Use ENTER_KERNEL instead + of int $0x80. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevelmutex.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: Likewise. + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Add support for using + sysenter. + * sysdeps/unix/sysv/linux/i386/lowlevelsem.h: Likewise. + + * sysdeps/i386/tls.h: Unconditionally include <dl-sysdep.h>. + + * allocatestack.c (allocate_stack) [NEED_DL_SYSINFO]: Set sysinfo + in new TCB. + * sysdeps/unix/sysv/linux/i386/createthread.c (create_thread): Check + that sysinfo is properly initialized. + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h: Define RTLD_PRIVATE_ERRNO + to 1 only for ld.so. + + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h: Define + RTLD_CORRECT_DYNAMIC_WEAK. + +2002-12-19 Jakub Jelinek <jakub@redhat.com> + + * forward.c (pthread_attr_init_2_0, pthread_attr_init_2_1): + Use return 0 as 6th argument to FORWARD4. + * pthread_equal.c: Include pthreadP.h instead of pthread.h. + +2002-12-18 Ulrich Drepper <drepper@redhat.com> + + * descr.h (struct pthread) [NEED_DL_SYSINFO]: Add sysinfo member. + * sysdeps/i386/tls.h (tcbhead_t): Add sysinfo member. + Define SYSINFO_OFFSEET if NEED_DL_SYSINFO is defined. + (INIT_SYSINFO): New #define. + (TLS_TP_INIT): Use INIT_SYSINFO. + * sysdeps/unix/sysv/linux/libc_pthread_init.c (__libc_pthread_init): + At test to make sure SYSINFO_OFFSET value is correct. + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h: New file. + +2002-12-18 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/flockfile.c (flockfile): Change into weak alias. + * sysdeps/unix/sysv/linux/raise.c (gsignal): Add weak alias to raise. + * Versions [libc: GLIBC_2.0]: Add pthread_attr_init. + [libpthread: GLIBC_2.1]: Remove __pthread_rwlock_init, + __pthread_rwlock_destroy, __pthread_rwlock_rdlock, + __pthread_rwlock_wrlock, __pthread_rwlock_unlock, + __pthread_rwlock_tryrdlock and __pthread_rwlock_trywrlock. + +2002-12-18 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Use ENTER_KERNEL + macro instead of using int $0x80 directly. + + * sysdeps/pthread/bits/stdio-lock.h: New file. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevelmutex.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/libc-lowlevelmutex.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/libc-lowlevelmutex.S: New file. + * Makefile (routines): Add libc-lowlevelmutex. + + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Remove + __i686.get_pc_thunk.dx. + +2002-12-17 Jakub Jelinek <jakub@redhat.com> + + * Makefile (libpthread-shared-only-routines): Add pt-allocrtsig. + (tests): Depend on $(objpfx)tst-cancel-wrappers.out. + ($(objpfx)tst-cancel-wrappers.out): New rule. + * tst-cancel-wrappers.sh: New test. + * tst-locale1.c: Include signal.h. + (uselocale): Test static linking of __libc_current_sigrt*. + +2002-12-17 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-cancel6. + * tst-cancel6.c: New file + +2002-12-17 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (SINGLE_THREAD_P): + Define meaningfully for assembler as well. + * pthreadP.h (struct pthread_functions): Remove + ptr_pthread_attr_init field. Add ptr_pthread_attr_init_2_0 + and ptr_pthread_attr_init_2_1 fields. + * init.c (pthread_functions): Initialize ptr_pthread_attr_init_2_0 + and ptr_pthread_attr_init_2_1 instead of ptr_pthread_attr_init. + * forward.c (FORWARD4): Renamed from FORWARD3. Add export argument. + (FORWARD3): Define using FORWARD4. + (pthread_attr_init): Provide both @GLIBC_2.0 and @@GLIBC_2.1 + versions. + * pt-system.c: Remove duplicate stdlib.h include. + +2002-12-16 Ulrich Drepper <drepper@redhat.com> + + * sem_init.c: Define sem_init@GLIBC_2.0. + * sem_destroy.c: Define sem_destroy@GLIBC_2.0. + * sem_getvalue.c: Define sem_getvalue@GLIBC_2.0. + + * flockfile.c: Moved to... + * sysdeps/pthread/flockfile.c: ...here. New file. + * funlockfile.c: Moved to... + * sysdeps/pthread/funlockfile.c: ...here. New file. + * ftrylockfile.c: Moved to... + * sysdeps/pthread/ftrylockfile.c: ...here. New file. + +2002-12-16 Jakub Jelinek <jakub@redhat.com> + + * libc-cancellation.c: Guard both function with + #if !defined NOT_IN_libc. + * Makefile (libpthread-routines): Use ptw-, not pt- prefix for the + automatically provided pthread wrappers. + * pthreadP.h (LIBC_CANCEL_ASYNC, LIBC_CANCEL_RESET): Define to + CANCEL_* if IS_IN_libpthread and to dummy versions if not in libc + nor in libpthread. + * pt-open.c: Removed. + * pt-fcntl.c: Removed. + * pt-fsync.c: Removed. + * pt-lseek.c: Removed. + * pt-msgrcv.c: Removed. + * pt-msgsnd.c: Removed. + * pt-msync.c: Removed. + * pt-nanosleep.c: Removed. + * pt-open64.c: Removed. + * pt-pause.c: Removed. + * pt-pread.c: Removed. + * pt-pread64.c: Removed. + * pt-pwrite.c: Removed. + * pt-pwrite64.c: Removed. + * pt-read.c: Removed. + * pt-recv.c: Removed. + * pt-recvfrom.c: Removed. + * pt-recvmsg.c: Removed. + * pt-send.c: Removed. + * pt-sendto.c: Removed. + * pt-sigtimedwait.c: Removed. + * pt-sigwait.c: Removed. + * pt-wait.c: Removed. + * pt-waitpid.c: Removed. + * pt-write.c: Removed. + * pt-accept.c: Removed. + * pt-close.c: Removed. + * pt-connect.c: Removed. + * pt-lseek64.c: Removed. + * pt-sendmsg.c: Removed. + * pt-tcdrain.c: Removed. + +2002-12-15 Ulrich Drepper <drepper@redhat.com> + + * init.c (__pthread_initialize_minimal_internal): Renamed from + __pthread_initialize_minimal. Make old name an alias. This + converts a normal relocation into a relative relocation. + + * pt-fcntl.c (__fcntl): Use fcntl64 syscall, not fcntl. + + * Versions [libpthread: GLIBC_2.3.2]: Remove creat, poll, pselect, + readv, select, sigpause, sigsuspend, sigwaitinfo, waitid, writev. + * Makefile (libpthread-routines): Remove pt-creat, pt-poll, + pt-pselect, pt-readv, pt-select, pt-sigpause, pt-sigsuspend, + pt-sigwaitinfo, pt-waitid, and pt-writev. + * pt-creat.c: Removed. + * pt-poll.c: Removed. + * pt-pselect.c: Removed. + * pt-readv.c: Removed. + * pt-select.c: Removed. + * pt-sigpause.c: Removed. + * pt-sigsuspend.c: Removed. + * pt-sigwaitinfo.c: Removed. + * pt-waitid.c: Removed. + * pt-writev.c: Removed. + + * init.c (pthread_functions): New variable. + (__pthread_initialize_minimal): Pass pointer to pthread_functions + (or NULL) to __libc_pthread_init. + * forward.c: Rewrite to use __libc:pthread_functions array to get + function addresses. + * sysdeps/unix/sysv/linux/fork.h: Remove __libc_pthread_init + prototype. + * sysdeps/unix/sysv/linux/libc_pthread_init.c (__libc_pthread_init): + Take new parameter. Copy content of variable pointed to by it + to __libc_pthread_init. + + * pthreadP.h (struct pthread_functions): New type. + (__libc_pthread_init): Declare. + + * pthread_attr_destroy.c: Add namespace protected alias. + * pthread_attr_getdetachstate.c: Likewise. + * pthread_attr_getinheritsched.c: Likewise. + * pthread_attr_getschedparam.c: Likewise. + * pthread_attr_getschedpolicy.c: Likewise. + * pthread_attr_getscope.c: Likewise. + * pthread_attr_setdetachstate.c: Likewise. + * pthread_attr_setinheritsched.c: Likewise. + * pthread_attr_setschedparam.c: Likewise. + * pthread_attr_setschedpolicy.c: Likewise. + * pthread_attr_setscope.c: Likewise. + * pthread_cond_broadcast.c: Likewise. + * pthread_cond_destroy.c: Likewise. + * pthread_cond_init.c: Likewise. + * pthread_cond_signal.c: Likewise. + * pthread_cond_wait.c: Likewise. + * pthread_condattr_destroy.c: Likewise. + * pthread_condattr_init.c: Likewise. + * pthread_equal.c: Likewise. + * pthread_exit.c: Likewise. + * pthread_getschedparam.c: Likewise. + * pthread_self.c: Likewise. + * pthread_setcancelstate.c: Likewise. + * pthread_setschedparam.c: Likewise. + * pthread_mutex_destroy.c: Likewise. + * pthread_mutex_init.c: Likewise. + * pthreadP.h: Add prototypes for the aliases. + + * sysdeps/unix/sysv/linux/i386/createthread.c (create_thread): Set + multiple_threads member in correct TCB to 1. + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Define + SINGLE_THREAD_P. If in libc or libpthread examine multiple_thread + member of thread decriptor, otherwise return unconditionally 1. + +2002-12-14 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/pt-socket.S: Changes folded into the + regular Linux version. Remove file. + * sysdeps/unix/sysv/linux/connect.S: Likewise. Remove file. + * sysdeps/unix/sysv/linux/llseek.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/msgrcv.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/msgsnd.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/open64.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/poll.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/pread.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/pread64.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/pselect.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/pwrite.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/pwrite64.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/readv.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/recv.S: Likewise. Remove file. + * sysdeps/unix/sysv/linux/recvfrom.S: Likewise. Remove file. + * sysdeps/unix/sysv/linux/recvmsg.S: Likewise. Remove file. + * sysdeps/unix/sysv/linux/send.S: Likewise. Remove file. + * sysdeps/unix/sysv/linux/sendmsg.S: Likewise. Remove file. + * sysdeps/unix/sysv/linux/sendto.S: Likewise. Remove file. + * sysdeps/unix/sysv/linux/sigpause.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/sigsuspend.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/sigtimedwait.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/sigwait.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/sigwaitinfo.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/system.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/tcdrain.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/wait.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/waitid.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/waitpid.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/writev.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/i386/fcntl.c: Likewise. Remove file. + +2002-12-14 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: New file. + * sysdeps/unix/sysv/linux/open.c: Removed. + * sysdeps/unix/sysv/linux/fsync.c: Removed. + * sysdeps/unix/sysv/linux/lseek.c: Removed. + * sysdeps/unix/sysv/linux/msync.c: Removed. + * sysdeps/unix/sysv/linux/read.c: Removed. + * sysdeps/unix/sysv/linux/close.c: Removed. + * sysdeps/unix/sysv/linux/creat.c: Removed. + * sysdeps/unix/sysv/linux/nanosleep.c: Removed. + * sysdeps/unix/sysv/linux/pause.c: Removed. + * sysdeps/unix/sysv/linux/select.c: Removed. + * sysdeps/unix/sysv/linux/write.c: Removed. + +2002-12-14 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/pt-socket.S: Check multiple_threads + element in TCB to see whether locking is needed. + + * sysdeps/unix/sysv/linux/libc_pthread_init.c: Check that + MULTIPLE_THREADS_OFFSET value is correct. + + * sysdeps/unix/sysv/linux/close.c: New file. + * sysdeps/unix/sysv/linux/connect.S: New file. + * sysdeps/unix/sysv/linux/creat.c: New file. + * sysdeps/unix/sysv/linux/fsync.c: New file. + * sysdeps/unix/sysv/linux/llseek.c: New file. + * sysdeps/unix/sysv/linux/lseek.c: New file. + * sysdeps/unix/sysv/linux/msgrcv.c: New file. + * sysdeps/unix/sysv/linux/msgsnd.c: New file. + * sysdeps/unix/sysv/linux/msync.c: New file. + * sysdeps/unix/sysv/linux/nanosleep.c: New file. + * sysdeps/unix/sysv/linux/open.c: New file. + * sysdeps/unix/sysv/linux/open64.c: New file. + * sysdeps/unix/sysv/linux/pause.c: New file. + * sysdeps/unix/sysv/linux/poll.c: New file. + * sysdeps/unix/sysv/linux/pread.c: New file. + * sysdeps/unix/sysv/linux/pread64.c: New file. + * sysdeps/unix/sysv/linux/pselect.c: New file. + * sysdeps/unix/sysv/linux/pwrite.c: New file. + * sysdeps/unix/sysv/linux/pwrite64.c: New file. + * sysdeps/unix/sysv/linux/readv.c: New file. + * sysdeps/unix/sysv/linux/recv.S: New file. + * sysdeps/unix/sysv/linux/recvfrom.S: New file. + * sysdeps/unix/sysv/linux/recvmsg.S: New file. + * sysdeps/unix/sysv/linux/select.c: New file. + * sysdeps/unix/sysv/linux/send.S: New file. + * sysdeps/unix/sysv/linux/sendmsg.S: New file. + * sysdeps/unix/sysv/linux/sendto.S: New file. + * sysdeps/unix/sysv/linux/sigpause.c: New file. + * sysdeps/unix/sysv/linux/sigsuspend.c: New file. + * sysdeps/unix/sysv/linux/sigtimedwait.c: New file. + * sysdeps/unix/sysv/linux/sigwait.c: New file. + * sysdeps/unix/sysv/linux/sigwaitinfo.c: New file. + * sysdeps/unix/sysv/linux/system.c: New file. + * sysdeps/unix/sysv/linux/tcdrain.c: New file. + * sysdeps/unix/sysv/linux/wait.c: New file. + * sysdeps/unix/sysv/linux/waitid.c: New file. + * sysdeps/unix/sysv/linux/waitpid.c: New file. + * sysdeps/unix/sysv/linux/writev.c: New file. + * sysdeps/unix/sysv/linux/i386/fcntl.c: New file. + + * pt-readv.c: Fix comment. + +2002-12-14 Jakub Jelinek <jakub@redhat.com> + + * tst-cleanup1.c: Include stdlib.h. + + * tst-cancel5.c: New test. + * Makefile (tests): Add tst-cancel5. + (tst-cancel5): Link against libc.so libpthread.so in that order. + +2002-12-13 Ulrich Drepper <drepper@redhat.com> + + * forward.c (test_loaded): Prevent recursive calls. + + * Makefile (routines): Add libc-cancellation. + * libc-cancellation.c: New file. + * descr.h (struct pthread): Add multiple_threads field. + * allocatestack.c (allocate_stack): Initialize multiple_header field of + new thread descriptor to 1. + * sysdeps/unix/sysv/linux/i386/createthread.c (create_thread): + Initialize multiple_thread field after successful thread creation. + * cancellation.c (__do_cancel): Move to pthreadP.h. + (__pthread_enable_asynccancel): Remove parameter from __do_cancel call. + (__pthread_disable_asynccancel): Add internal_function attribute. + * init.c (sigcancel_handler): Remove parameter from __do_cancel call. + * pthread_setcancelstate.c: Likewise. + * pthread_setcanceltype.c: Likewise. + * pthread_exit.c: Likewise. + * pthreadP.h (CANCELLATION_P): Likewise. + (__do_cancel): Define as static inline. + (LIBC_CANCEL_ASYNC, LIBC_CANCEL_RESET): New #defines. + (__libc_enable_asynccancel, __libc_disable_asynccancel): New + declarations. + * sysdeps/i386/tls.h (tcbhead_t): Add list and multiple_threads + fields. Define MULTIPLE_THREADS_OFFSET. + * sysdeps/pthread/bits/libc-lock.h: Remove __libc_locking_needed + declaration. + * sysdeps/unix/sysv/linux/accept.S: New file. + * sysdeps/unix/sysv/linux/read.c: New file. + * sysdeps/unix/sysv/linux/write.c: New file. + * sysdeps/unix/sysv/linux/i386/pt-socket.S: New file. + * sysdeps/unix/sysv/linux/libc_pthread_init.c: Remove definition and + initialization of __libc_locking_needed. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Don't use + __libc_locking_needed, use multiple_threads field in TCB. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Likewise. + +2002-12-12 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i686/libc-lowlevellock.S: Use i486 + version. + * sysdeps/unix/sysv/linux/i386/i586/libc-lowlevellock.S: Likewise. + + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Correct + access to __libc_locking_needed for PIC. + +2002-12-12 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/pthread/bits/libc-lock.h (__libc_locking_needed): Only + declare for libc.so. + (__libc_lock_init, __libc_lock_init_recursive): Change into comma + expression. + (__libc_lock_lock): Put into statement expression. + (__libc_lock_unlock): Remove trailing semicolon. + * sysdeps/unix/sysv/linux/fork.h (__libc_pthread_init): Fix typo. + +2002-12-12 Roland McGrath <roland@redhat.com> + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Use asm operand with + "m" constraint to refer to __libc_locking_needed. Declare it here. + +2002-12-12 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/fork-gen.c: Renamed to... + * sysdeps/unix/sysv/linux/libc_pthread_init.c: ...this. + Initialize __libc_locking_needed. + * init.c (__pthread_initialize_minimal): Call __libc_pthread_init + instead of __register_pthread_fork_handler. + * sysdeps/pthread/bits/libc-lock.h: Declare __libc_locking_needed. + * sysdeps/unix/sysv/linux/Makefile (sysdep_routimes): Replace + fork-gen with libc_pthread_init. + * sysdeps/unix/sysv/linux/Versions: Use __libc_pthread_init instead + of __register_pthread_fork_handler. + * sysdeps/unix/sysv/linux/fork.h: Declare __libc_pthread_init instead + of __register_pthread_fork_handler. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Use + __libc_locking_needed to determine whether lock prefix can be avoided. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Likewise. + +2002-12-11 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-cleanup1. + * tst-cleanup1.c: New file. + * cancellation.c (__cleanup_thread): Removed. + (__do_cancel): Remove call to __cleanup_thread. + * pthreadP.h: Remove __cleanup_thread prorotype. + + * sysdeps/pthread/bits/libc-lock.h (__libc_cleanup_region_start): + Remember function and argument even if cancellation handler + function is not available. + (__libc_cleanup_region_end): Execute registered function directly if + pthread functions are not available. + (__libc_cleanup_end): Likewise. + + * init.c (__pthread_initialize_minimal): Fix initialization in + static lib by preventing gcc from being too clever. + +2002-12-10 Ulrich Drepper <drepper@redhat.com> + + * init.c (__pthread_initialize_minimal): Remove unneccesary + sigaddset call. + + * Makefile (tests): We can run tst-locale2 now. + +2002-12-09 Ulrich Drepper <drepper@redhat.com> + + * Versions: Remove duplicated sigwait entry. + +2002-12-08 Ulrich Drepper <drepper@redhat.com> + + * pthreadP.h: Enable pthread_cleanup_{push,pop} optimizations only + inside libpthread. + + * pt-fcntl.c (__fcntl): Initialize oldtype to avoid warning. + + * pthreadP.h: Declare __pthread_enable_asynccancel and + __pthread_disable_asynccancel. + (CANCEL_ASYNC): Use __pthread_enable_asynccancel. + (CANCEL_RESET): Use __pthread_disable_asynccancel. + * cancellation.c (__pthread_enable_asynccancel): New function. + (__pthread_disable_asynccancel): New function. + * pt-accept.c: Adjust for CANCEL_ASYNC and CANCEL_RESET change. + * pt-close.c: Likewise. + * pt-connect.c: Likewise. + * pt-creat.c: Likewise. + * pt-fcntl.c: Likewise. + * pt-fsync.c: Likewise. + * pt-lseek.c: Likewise. + * pt-lseek64.c: Likewise. + * pt-msgrcv.c: Likewise. + * pt-msgsnd.c: Likewise. + * pt-msync.c: Likewise. + * pt-nanosleep.c: Likewise. + * pt-open.c: Likewise. + * pt-open64.c: Likewise. + * pt-pause.c: Likewise. + * pt-poll.c: Likewise. + * pt-pread.c: Likewise. + * pt-pread64.c: Likewise. + * pt-pselect.c: Likewise. + * pt-pwrite.c: Likewise. + * pt-pwrite64.c: Likewise. + * pt-read.c: Likewise. + * pt-readv.c: Likewise. + * pt-recv.c: Likewise. + * pt-recvfrom.c: Likewise. + * pt-recvmsg.c: Likewise. + * pt-select.c: Likewise. + * pt-send.c: Likewise. + * pt-sendmsg.c: Likewise. + * pt-sendto.c: Likewise. + * pt-sigpause.c: Likewise. + * pt-sigsuspend.c: Likewise. + * pt-sigtimedwait.c: Likewise. + * pt-sigwait.c: Likewise. + * pt-sigwaitinfo.c: Likewise. + * pt-system.c: Likewise. + * pt-tcdrain.c: Likewise. + * pt-wait.c: Likewise. + * pt-waitid.c: Likewise. + * pt-waitpid.c: Likewise. + * pt-write.c: Likewise. + * pt-writev.c: Likewise. + * pthread_join.c: Likewise. + * pthread_timedjoin.c: Likewise. + + * pt-sigpause.c (sigsuspend): Call __sigsuspend. + (__xpg_sigpause): New function. + * Versions (libpthread:GLIBC_2.3.2): Add __xpg_sigpause. + +2002-12-07 Ulrich Drepper <drepper@redhat.com> + + * Makefile (CFLAGS-ftrylockfile.c): Add -D_IO_MTSAFE_IO. + + * cleanup.c: Move declarations of _GI_pthread_cleanup_push and + _GI_pthread_cleanup_pop to pthreadP.h. + + * ftrylockfile.c: Use _IO_lock_trylock instead of + pthread_mutex_trylock. + + * pthreadP.h (CANCEL_ASYNC): Use __pthread_setcanceltype. + (CANCEL_RESET): Likewise. + (__pthread_setcanceltype_): Declare. + (__pthread_mutex_lock_internal): Declare. + (__pthread_mutex_unlock_internal): Declare. + (__pthread_once_internal): Declare. + (pthread_cleanup_push): Redefine using _GI_pthread_cleanup_push. + (pthread_cleanup_pop): Redefine using _GI_pthread_cleanup_pop. + + * pthread_cond_timedwait.c: Use INTUSE is calls to pthread_mutex_lock + and pthread_mutex_unlock. + * pthread_cond_wait.c: Likewise. + * pthread_mutex_lock.c: Use INTDEF to define alias if needed. + * pthread_mutex_unlock.c: Likewise. + + * pthread_setcanceltype.c: Add additional alias + __pthread_setcanceltype. + + * sem_unlink.c (sem_unlink): Use __pthread_once with INTDEF. + * sem_open.c (sem_open): Likewise. + Use __libc_open, __libc_write, and __libc_close instead of + open, write, and close respectively. + + * sysdeps/pthread/bits/libc-lock.h (__libc_lock_trylock_internal): + Rewrite as statement expression since it must return a value. + + * pthread_cancel.c: Use __pthread_kill instead of pthread_kill. + * sysdeps/unix/sysv/linux/pthread_kill.c: Define additional alias + __pthread_kill. + + * sysdeps/unix/sysv/linux/i386/pthread_once.S: Define additional + alias __pthread_once_internal. + + * sysdeps/unix/sysv/linux/raise.c: Use libc_hidden_def for raise. + +2002-12-06 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-stdio1 and tst-stdio2. + * tst-stdio1.c: New file. + * tst-stdio2.c: New file. + + * init.c (__pthread_initialize_minimal): Correct INIT_LIST_HEAD use. + + * Makefile (tests): Comment out tst-locale2 for now. + (CFLAGS-flockfile.c, CFLAGS-funlockfile.c): Define to -D_IO_MTSAFE_IO. + + * sysdeps/unix/sysv/linux/Makefile: Define CFLAGS-fork.c to + -D_IO_MTSAFE_IO. + * sysdeps/unix/sysv/linux/fork.c: Include <bits/stdio-lock.h>. + Use _IO_lock_init instead of explicit assignment. + + * sysdeps/pthread/bits/libc-lock.h: Define __rtld_lock_* macros. + Define __libc_lock_* and __libc_lock_recursive macros with + lowlevellock macros, not pthread mutexes. + + * flockfile.c: Include <bits/stdio-lock.h>. Use _IO_lock_lock instead + of pthread_mutex_lock. + * funlockfile.c: Include <bits/stdio-lock.h>. Use _IO_lock_unlock + instead of pthread_mutex_unlock. + +2002-12-06 Roland McGrath <roland@redhat.com> + + * allocatestack.c (__stack_user): Use uninitialized defn. + * init.c (__pthread_initialize_minimal): Initialize it here. + +2002-12-05 Roland McGrath <roland@redhat.com> + + * sysdeps/i386/tls.h (TLS_INIT_TP): Make it return zero or an error + string. + * sysdeps/x86_64/tls.h (TLS_INIT_TP): Likewise. + + * sysdeps/unix/sysv/linux/i386/createthread.c (create_thread): Add + missing & here too. + +2002-12-05 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/Makefile (sysdep_routines): Remove + lowlevellock. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/libc-lowlevellock.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/libc-lowlevellock.S: New file. + * sysdeps/pthread/bits/libc-lock.h: Use lowlevellock implementation + for __libc_lock_* macros. + * Makefile (routines): Add libc-lowlevellock. + +2002-10-09 Roland McGrath <roland@redhat.com> + + * sysdeps/pthread/bits/libc-lock.h (__libc_maybe_call): New macro. + Under [__PIC__], call the function via the pointer fetched for + comparison rather than a call by name that uses the PLT. + (__libc_lock_init, __libc_rwlock_init, __libc_lock_fini) + (__libc_rwlock_fini, __libc_lock_lock, __libc_rwlock_rdlock) + (__libc_rwlock_wrlock, __libc_lock_trylock, __libc_rwlock_tryrdlock) + (__libc_rwlock_trywrlock, __libc_lock_unlock, __libc_rwlock_unlock) + (__libc_key_create, __libc_getspecific, __libc_setspecific): Use it. + +2002-12-04 Roland McGrath <roland@redhat.com> + + * forward.c (pthread_self): Use FORWARD3 macro to correct return type. + + * sysdeps/i386/td_ta_map_lwp2thr.c: Moved from ../nptl_db. + * sysdeps/generic/td_ta_map_lwp2thr.c: New file. + + * pthread_create.c (start_thread): Add missing & on __nptl_last_event. + +2002-12-04 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Make pthread_t + a completely opaque, non-integer type. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + +2002-12-05 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/i386/tls.h: Include stdlib.h. + * sysdeps/x86_64/tls.h: Likewise. + +2002-12-04 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-locale2. + (tests-static): Likewise. + * tst-locale2.c: New file. + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Mark asms as + volatile and add memory clobbers to lock operations. + +2002-12-03 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/i386/i686/bits/atomic.h: Use i486 version. + * sysdeps/i386/i486/bits/atomic.h: New file. + * sysdeps/i386/i586/bits/atomic.h: New file. + * sysdeps/i386/i686/pthread_spin_trylock.S: Define HAVE_CMOV and + include i486 version. + * sysdeps/i386/i486/pthread_spin_trylock.S: New file. + * sysdeps/i386/i586/pthread_spin_trylock.S: New file. + Patch by Marijn Ros <marijn@mad.scientist.com>. + + * allocatestack.c (get_cached_stack): Don't crash if we first + found a stack with a larger size then needed. + Reported by Hui Huang <hui.huang@sun.com>. + + * Makefile (tests): Add tst-sysconf. + * tst-sysconf.c: New file. + + * sysdeps/unix/sysv/linux/bits/local_lim.h: Undefine + PTHREAD_THREADS_MAX. + +2002-12-02 Roland McGrath <roland@redhat.com> + + * pthreadP.h (__stack_user, __nptl_create_event, __nptl_death_event): + Declare using hidden_proto instead of attribute_hidden, so there are + non-.hidden static symbols for gdb to find. + (__pthread_keys): Likewise. + * events.c (__nptl_create_event, __nptl_death_event): Add hidden_def. + * allocatestack.c (__stack_user): Likewise. + * pthread_create.c (__pthread_keys): Likewise. + (__nptl_threads_events, __nptl_last_event): Make these static instead + of hidden. + * pthread_key_create.c (__pthread_pthread_keys_max, + __pthread_pthread_key_2ndlevel_size): Renamed from __linuxthreads_*. + +2002-12-02 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-locale1. If buid-static is yes link + statically. + * tst-locale1.c: New file. + + * pthread_cond_timedwait.c: Include <stdlib.h>. + + * Makefile (tests): Add tst-fork2 and tst-fork3. + * tst-fork2.c: New file. + * tst-fork3.c: New file. + +2002-11-28 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: New file. + + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Define macros which + require it to 200112L. + + * sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S: Use cmov + instruction only if HAVE_CMOV is defined. + * sysdeps/unix/sysv/linux/i386/i686/lowlevelrwlock.S: Define HAVE_CMOV. + + * sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h: New file. + + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: New file. + + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: New file. + + * sysdeps/unix/sysv/linux/x86_64/pt-vfork.S: New file. + +2002-11-27 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/x86_64/bits/atomic.h: New file. + + * sysdeps/i386/i686/bits/atomic.h: Fix asm syntax for 8- and + 16-bit operations. + + * sysdeps/unix/sysv/linux/raise.c (raise): Use INTERNAL_SYSCALL if + possible since gettid cannot fail. + + * sysdeps/x86_64/pthreaddef.h: New file. + + * sysdeps/i386/pthreaddef.h (gettid): Removed. + + * sysdeps/x86_64/pthread_spin_init.c: New file. + * sysdeps/x86_64/pthread_spin_lock.c: New file. + * sysdeps/x86_64/pthread_spin_trylock.c: New file. + * sysdeps/x86_64/pthread_spin_unlock.c: New file. + + * sysdeps/i386/i686/pthread_spin_trylock.S (pthread_spin_trylock): + Add missing lock prefix. Minute optimization. + + * tst-spin2.c (main): Also check successful trylock call. + + * sysdeps/pthread/pthread_sigmask.c (pthread_sigmask): Use correct + syscall. Fix typo in case INTERNAL_SYSCALL is not used. + + * sysdeps/i386/pthread_spin_destroy.c: Moved to... + * sysdeps/pthread/pthread_spin_destroy.c: ...here. New file. + + * sysdeps/i386/pthread_sigmask.c: Removed. Use the generic code. + * sysdeps/pthread/pthread_sigmask.c (pthread_sigmask): Return correct + value in case of an error. Add support for INTERNAL_SYSCALL. + + * sysdeps/i386/pthread_sigmask.c (pthread_sigmask): Return correct + value in case of an error. + + * sysdeps/x86_64/tls.h: New file. + +2002-11-26 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/i386/tls.h (THREAD_GETMEM_NC): Change interface. It now + takes the array member name and the index as parameters. + (THREAD_SETMEM_NC): Likewise. + * pthread_getspecific.c: Use new THREAD_GETMEM_NC interface. + * pthread_setspecific.c: Use new THREAD_GETMEM_NC and THREAD_SETMEM_NC + interfaces. + + * sysdeps/i386/tls.h (THREAD_SETMEM): Use size of member element + to decide which code to use. + (THREAD_SETMEM_NC): Likewise. + + * allocatestack.c (queue_stack): Don't remove stack from list here. + Do it in the caller. Correct condition to prematurely terminate + loop to free stacks. + (__deallocate_stack): Remove stack from list here. + +2002-11-26 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-stack1. + * tst-stack1.c: New file. + + * allocatestack.c (allocate_stack): Initialize the TCB on a user + provided stack. + + * pthread_attr_getstack.c: Return bottom of the thread area. + +2002-11-25 Ulrich Drepper <drepper@redhat.com> + + * Makefile (libpthread-routines): Add pt-allocrtsig and + pthread_kill_other_threads. + * pt-allocrtsig.c: New file. + * pthread_kill_other_threads.c: New file. + * sysdeps/unix/sysv/linux/allocrtsig.c: Add additional aliases for + all three functions. + * sysdeps/unix/sysv/linux/Makefile (sysdep_routines): Remove + allocrtsig. + * sysdeps/unix/sysv/linux/Versions (libc:GLIBC_PRIVATE): Export + __libc_current_sigrtmin_private, __libc_current_sigrtmax_private, + and __libc_allocate_rtsig_private. + * Versions (libpthread): Export pthread_kill_other_threads_np, + __libc_current_sigrtmin, and __libc_current_sigrtmax. + +2002-11-24 Ulrich Drepper <drepper@redhat.com> + + * allocatestack.c (allocate_stack): stackaddr in attribute points to + the end of the stack. Adjust computations. + When mprotect call fails dequeue stack and free it. + * pthread_attr_setstack.c: Store top of the stack in stackaddr + attribute. + * pthread_getattr_np.c: Likewise. + + * descr.h (IS_DETACHED): Add some more parenthesis to prevent + surprises. + +2002-11-23 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/pthread/pthread.h (pthread_self): __THROW must come before + attribute definitions. Patch by Luca Barbieri <ldb@ldb.ods.org>. + +2002-11-22 Ulrich Drepper <drepper@redhat.com> + + * pthread_getspecific.c: Optimize access to first 2nd-level array. + * pthread_setspecific.c: Likewise. + +2002-11-21 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/createthread.c: Remove CLONE_ flags + definitions. Get them from the official place. + * sysdeps/unix/sysv/linux/i386/fork.c: Likewise. + + * sysdeps/unix/sysv/linux/i386/createthread.c: Update CLONE_* flags. + Use new CLONE_ flags in clone() calls. + + * sysdeps/unix/sysv/linux/fork.c: Use ARCH_FORK to actually fork. + * sysdeps/unix/sysv/linux/i386/fork.c: New file. + + * Versions: Add pthread_* functions for libc. + * forward.c: New file. + + * sysdeps/pthread/Makefile (libpthread-sysdeps_routines): Add + errno-loc. + * herrno.c: New file. + * res.c: New file. + + * Makefile (libpthread-routines): Remove sem_post, sem_wait, + sem_trywait, and sem_timedwait. Add herrno and res. + * sem_init.c: Don't initialize lock and waiters members. + * sem_open.c: Likewise. + * sem_post.c: Removed. + * sem_wait.c: Removed. + * sem_trywait.c: Removed. + * sem_timedwait.c: Removed. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S: Complete rewrite. + Includes full implementations of sem_post, sem_wait, sem_trywait, + and sem_timedwait. + * sysdeps/unix/sysv/linux/i386/lowlevelsem.h (lll_sem_post): Adjust + for new implementation. + * sysdeps/unix/sysv/linux/internaltypes.h (struct sem): Remove lock + and waiters fields. + + * tst-sem3.c: Improve error message. + * tst-signal3.c: Likewise. + + * init.c (__pthread_initialize_minimal): Use set_tid_address syscall + to tell the kernel about the termination futex and to initialize tid + member. Don't initialize main_thread. + * descr.h (struct pthread): Remove main_thread member. + * cancelllation.c (__do_cancel): Remove code handling main thread. + The main thread is not special anymore. + + * allocatestack.c (__reclaim_stacks): Mark stacks as unused. Add + size of the stacks to stack_cache_actsize. + + * pt-readv.c: Add missing "defined". + * pt-sigwait.c: Likewise. + * pt-writev.c: Likewise. + +2002-11-09 Ulrich Drepper <drepper@redhat.com> + + * Versions: Export __connect from libpthread. + Patch by Luca Barbieri <ldb@ldb.ods.org>. + + * Makefile (libpthread-routines): Add pt-raise. + * sysdeps/unix/sysv/linux/raise.c: New file. + * sysdeps/unix/sysv/linux/pt-raise.c: New file. + * sysdeps/generic/pt-raise.c: New file. + + * pthread_cond_init.c: Initialize all data elements of the condvar + structure. Patch by Luca Barbieri <ldb@ldb.ods.org>. + + * pthread_attr_init.c: Actually implement 2.0 compatibility version. + * pthread_create.c: Likewise. + + * Makefile (tests): Add tst-key1, tst-key2, tst-key3. + * tst-key1.c: New file. + * tst-key2.c: New file. + * tst-key3.c: New file. + + * Versions: Export pthread_detach for version GLIBC_2.0. + Reported by Saurabh Desai <sdesai@austin.ibm.com>. + +2002-11-08 Ulrich Drepper <drepper@redhat.com> + + * pthread_key_create.c: Terminate search after an unused key was found. + Patch by Luca Barbieri <ldb@ldb.ods.org>. + + * sysdeps/unix/sysv/linux/i386/pthread_once.S: Return zero. + Patch by Luca Barbieri <ldb@ldb.ods.org>. + +2002-10-10 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S: Use slow generic + dynamic lookup for errno in PIC. + + * allocatestack.c (get_cached_stack): Rearrange code slightly to + release the stack lock as soon as possible. + Call _dl_allocate_tls_init for TCB from the cache to re-initialize + the static TLS block. + (allocate_stack): Call _dl_allocate_tls_init for user-provided stack. + + * cancellation.c: Renamed from cancelation.c. + * Makefile: Adjust accordingly. + * pthreadP.h (CANCELLATION_P): Renamed from CANCELATION_P. + * cleanup_defer.c: Use CANCELLATION_P. + * pthread_testcancel.c: Likewise. + * descr.h: Fix spelling in comments. + * init.c: Likewise. + * pthread_getattr_np.c: Likewise. + * pthread_getschedparam.c: Likewise. + * pthread_setschedparam.c: Likewise. + * Versions: Likewise. + + * pt-pselect.c: New file. + * Makefile (libpthread-routines): Add pt-pselect. + * Versions: Add pselect. + + * tst-cancel4.c: New file. + * Makefile (tests): Add tst-cancel4. + +2002-10-09 Ulrich Drepper <drepper@redhat.com> + + * pthread_mutex_lock.c: Always record lock ownership. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_trylock.c: Likewise. + + * pt-readv.c: New file. + * pt-writev.c: New file. + * pt-creat.c: New file. + * pt-msgrcv.c: New file. + * pt-msgsnd.c: New file. + * pt-poll.c: New file. + * pt-select.c: New file. + * pt-sigpause.c: New file. + * pt-sigsuspend.c: New file. + * pt-sigwait.c: New file. + * pt-sigwaitinfo.c: New file. + * pt-waitid.c: New file. + * Makefile (libpthread-routines): Add pt-readv, pt-writev, pt-creat, + pt-msgrcv, pt-msgsnd, pt-poll, pt-select, pt-sigpause, pt-sigsuspend, + pt-sigwait, pt-sigwaitinfo, and pt-waitid. + * Versions: Add all the new functions. + + * tst-exit1.c: New file. + * Makefile (tests): Add tst-exit1. + + * sem_timedwait.c: Minor optimization for more optimal fastpath. + +2002-10-08 Ulrich Drepper <drepper@redhat.com> + + * pt-fcntl.c: Only enable asynchronous cancellation for F_SETLKW. + + * pthread_join.c: Enable asynchronous cancellation around lll_wait_tid + call. pthread_join is an official cancellation point. + * pthread_timedjoin.c: Likewise. + + * pthread_cond_wait.c: Revert order in which internal lock are dropped + and the condvar's mutex are retrieved. + * pthread_cond_timedwait.c: Likewise. + Reported by dice@saros.East.Sun.COM. + +2002-10-07 Ulrich Drepper <drepper@redhat.com> + + * pthreadP.h: Cut out all type definitions and move them... + * sysdeps/unix/sysv/linux/internaltypes.h: ...here. New file. + * pthreadP.h: Include <internaltypes.h>. + + * sysdeps/unix/sysv/linux/i386/lowlevelsem.h (lll_sem_post): Little + performance tweaks. + + * sem_trywait.c: Shuffle #includes around to get right order. + * sem_timedwait.c: Likewise. + * sem_post.c: Likewise. + * sem_wait.c: Likewise. + + * nptl 0.3 released. + + * Makefile (tests): Add tst-signal3. + * tst-signal3.c: New file. + +2002-10-05 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/lowlevelsem.h: Tell the compiler that + the asms modify the sem object. + (__lll_sem_timedwait): Now takes struct sem* as first parameter. + + * sysdeps/unix/sysv/linux/i386/bits/semaphore.h (sem_t): Don't expose + the actual members. + * pthreadP.h (struct sem): New type. Actual semaphore type. + * semaphoreP.h: Include pthreadP.h. + * sem_getvalue.c: Adjust to sem_t change. + * sem_init.c: Likewise. + * sem_open.c: Likewise. + * sem_post.c: Likewise. + * sem_timedwait.c: Likewise. + * sem_trywait.c: Likewise. + * sem_wait.c: Likewise. + +2002-10-04 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-basic2, tst-exec1, tst-exec3, tst-exec3. + * tst-basic2.c: New file. + * tst-exec1.c: New file. + * tst-exec2.c: New file. + * tst-exec3.c: New file. + + * tst-fork1.c: Remove extra */. + + * nptl 0.2 released. The API for IA-32 is complete. diff --git a/libpthread/nptl/DESIGN-barrier.txt b/libpthread/nptl/DESIGN-barrier.txt new file mode 100644 index 000000000..23463c6b7 --- /dev/null +++ b/libpthread/nptl/DESIGN-barrier.txt @@ -0,0 +1,44 @@ +Barriers pseudocode +=================== + + int pthread_barrier_wait(barrier_t *barrier); + +struct barrier_t { + + unsigned int lock: + - internal mutex + + unsigned int left; + - current barrier count, # of threads still needed. + + unsigned int init_count; + - number of threads needed for the barrier to continue. + + unsigned int curr_event; + - generation count +} + +pthread_barrier_wait(barrier_t *barrier) +{ + unsigned int event; + result = 0; + + lll_lock(barrier->lock); + if (!--barrier->left) { + barrier->curr_event++; + futex_wake(&barrier->curr_event, INT_MAX) + + result = BARRIER_SERIAL_THREAD; + } else { + event = barrier->curr_event; + lll_unlock(barrier->lock); + do { + futex_wait(&barrier->curr_event, event) + } while (event == barrier->curr_event); + } + + if (atomic_increment_val (barrier->left) == barrier->init_count) + lll_unlock(barrier->lock); + + return result; +} diff --git a/libpthread/nptl/DESIGN-condvar.txt b/libpthread/nptl/DESIGN-condvar.txt new file mode 100644 index 000000000..4845251c7 --- /dev/null +++ b/libpthread/nptl/DESIGN-condvar.txt @@ -0,0 +1,134 @@ +Conditional Variable pseudocode. +================================ + + int pthread_cond_timedwait (pthread_cond_t *cv, pthread_mutex_t *mutex); + int pthread_cond_signal (pthread_cond_t *cv); + int pthread_cond_broadcast (pthread_cond_t *cv); + +struct pthread_cond_t { + + unsigned int cond_lock; + + internal mutex + + uint64_t total_seq; + + Total number of threads using the conditional variable. + + uint64_t wakeup_seq; + + sequence number for next wakeup. + + uint64_t woken_seq; + + sequence number of last woken thread. + + uint32_t broadcast_seq; + +} + + +struct cv_data { + + pthread_cond_t *cv; + + uint32_t bc_seq + +} + + + +cleanup_handler(cv_data) +{ + cv = cv_data->cv; + lll_lock(cv->lock); + + if (cv_data->bc_seq == cv->broadcast_seq) { + ++cv->wakeup_seq; + ++cv->woken_seq; + } + + /* make sure no signal gets lost. */ + FUTEX_WAKE(cv->wakeup_seq, ALL); + + lll_unlock(cv->lock); +} + + +cond_timedwait(cv, mutex, timeout): +{ + lll_lock(cv->lock); + mutex_unlock(mutex); + + cleanup_push + + ++cv->total_seq; + val = seq = cv->wakeup_seq; + cv_data.bc = cv->broadcast_seq; + cv_data.cv = cv; + + while (1) { + + lll_unlock(cv->lock); + + enable_async(&cv_data); + + ret = FUTEX_WAIT(cv->wakeup_seq, val, timeout); + + restore_async + + lll_lock(cv->lock); + + if (bc != cv->broadcast_seq) + goto bc_out; + + val = cv->wakeup_seq; + + if (val != seq && cv->woken_seq != val) { + ret = 0; + break; + } + + if (ret == TIMEDOUT) { + ++cv->wakeup_seq; + break; + } + } + + ++cv->woken_seq; + + bc_out: + lll_unlock(cv->lock); + + cleanup_pop + + mutex_lock(mutex); + + return ret; +} + +cond_signal(cv) +{ + lll_lock(cv->lock); + + if (cv->total_seq > cv->wakeup_seq) { + ++cv->wakeup_seq; + FUTEX_WAKE(cv->wakeup_seq, 1); + } + + lll_unlock(cv->lock); +} + +cond_broadcast(cv) +{ + lll_lock(cv->lock); + + if (cv->total_seq > cv->wakeup_seq) { + cv->wakeup_seq = cv->total_seq; + cv->woken_seq = cv->total_seq; + ++cv->broadcast_seq; + FUTEX_WAKE(cv->wakeup_seq, ALL); + } + + lll_unlock(cv->lock); +} diff --git a/libpthread/nptl/DESIGN-rwlock.txt b/libpthread/nptl/DESIGN-rwlock.txt new file mode 100644 index 000000000..810d1b8f3 --- /dev/null +++ b/libpthread/nptl/DESIGN-rwlock.txt @@ -0,0 +1,113 @@ +Reader Writer Locks pseudocode +============================== + + pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); + pthread_rwlock_unlock(pthread_rwlock_t *rwlock); + pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); + +struct pthread_rwlock_t { + + unsigned int lock: + - internal mutex + + unsigned int writers_preferred; + - locking mode: 0 recursive, readers preferred + 1 nonrecursive, writers preferred + + unsigned int readers; + - number of read-only references various threads have + + pthread_t writer; + - descriptor of the writer or 0 + + unsigned int readers_wakeup; + - 'all readers should wake up' futex. + + unsigned int writer_wakeup; + - 'one writer should wake up' futex. + + unsigned int nr_readers_queued; + - number of readers queued up. + + unsigned int nr_writers_queued; + - number of writers queued up. +} + +pthread_rwlock_rdlock(pthread_rwlock_t *rwlock) +{ + lll_lock(rwlock->lock); + for (;;) { + if (!rwlock->writer && (!rwlock->nr_writers_queued || + !rwlock->writers_preferred)) + break; + + rwlock->nr_readers_queued++; + val = rwlock->readers_wakeup; + lll_unlock(rwlock->lock); + + futex_wait(&rwlock->readers_wakeup, val) + + lll_lock(rwlock->lock); + rwlock->nr_readers_queued--; + } + rwlock->readers++; + lll_unlock(rwlock->lock); +} + +pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock) +{ + int result = EBUSY; + lll_lock(rwlock->lock); + if (!rwlock->writer && (!rwlock->nr_writers_queued || + !rwlock->writers_preferred)) + rwlock->readers++; + lll_unlock(rwlock->lock); + return result; +} + +pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) +{ + lll_lock(rwlock->lock); + for (;;) { + if (!rwlock->writer && !rwlock->readers) + break; + + rwlock->nr_writers_queued++; + val = rwlock->writer_wakeup; + lll_unlock(rwlock->lock); + + futex_wait(&rwlock->writer_wakeup, val); + + lll_lock(rwlock->lock); + rwlock->nr_writers_queued--; + } + rwlock->writer = pthread_self(); + lll_unlock(rwlock->lock); +} + +pthread_rwlock_unlock(pthread_rwlock_t *rwlock) +{ + lll_lock(rwlock->lock); + + if (rwlock->writer) + rwlock->writer = 0; + else + rwlock->readers--; + + if (!rwlock->readers) { + if (rwlock->nr_writers_queued) { + ++rwlock->writer_wakeup; + lll_unlock(rwlock->lock); + futex_wake(&rwlock->writer_wakeup, 1); + return; + } else + if (rwlock->nr_readers_queued) { + ++rwlock->readers_wakeup; + lll_unlock(rwlock->lock); + futex_wake(&rwlock->readers_wakeup, MAX_INT); + return; + } + } + + lll_unlock(rwlock->lock); +} diff --git a/libpthread/nptl/DESIGN-sem.txt b/libpthread/nptl/DESIGN-sem.txt new file mode 100644 index 000000000..17eb0c11c --- /dev/null +++ b/libpthread/nptl/DESIGN-sem.txt @@ -0,0 +1,46 @@ +Semaphores pseudocode +============================== + + int sem_wait(sem_t * sem); + int sem_trywait(sem_t * sem); + int sem_post(sem_t * sem); + int sem_getvalue(sem_t * sem, int * sval); + +struct sem_t { + + unsigned int count; + - current semaphore count, also used as a futex +} + +sem_wait(sem_t *sem) +{ + for (;;) { + + if (atomic_decrement_if_positive(sem->count)) + break; + + futex_wait(&sem->count, 0) + } +} + +sem_post(sem_t *sem) +{ + n = atomic_increment(sem->count); + // Pass the new value of sem->count + futex_wake(&sem->count, n + 1); +} + +sem_trywait(sem_t *sem) +{ + if (atomic_decrement_if_positive(sem->count)) { + return 0; + } else { + return EAGAIN; + } +} + +sem_getvalue(sem_t *sem, int *sval) +{ + *sval = sem->count; + read_barrier(); +} diff --git a/libpthread/nptl/Makefile b/libpthread/nptl/Makefile new file mode 100644 index 000000000..f9100219a --- /dev/null +++ b/libpthread/nptl/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libpthread/nptl/Makefile.in b/libpthread/nptl/Makefile.in new file mode 100644 index 000000000..d9f2d2368 --- /dev/null +++ b/libpthread/nptl/Makefile.in @@ -0,0 +1,341 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005-2006 Steven J. Hill <sjhill@realitydiluted.com> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libpthread/nptl/sysdeps/$(TARGET_ARCH) \ + libpthread/nptl/sysdeps/unix/sysv/linux \ + libpthread/nptl/sysdeps/pthread + +libpthread-routines = init vars events version \ + pthread_create pthread_exit pthread_detach \ + pthread_join pthread_tryjoin pthread_timedjoin \ + pthread_self pthread_equal pthread_yield \ + pthread_getconcurrency pthread_setconcurrency \ + pthread_getschedparam pthread_setschedparam \ + pthread_setschedprio \ + pthread_attr_init pthread_attr_destroy \ + pthread_attr_getdetachstate pthread_attr_setdetachstate \ + pthread_attr_getguardsize pthread_attr_setguardsize \ + pthread_attr_getschedparam pthread_attr_setschedparam \ + pthread_attr_getschedpolicy pthread_attr_setschedpolicy \ + pthread_attr_getinheritsched \ + pthread_attr_setinheritsched \ + pthread_attr_getscope pthread_attr_setscope \ + pthread_attr_getstackaddr pthread_attr_setstackaddr \ + pthread_attr_getstacksize pthread_attr_setstacksize \ + pthread_attr_getstack pthread_attr_setstack \ + pthread_getattr_np \ + pthread_mutex_init pthread_mutex_destroy \ + pthread_mutex_lock pthread_mutex_trylock \ + pthread_mutex_timedlock pthread_mutex_unlock \ + pthread_mutex_consistent \ + pthread_mutexattr_init pthread_mutexattr_destroy \ + pthread_mutexattr_getpshared \ + pthread_mutexattr_setpshared \ + pthread_mutexattr_getrobust \ + pthread_mutexattr_setrobust \ + pthread_mutexattr_getprotocol \ + pthread_mutexattr_setprotocol \ + pthread_mutexattr_getprioceiling \ + pthread_mutexattr_setprioceiling \ + pthread_mutexattr_gettype pthread_mutexattr_settype \ + pthread_rwlock_init pthread_rwlock_destroy \ + pthread_rwlock_rdlock pthread_rwlock_timedrdlock \ + pthread_rwlock_wrlock pthread_rwlock_timedwrlock \ + pthread_rwlock_tryrdlock pthread_rwlock_trywrlock \ + pthread_rwlock_unlock \ + pthread_rwlockattr_init pthread_rwlockattr_destroy \ + pthread_rwlockattr_getpshared \ + pthread_rwlockattr_setpshared \ + pthread_rwlockattr_getkind_np \ + pthread_rwlockattr_setkind_np \ + pthread_cond_init pthread_cond_destroy \ + pthread_cond_wait pthread_cond_timedwait \ + pthread_cond_signal pthread_cond_broadcast \ + pthread_condattr_init pthread_condattr_destroy \ + pthread_condattr_getpshared pthread_condattr_setpshared \ + pthread_condattr_getclock pthread_condattr_setclock \ + pthread_spin_init pthread_spin_destroy \ + pthread_spin_lock pthread_spin_trylock \ + pthread_spin_unlock \ + pthread_barrier_init pthread_barrier_destroy \ + pthread_barrier_wait \ + pthread_barrierattr_init pthread_barrierattr_destroy \ + pthread_barrierattr_getpshared \ + pthread_barrierattr_setpshared \ + pthread_key_create pthread_key_delete \ + pthread_getspecific pthread_setspecific \ + pthread_sigmask pthread_kill \ + pthread_cancel pthread_testcancel \ + pthread_setcancelstate pthread_setcanceltype \ + pthread_once \ + pthread_atfork \ + pthread_getcpuclockid \ + pthread_clock_gettime pthread_clock_settime \ + sem_init sem_destroy \ + sem_open sem_close sem_unlink \ + sem_getvalue \ + sem_wait sem_trywait sem_timedwait sem_post \ + cleanup cleanup_defer cleanup_compat \ + cleanup_defer_compat unwind \ + pt-longjmp pt-cleanup\ + cancellation \ + lowlevellock \ + pt-vfork \ + ptw-write ptw-read ptw-close ptw-fcntl ptw-accept \ + ptw-connect ptw-recv ptw-recvfrom ptw-recvmsg ptw-send \ + ptw-sendmsg ptw-sendto ptw-fsync ptw-lseek ptw-llseek \ + ptw-msync ptw-nanosleep ptw-open ptw-open64 ptw-pause \ + ptw-pread ptw-pread64 ptw-pwrite ptw-pwrite64 \ + ptw-tcdrain ptw-wait ptw-waitpid ptw-msgrcv ptw-msgsnd \ + ptw-sigwait \ + pt-raise pt-system \ + flockfile ftrylockfile funlockfile \ + sigaction \ + herrno res \ + pthread_kill_other_threads \ + pthread_getaffinity pthread_setaffinity \ + pthread_attr_getaffinity pthread_attr_setaffinity \ + cleanup_routine unwind-forcedunwind + +libpthread-shared-only-routines = version pt-allocrtsig unwind-forcedunwind + +CFLAGS-pthread_atfork.c = -DNOT_IN_libc + +# Since cancellation handling is in large parts handled using exceptions +# we have to compile some files with exception handling enabled, some +# even with asynchronous unwind tables. + +# init.c contains sigcancel_handler(). +CFLAGS-init.c = -fexceptions -fasynchronous-unwind-tables +# The unwind code itself, +CFLAGS-unwind.c = -fexceptions +CFLAGS-unwind-forcedunwind.c = -fexceptions -fasynchronous-unwind-tables + +# The following three functions must be async-cancel safe. +CFLAGS-pthread_cancel.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pthread_setcancelstate.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pthread_setcanceltype.c = -fexceptions -fasynchronous-unwind-tables + +# These are internal functions which similar functionality as setcancelstate +# and setcanceltype. +CFLAGS-cancellation.c = -fasynchronous-unwind-tables +CFLAGS-libc-cancellation.c = -fasynchronous-unwind-tables + +# Calling pthread_exit() must cause the registered cancel handlers to +# be executed. Therefore exceptions have to be thrown through this +# function. +CFLAGS-pthread_exit.c = -fexceptions + +# Among others, __pthread_unwind is forwarded. This function must handle +# exceptions. +CFLAGS-forward.c = -fexceptions + +# The following are cancellation points. Some of the functions can +# block and therefore temporarily enable asynchronous cancellation. +# Those must be compiled asynchronous unwind tables. +CFLAGS-pthread_testcancel.c = -fexceptions +CFLAGS-pthread_join.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pthread_timedjoin.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pthread_once.c = $(uses-callbacks) -fexceptions \ + -fasynchronous-unwind-tables +CFLAGS-pthread_cond_wait.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pthread_cond_timedwait.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-sem_wait.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-sem_timedwait.c = -fexceptions -fasynchronous-unwind-tables + +# These are the function wrappers we have to duplicate here. +CFLAGS-fcntl.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-lockf.c = -fexceptions +CFLAGS-pread.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pread64.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pwrite.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pwrite64.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-wait.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-waitpid.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-sigwait.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-msgrcv.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-msgsnd.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-tcdrain.c = -fexceptions -fasynchronous-unwind-tables + +CFLAGS-pt-system.c = -fexceptions -I./libc/stdlib + +# +# The rest of this file is uClibc specific. +# +CFLAGS-pthread_barrier_init.c = -D_GNU_SOURCE +CFLAGS-pthread_barrier_destroy.c = -D_GNU_SOURCE +CFLAGS-pthread_barrierattr_init.c = -D_GNU_SOURCE +CFLAGS-pthread_barrierattr_destroy.c = -D_GNU_SOURCE +CFLAGS-pthread_barrierattr_getpshared.c = -D_GNU_SOURCE +CFLAGS-pthread_barrierattr_setpshared.c = -D_GNU_SOURCE +CFLAGS-sem_open.c = -D_GNU_SOURCE + +CFLAGS-nptl = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 $(SSP_ALL_CFLAGS) + +CFLAGS-OMIT-alloca_cutoff.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-forward.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-libc-lowlevelock.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-libc-cancellation.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + +libpthread-os-routines = pthread_yield +libpthread-misc-routines = pthread_rwlock_rdlock pthread_rwlock_timedrdlock \ + pthread_rwlock_wrlock pthread_rwlock_timedwrlock \ + pthread_rwlock_unlock pthread_cond_wait \ + pthread_cond_timedwait pthread_cond_signal \ + pthread_cond_broadcast pthread_spin_init \ + pthread_spin_destroy pthread_spin_lock \ + pthread_spin_trylock pthread_spin_unlock \ + pthread_barrier_init pthread_barrier_destroy \ + pthread_barrier_wait pthread_sigmask \ + pthread_kill pthread_once \ + pthread_getcpuclockid sem_wait \ + sem_trywait sem_timedwait \ + sem_post pt-longjmp \ + lowlevellock pt-vfork \ + ptw-close ptw-read ptw-write \ + ptw-fcntl ptw-accept ptw-connect \ + ptw-recv ptw-recvfrom ptw-recvmsg \ + ptw-send ptw-sendmsg ptw-sendto \ + ptw-fsync ptw-lseek ptw-llseek \ + ptw-msync ptw-nanosleep ptw-open \ + ptw-open64 ptw-pause ptw-pread \ + ptw-pread64 ptw-pwrite ptw-pwrite64 \ + ptw-tcdrain ptw-wait ptw-waitpid \ + ptw-msgrcv ptw-msgsnd ptw-sigwait \ + pt-raise flockfile ftrylockfile \ + funlockfile sigaction \ + pthread_getaffinity \ + pthread_setaffinity \ + pthread_attr_getaffinity \ + pthread_attr_setaffinity \ + unwind-forcedunwind + +ifeq ($(PTHREADS_DEBUG_SUPPORT),y) +LDFLAGS-libpthread.so := $(LDFLAGS_NOSTRIP) -Wl,-z,defs +else +LDFLAGS-libpthread.so := $(LDFLAGS) +endif + +LDFLAGS-libpthread.so += $(top_builddir)lib/$(UCLIBC_LDSO_NAME)-$(VERSION).so $(top_builddir)lib/libdl-$(VERSION).so + +LIBS-libpthread.so := $(LIBS) + +ifneq ($(UCLIBC_CTOR_DTOR),y) +START_FILE-libpthread.so := $(top_builddir)/libpthread/nptl/sysdeps/pthread/crti.o $(SHARED_START_FILES) +END_FILE-libpthread.so := $(SHARED_END_FILES) $(top_builddir)/libpthread/nptl/sysdeps/pthread/crtn.o +endif + +libpthread_FULL_NAME := libpthread-$(VERSION).so + +PTHREAD_DIR := $(top_srcdir)libpthread/nptl +PTHREAD_OUT := $(top_builddir)libpthread/nptl + +libpthread_static_SRC := pthread_atfork + +libpthread_a_SRC = $(patsubst %, $(PTHREAD_DIR)/%.c, \ + $(filter-out $(libpthread-os-routines) \ + $(libpthread-misc-routines) \ + $(libpthread-shared-only-routines), \ + $(libpthread-routines))) +libpthread_so_SRC = $(patsubst %, $(PTHREAD_DIR)/%.c, \ + $(filter-out $(libpthread-os-routines) \ + $(libpthread-misc-routines), $(libpthread-routines))) + +libc-static-y += $(patsubst %.c, $(PTHREAD_OUT)/%.o, alloca_cutoff.c \ + libc-cancellation.c) +libc-shared-y += $(patsubst %.c, $(PTHREAD_OUT)/%.oS, forward.c \ + libc-cancellation.c) +libpthread-nonshared-y += $(patsubst %,$(PTHREAD_OUT)/%.oS,$(libpthread_static_SRC)) + + +ifeq ($(DOPIC),y) +libpthread-a-y := $(patsubst $(PTHREAD_DIR)/%.c,$(PTHREAD_OUT)/%.os,$(libpthread_a_SRC)) +else +libpthread-a-y := $(patsubst $(PTHREAD_DIR)/%.c,$(PTHREAD_OUT)/%.o,$(libpthread_a_SRC)) +endif + +libpthread-so-y := $(patsubst $(PTHREAD_DIR)/%.c,$(PTHREAD_OUT)/%.oS,$(libpthread_so_SRC)) +libpthread-static-y += $(patsubst $(PTHREAD_DIR)/%.c,$(PTHREAD_OUT)/%.o,$(libpthread_a_SRC) $(libpthread_static_SRC)) + +objclean-y += libpthread_clean +headers_clean-y += nptl_headers_clean + +-include $(PTHREAD_DIR)/sysdeps/generic/Makefile.in +-include $(PTHREAD_DIR)/sysdeps/pthread/Makefile.in +-include $(PTHREAD_DIR)/sysdeps/$(TARGET_ARCH)/Makefile.arch +-include $(PTHREAD_DIR)/sysdeps/unix/sysv/linux/Makefile.in +-include $(PTHREAD_DIR)/sysdeps/unix/sysv/linux/$(TARGET_ARCH)/Makefile.arch + +lib-a-$(UCLIBC_HAS_THREADS) += $(top_builddir)lib/libpthread.a +lib-so-$(UCLIBC_HAS_THREADS) += $(top_builddir)lib/libpthread.so + +$(top_builddir)lib/libpthread.so: $(PTHREAD_OUT)/libpthread_so.a $(libc.depend) $(libdl.depend) $(top_builddir)lib/libpthread_nonshared.a + $(call link.so,$(libpthread_FULL_NAME),$(MAJOR_VERSION)) + $(Q)$(RM) $@ + $(Q)cp $(top_srcdir)extra/scripts/format.lds $@ + $(Q)echo "GROUP ( $(notdir $@).$(MAJOR_VERSION) libpthread_nonshared.a )" >> $@ + +$(PTHREAD_OUT)/libpthread_so.a: $(libpthread-so-y) + $(Q)$(RM) $@ +ifeq ($(PTHREADS_DEBUG_SUPPORT),y) + $(do_strip:-x=-X --strip-debug) +else + $(do_strip) +endif + $(do_ar) + +$(top_builddir)lib/libpthread.a: $(libpthread-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_strip) + $(do_ar) + +# +# Create 'pthread-errnos.h' header file. +# +CFLAGS-pthread-errnos.c = -S + +$(PTHREAD_OUT)/pthread-errnos.c: $(PTHREAD_DIR)/pthread-errnos.sym + $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ + +$(PTHREAD_OUT)/pthread-errnos.s: $(PTHREAD_OUT)/pthread-errnos.c + $(compile.c) + +$(PTHREAD_OUT)/pthread-errnos.h: $(PTHREAD_OUT)/pthread-errnos.s + $(do_sed) -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $@ + +pregen-headers-$(UCLIBC_HAS_THREADS_NATIVE) += $(PTHREAD_OUT)/pthread-errnos.h + +headers-$(UCLIBC_HAS_THREADS_NATIVE) += $(nptl_headers_bootstrap) + +$(top_builddir)include/pthread.h: + $(do_ln) ../$(PTDIR)/sysdeps/pthread/$(@F) $(top_builddir)$@ +$(top_builddir)include/semaphore.h: + $(do_ln) ../$(PTDIR)/$(@F) $(top_builddir)$@ +$(top_builddir)include/bits/semaphore.h: | include/bits + $(do_ln) ../../$(PTDIR)/sysdeps/unix/sysv/linux/$(TARGET_ARCH)/bits/$(@F) $(top_builddir)$@ +$(top_builddir)include/bits/pthreadtypes.h: | include/bits + $(do_ln) ../../$(PTDIR)/sysdeps/unix/sysv/linux/$(TARGET_ARCH)/bits/$(@F) $(top_builddir)$@ +$(top_builddir)include/bits/libc-lock.h: | include/bits + $(do_ln) ../../$(PTDIR)/sysdeps/pthread/bits/$(@F) $(top_builddir)$@ +$(top_builddir)include/bits/stdio-lock.h: | include/bits + $(do_ln) ../../$(PTDIR)/sysdeps/pthread/bits/$(@F) $(top_builddir)$@ + +nptl_headers_bootstrap := $(top_builddir)include/pthread.h \ + $(top_builddir)include/semaphore.h \ + $(top_builddir)include/bits/semaphore.h \ + $(top_builddir)include/bits/pthreadtypes.h \ + $(top_builddir)include/bits/libc-lock.h \ + $(top_builddir)include/bits/stdio-lock.h + + +nptl_headers_clean: + $(do_rm) $(nptl_headers_bootstrap) \ + $(addprefix $(PTHREAD_OUT)/pthread-errnos., c h s) + +libpthread_clean: + $(do_rm) $(addprefix $(PTHREAD_OUT)/*., o os oS a) diff --git a/libpthread/nptl/README.NPTL b/libpthread/nptl/README.NPTL new file mode 100644 index 000000000..7e50984cb --- /dev/null +++ b/libpthread/nptl/README.NPTL @@ -0,0 +1,307 @@ +The base NPTL code for uClibc is from the glibc project located at +<http://sourceware.org/glibc/>. The starting version was the HEAD of +the glibc CVS repository dated 2005-05-06. Important changes from +glibc will continue to be brought in as necessary until the version +for uClibc is standing on its own. All of the files were originally +brought over verbatim with no modifications. Obviously, these will +undergo any necessary changes needed for integration into uClibc. +Additionally (or subtractingly), the files and directories below +were removed and not imported. + +-- Steven J. Hill <sjhill@realitydiluted.com> on 2005-05-06 + + +nptl/Makeconfig +nptl/configure +nptl/shlib-versions +nptl/sysdeps/generic +nptl/sysdeps/ia64 +nptl/sysdeps/pthread/Makefile +nptl/sysdeps/pthread/Subdirs +nptl/sysdeps/pthread/allocalim.h +nptl/sysdeps/pthread/configure +nptl/sysdeps/pthread/configure.in +nptl/sysdeps/pthread/createthread.c +nptl/sysdeps/pthread/flockfile.c +nptl/sysdeps/pthread/ftrylockfile.c +nptl/sysdeps/pthread/funlockfile.c +nptl/sysdeps/pthread/librt-cancellation.c +nptl/sysdeps/pthread/list.h +nptl/sysdeps/pthread/malloc-machine.h +nptl/sysdeps/pthread/posix-timer.h +nptl/sysdeps/pthread/pt-initfini.c +nptl/sysdeps/pthread/pt-longjmp.c +nptl/sysdeps/pthread/pthread-functions.h +nptl/sysdeps/pthread/pthread.h +nptl/sysdeps/pthread/pthread_barrier_wait.c +nptl/sysdeps/pthread/pthread_cond_broadcast.c +nptl/sysdeps/pthread/pthread_cond_signal.c +nptl/sysdeps/pthread/pthread_cond_timedwait.c +nptl/sysdeps/pthread/pthread_cond_wait.c +nptl/sysdeps/pthread/pthread_getcpuclockid.c +nptl/sysdeps/pthread/pthread_once.c +nptl/sysdeps/pthread/pthread_rwlock_rdlock.c +nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c +nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c +nptl/sysdeps/pthread/pthread_rwlock_unlock.c +nptl/sysdeps/pthread/pthread_rwlock_wrlock.c +nptl/sysdeps/pthread/pthread_sigmask.c +nptl/sysdeps/pthread/pthread_spin_destroy.c +nptl/sysdeps/pthread/pthread_spin_init.c +nptl/sysdeps/pthread/pthread_spin_unlock.c +nptl/sysdeps/pthread/rt-unwind-resume.c +nptl/sysdeps/pthread/setxid.h +nptl/sysdeps/pthread/sigaction.c +nptl/sysdeps/pthread/sigfillset.c +nptl/sysdeps/pthread/sigprocmask.c +nptl/sysdeps/pthread/tcb-offsets.h +nptl/sysdeps/pthread/timer_create.c +nptl/sysdeps/pthread/timer_delete.c +nptl/sysdeps/pthread/timer_getoverr.c +nptl/sysdeps/pthread/timer_gettime.c +nptl/sysdeps/pthread/timer_routines.c +nptl/sysdeps/pthread/timer_settime.c +nptl/sysdeps/pthread/tst-mqueue8x.c +nptl/sysdeps/pthread/tst-timer.c +nptl/sysdeps/pthread/unwind-forcedunwind.c +nptl/sysdeps/pthread/unwind-resume.c +nptl/sysdeps/s390 +nptl/sysdeps/unix +nptl/tst-_res1.c +nptl/tst-_res1mod1.c +nptl/tst-_res1mod2.c +nptl/tst-align.c +nptl/tst-align2.c +nptl/tst-atfork1.c +nptl/tst-atfork2.c +nptl/tst-atfork2mod.c +nptl/tst-attr1.c +nptl/tst-attr2.c +nptl/tst-attr3.c +nptl/tst-backtrace1.c +nptl/tst-barrier1.c +nptl/tst-barrier2.c +nptl/tst-barrier3.c +nptl/tst-barrier4.c +nptl/tst-basic1.c +nptl/tst-basic2.c +nptl/tst-basic3.c +nptl/tst-basic4.c +nptl/tst-basic5.c +nptl/tst-basic6.c +nptl/tst-cancel-wrappers.sh +nptl/tst-cancel1.c +nptl/tst-cancel10.c +nptl/tst-cancel11.c +nptl/tst-cancel12.c +nptl/tst-cancel13.c +nptl/tst-cancel14.c +nptl/tst-cancel15.c +nptl/tst-cancel16.c +nptl/tst-cancel17.c +nptl/tst-cancel18.c +nptl/tst-cancel19.c +nptl/tst-cancel2.c +nptl/tst-cancel20.c +nptl/tst-cancel21.c +nptl/tst-cancel22.c +nptl/tst-cancel23.c +nptl/tst-cancel3.c +nptl/tst-cancel4.c +nptl/tst-cancel5.c +nptl/tst-cancel6.c +nptl/tst-cancel7.c +nptl/tst-cancel8.c +nptl/tst-cancel9.c +nptl/tst-cancelx1.c +nptl/tst-cancelx10.c +nptl/tst-cancelx11.c +nptl/tst-cancelx12.c +nptl/tst-cancelx13.c +nptl/tst-cancelx14.c +nptl/tst-cancelx15.c +nptl/tst-cancelx16.c +nptl/tst-cancelx17.c +nptl/tst-cancelx18.c +nptl/tst-cancelx2.c +nptl/tst-cancelx20.c +nptl/tst-cancelx21.c +nptl/tst-cancelx3.c +nptl/tst-cancelx4.c +nptl/tst-cancelx5.c +nptl/tst-cancelx6.c +nptl/tst-cancelx7.c +nptl/tst-cancelx8.c +nptl/tst-cancelx9.c +nptl/tst-cleanup0.c +nptl/tst-cleanup0.expect +nptl/tst-cleanup1.c +nptl/tst-cleanup2.c +nptl/tst-cleanup3.c +nptl/tst-cleanup4.c +nptl/tst-cleanup4aux.c +nptl/tst-cleanupx0.c +nptl/tst-cleanupx0.expect +nptl/tst-cleanupx1.c +nptl/tst-cleanupx2.c +nptl/tst-cleanupx3.c +nptl/tst-cleanupx4.c +nptl/tst-clock1.c +nptl/tst-clock2.c +nptl/tst-cond1.c +nptl/tst-cond10.c +nptl/tst-cond11.c +nptl/tst-cond12.c +nptl/tst-cond13.c +nptl/tst-cond14.c +nptl/tst-cond15.c +nptl/tst-cond16.c +nptl/tst-cond17.c +nptl/tst-cond18.c +nptl/tst-cond19.c +nptl/tst-cond2.c +nptl/tst-cond20.c +nptl/tst-cond21.c +nptl/tst-cond3.c +nptl/tst-cond4.c +nptl/tst-cond5.c +nptl/tst-cond6.c +nptl/tst-cond7.c +nptl/tst-cond8.c +nptl/tst-cond9.c +nptl/tst-context1.c +nptl/tst-detach1.c +nptl/tst-dlsym1.c +nptl/tst-eintr1.c +nptl/tst-eintr2.c +nptl/tst-eintr3.c +nptl/tst-eintr4.c +nptl/tst-eintr5.c +nptl/tst-exec1.c +nptl/tst-exec2.c +nptl/tst-exec3.c +nptl/tst-exec4.c +nptl/tst-execstack-mod.c +nptl/tst-execstack.c +nptl/tst-exit1.c +nptl/tst-exit2.c +nptl/tst-exit3.c +nptl/tst-fini1.c +nptl/tst-fini1mod.c +nptl/tst-flock1.c +nptl/tst-flock2.c +nptl/tst-fork1.c +nptl/tst-fork2.c +nptl/tst-fork3.c +nptl/tst-fork4.c +nptl/tst-getpid1.c +nptl/tst-getpid2.c +nptl/tst-join1.c +nptl/tst-join2.c +nptl/tst-join3.c +nptl/tst-join4.c +nptl/tst-join5.c +nptl/tst-key1.c +nptl/tst-key2.c +nptl/tst-key3.c +nptl/tst-key4.c +nptl/tst-kill1.c +nptl/tst-kill2.c +nptl/tst-kill3.c +nptl/tst-kill4.c +nptl/tst-kill5.c +nptl/tst-kill6.c +nptl/tst-locale1.c +nptl/tst-locale2.c +nptl/tst-mutex1.c +nptl/tst-mutex2.c +nptl/tst-mutex3.c +nptl/tst-mutex4.c +nptl/tst-mutex5.c +nptl/tst-mutex5a.c +nptl/tst-mutex6.c +nptl/tst-mutex7.c +nptl/tst-mutex7a.c +nptl/tst-mutex8.c +nptl/tst-mutex9.c +nptl/tst-oddstacklimit.c +nptl/tst-once1.c +nptl/tst-once2.c +nptl/tst-once3.c +nptl/tst-once4.c +nptl/tst-oncex3.c +nptl/tst-oncex4.c +nptl/tst-popen1.c +nptl/tst-raise1.c +nptl/tst-rwlock1.c +nptl/tst-rwlock10.c +nptl/tst-rwlock11.c +nptl/tst-rwlock12.c +nptl/tst-rwlock13.c +nptl/tst-rwlock14.c +nptl/tst-rwlock2.c +nptl/tst-rwlock3.c +nptl/tst-rwlock4.c +nptl/tst-rwlock5.c +nptl/tst-rwlock6.c +nptl/tst-rwlock7.c +nptl/tst-rwlock8.c +nptl/tst-rwlock9.c +nptl/tst-sched1.c +nptl/tst-sem1.c +nptl/tst-sem2.c +nptl/tst-sem3.c +nptl/tst-sem4.c +nptl/tst-sem5.c +nptl/tst-sem6.c +nptl/tst-sem7.c +nptl/tst-sem8.c +nptl/tst-sem9.c +nptl/tst-setuid1-static.c +nptl/tst-setuid1.c +nptl/tst-signal1.c +nptl/tst-signal2.c +nptl/tst-signal3.c +nptl/tst-signal4.c +nptl/tst-signal5.c +nptl/tst-signal6.c +nptl/tst-spin1.c +nptl/tst-spin2.c +nptl/tst-spin3.c +nptl/tst-stack1.c +nptl/tst-stack2.c +nptl/tst-stack3.c +nptl/tst-stdio1.c +nptl/tst-stdio2.c +nptl/tst-sysconf.c +nptl/tst-tls1.c +nptl/tst-tls2.c +nptl/tst-tls3.c +nptl/tst-tls3mod.c +nptl/tst-tls4.c +nptl/tst-tls4moda.c +nptl/tst-tls4modb.c +nptl/tst-tls5.c +nptl/tst-tls5.h +nptl/tst-tls5mod.c +nptl/tst-tls5moda.c +nptl/tst-tls5modb.c +nptl/tst-tls5modc.c +nptl/tst-tls5modd.c +nptl/tst-tls5mode.c +nptl/tst-tls5modf.c +nptl/tst-tls6.sh +nptl/tst-tsd1.c +nptl/tst-tsd2.c +nptl/tst-tsd3.c +nptl/tst-tsd4.c +nptl/tst-tsd5.c +nptl/tst-umask1.c +nptl/tst-unload.c +nptl/tst-vfork1.c +nptl/tst-vfork1x.c +nptl/tst-vfork2.c +nptl/tst-vfork2x.c +nptl/version.c +nptl_db/ChangeLog +nptl_db/shlib-versions diff --git a/libpthread/nptl/TODO b/libpthread/nptl/TODO new file mode 100644 index 000000000..70b8fe4f7 --- /dev/null +++ b/libpthread/nptl/TODO @@ -0,0 +1,31 @@ +- we should probably extend pthread_mutexattr_t with a field to create a + single linked list of all instances. This requires changing the + pthread_mutexattr_* functions. + + +- a new attribute for mutexes: number of times we spin before calling +sys_futex + +- for adaptive mutexes: when releasing, determine whether somebody spins. +If yes, for a short time release lock. If someone else locks no wakeup +syscall needed. + + + +- test with threaded process terminating and semadj (?) being applied + only after all threads are gone + + + +- semaphore changes: + + - sem_post should only wake one thread and only when the state of + the semaphore changed from 0 to 1 + + this also requires that sem_wait and sem_timedwait don't drop the + post if they get canceled. + + - possibly add counter field. This requires reviving the + differences between old and new semaphose funtions. The old ones + stay as they are now. The new once can use an additional field + wich is the counter for the number of waiters diff --git a/libpthread/nptl/TODO-kernel b/libpthread/nptl/TODO-kernel new file mode 100644 index 000000000..ad6d2a4b5 --- /dev/null +++ b/libpthread/nptl/TODO-kernel @@ -0,0 +1,20 @@ +- setuid/setgid must effect process + + test syscalls (getuid) afterwards + + test core file content + + + use UID/GID in access(2), chmod(2), chown(2), link(2) + +- nice level is process property + +- rlimit should be process-wide and SIGXCPU should be sent if all threads + together exceed the limit + +- getrusage() must return resource utilization for the process + + + +The following are possible optimizations and in no way required: + + +- the scheduler should be thread group-aware, i.e., it has to give time to + the thread group not proportional to the number of threads. diff --git a/libpthread/nptl/TODO-testing b/libpthread/nptl/TODO-testing new file mode 100644 index 000000000..e076e5624 --- /dev/null +++ b/libpthread/nptl/TODO-testing @@ -0,0 +1,20 @@ +pthread_attr_setguardsize + + test effectiveness + +pthread_attr_[sg]etschedparam + + what to test? + +pthread_attr_[sg]etstack + + some more tests needed + +pthread_getcpuclockid + + check that value is reset -> rt subdir + +pthread_getschedparam +pthread_setschedparam + + what to test? diff --git a/libpthread/nptl/alloca_cutoff.c b/libpthread/nptl/alloca_cutoff.c new file mode 100644 index 000000000..ba26ceba3 --- /dev/null +++ b/libpthread/nptl/alloca_cutoff.c @@ -0,0 +1,36 @@ +/* Determine whether block of given size can be allocated on the stack or not. + Copyright (C) 2002 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 <alloca.h> +#include <stdlib.h> +#include <sys/param.h> +#include <pthreadP.h> + + +int +__libc_alloca_cutoff (size_t size) +{ + return size <= (MIN (__MAX_ALLOCA_CUTOFF, + THREAD_GETMEM (THREAD_SELF, stackblock_size) / 4 + /* The main thread, before the thread library is + initialized, has zero in the stackblock_size + element. Since it is the main thread we can + assume the maximum available stack space. */ + ?: __MAX_ALLOCA_CUTOFF * 4)); +} diff --git a/libpthread/nptl/allocatestack.c b/libpthread/nptl/allocatestack.c new file mode 100644 index 000000000..7d4f9fd1c --- /dev/null +++ b/libpthread/nptl/allocatestack.c @@ -0,0 +1,1216 @@ +/* Copyright (C) 2002-2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include <signal.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/param.h> +#include <tls.h> +#include <lowlevellock.h> +#include <link.h> +#include <bits/kernel-features.h> + + +#ifndef NEED_SEPARATE_REGISTER_STACK + +/* Most architectures have exactly one stack pointer. Some have more. */ +# define STACK_VARIABLES void *stackaddr = NULL + +/* How to pass the values to the 'create_thread' function. */ +# define STACK_VARIABLES_ARGS stackaddr + +/* How to declare function which gets there parameters. */ +# define STACK_VARIABLES_PARMS void *stackaddr + +/* How to declare allocate_stack. */ +# define ALLOCATE_STACK_PARMS void **stack + +/* This is how the function is called. We do it this way to allow + other variants of the function to have more parameters. */ +# define ALLOCATE_STACK(attr, pd) allocate_stack (attr, pd, &stackaddr) + +#else + +/* We need two stacks. The kernel will place them but we have to tell + the kernel about the size of the reserved address space. */ +# define STACK_VARIABLES void *stackaddr = NULL; size_t stacksize = 0 + +/* How to pass the values to the 'create_thread' function. */ +# define STACK_VARIABLES_ARGS stackaddr, stacksize + +/* How to declare function which gets there parameters. */ +# define STACK_VARIABLES_PARMS void *stackaddr, size_t stacksize + +/* How to declare allocate_stack. */ +# define ALLOCATE_STACK_PARMS void **stack, size_t *stacksize + +/* This is how the function is called. We do it this way to allow + other variants of the function to have more parameters. */ +# define ALLOCATE_STACK(attr, pd) \ + allocate_stack (attr, pd, &stackaddr, &stacksize) + +#endif + + +/* Default alignment of stack. */ +#ifndef STACK_ALIGN +# define STACK_ALIGN __alignof__ (long double) +#endif + +/* Default value for minimal stack size after allocating thread + descriptor and guard. */ +#ifndef MINIMAL_REST_STACK +# define MINIMAL_REST_STACK 4096 +#endif + + +/* Newer kernels have the MAP_STACK flag to indicate a mapping is used for + a stack. Use it when possible. */ +#ifndef MAP_STACK +# define MAP_STACK 0 +#endif + +/* This yields the pointer that TLS support code calls the thread pointer. */ +#if defined(TLS_TCB_AT_TP) +# define TLS_TPADJ(pd) (pd) +#elif defined(TLS_DTV_AT_TP) +# define TLS_TPADJ(pd) ((struct pthread *)((char *) (pd) + TLS_PRE_TCB_SIZE)) +#endif + +/* Cache handling for not-yet free stacks. */ + +/* Maximum size in kB of cache. */ +static size_t stack_cache_maxsize = 40 * 1024 * 1024; /* 40MiBi by default. */ +static size_t stack_cache_actsize; + +/* Mutex protecting this variable. */ +static int stack_cache_lock = LLL_LOCK_INITIALIZER; + +/* List of queued stack frames. */ +static LIST_HEAD (stack_cache); + +/* List of the stacks in use. */ +static LIST_HEAD (stack_used); + +/* We need to record what list operations we are going to do so that, + in case of an asynchronous interruption due to a fork() call, we + can correct for the work. */ +static uintptr_t in_flight_stack; + +/* List of the threads with user provided stacks in use. No need to + initialize this, since it's done in __pthread_initialize_minimal. */ +list_t __stack_user __attribute__ ((nocommon)); +hidden_data_def (__stack_user) + +#if COLORING_INCREMENT != 0 +/* Number of threads created. */ +static unsigned int nptl_ncreated; +#endif + + +/* Check whether the stack is still used or not. */ +#define FREE_P(descr) ((descr)->tid <= 0) + + +static void +stack_list_del (list_t *elem) +{ + in_flight_stack = (uintptr_t) elem; + + atomic_write_barrier (); + + list_del (elem); + + atomic_write_barrier (); + + in_flight_stack = 0; +} + + +static void +stack_list_add (list_t *elem, list_t *list) +{ + in_flight_stack = (uintptr_t) elem | 1; + + atomic_write_barrier (); + + list_add (elem, list); + + atomic_write_barrier (); + + in_flight_stack = 0; +} + + +/* We create a double linked list of all cache entries. Double linked + because this allows removing entries from the end. */ + + +/* Get a stack frame from the cache. We have to match by size since + some blocks might be too small or far too large. */ +static struct pthread * +get_cached_stack (size_t *sizep, void **memp) +{ + size_t size = *sizep; + struct pthread *result = NULL; + list_t *entry; + + lll_lock (stack_cache_lock, LLL_PRIVATE); + + /* Search the cache for a matching entry. We search for the + smallest stack which has at least the required size. Note that + in normal situations the size of all allocated stacks is the + same. As the very least there are only a few different sizes. + Therefore this loop will exit early most of the time with an + exact match. */ + list_for_each (entry, &stack_cache) + { + struct pthread *curr; + + curr = list_entry (entry, struct pthread, list); + if (FREE_P (curr) && curr->stackblock_size >= size) + { + if (curr->stackblock_size == size) + { + result = curr; + break; + } + + if (result == NULL + || result->stackblock_size > curr->stackblock_size) + result = curr; + } + } + + if (__builtin_expect (result == NULL, 0) + /* Make sure the size difference is not too excessive. In that + case we do not use the block. */ + || __builtin_expect (result->stackblock_size > 4 * size, 0)) + { + /* Release the lock. */ + lll_unlock (stack_cache_lock, LLL_PRIVATE); + + return NULL; + } + + /* Dequeue the entry. */ + stack_list_del (&result->list); + + /* And add to the list of stacks in use. */ + stack_list_add (&result->list, &stack_used); + + /* And decrease the cache size. */ + stack_cache_actsize -= result->stackblock_size; + + /* Release the lock early. */ + lll_unlock (stack_cache_lock, LLL_PRIVATE); + + /* Report size and location of the stack to the caller. */ + *sizep = result->stackblock_size; + *memp = result->stackblock; + + /* Cancellation handling is back to the default. */ + result->cancelhandling = 0; + result->cleanup = NULL; + + /* No pending event. */ + result->nextevent = NULL; + + /* Clear the DTV. */ + dtv_t *dtv = GET_DTV (TLS_TPADJ (result)); + memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t)); + + /* Re-initialize the TLS. */ + _dl_allocate_tls_init (TLS_TPADJ (result)); + + return result; +} + + +/* Free stacks until cache size is lower than LIMIT. */ +void +__free_stacks (size_t limit) +{ + /* We reduce the size of the cache. Remove the last entries until + the size is below the limit. */ + list_t *entry; + list_t *prev; + + /* Search from the end of the list. */ + list_for_each_prev_safe (entry, prev, &stack_cache) + { + struct pthread *curr; + + curr = list_entry (entry, struct pthread, list); + if (FREE_P (curr)) + { + /* Unlink the block. */ + stack_list_del (entry); + + /* Account for the freed memory. */ + stack_cache_actsize -= curr->stackblock_size; + + /* Free the memory associated with the ELF TLS. */ + _dl_deallocate_tls (TLS_TPADJ (curr), false); + + /* Remove this block. This should never fail. If it does + something is really wrong. */ + if (munmap (curr->stackblock, curr->stackblock_size) != 0) + abort (); + + /* Maybe we have freed enough. */ + if (stack_cache_actsize <= limit) + break; + } + } +} + + +/* Add a stack frame which is not used anymore to the stack. Must be + called with the cache lock held. */ +static inline void +__attribute ((always_inline)) +queue_stack (struct pthread *stack) +{ + /* We unconditionally add the stack to the list. The memory may + still be in use but it will not be reused until the kernel marks + the stack as not used anymore. */ + stack_list_add (&stack->list, &stack_cache); + + stack_cache_actsize += stack->stackblock_size; + if (__builtin_expect (stack_cache_actsize > stack_cache_maxsize, 0)) + __free_stacks (stack_cache_maxsize); +} + + +static int +internal_function +change_stack_perm (struct pthread *pd +#ifdef NEED_SEPARATE_REGISTER_STACK + , size_t pagemask +#endif + ) +{ +#ifdef NEED_SEPARATE_REGISTER_STACK + void *stack = (pd->stackblock + + (((((pd->stackblock_size - pd->guardsize) / 2) + & pagemask) + pd->guardsize) & pagemask)); + size_t len = pd->stackblock + pd->stackblock_size - stack; +#elif _STACK_GROWS_DOWN + void *stack = pd->stackblock + pd->guardsize; + size_t len = pd->stackblock_size - pd->guardsize; +#elif _STACK_GROWS_UP + void *stack = pd->stackblock; + size_t len = (uintptr_t) pd - pd->guardsize - (uintptr_t) pd->stackblock; +#else +# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +#endif + if (mprotect (stack, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) + return errno; + + return 0; +} + + +static int +allocate_stack (const struct pthread_attr *attr, struct pthread **pdp, + ALLOCATE_STACK_PARMS) +{ + struct pthread *pd; + size_t size; + size_t pagesize_m1 = __getpagesize () - 1; + void *stacktop; + + assert (attr != NULL); + assert (powerof2 (pagesize_m1 + 1)); + assert (TCB_ALIGNMENT >= STACK_ALIGN); + + /* Get the stack size from the attribute if it is set. Otherwise we + use the default we determined at start time. */ + size = attr->stacksize ?: __default_stacksize; + + /* Get memory for the stack. */ + if (__builtin_expect (attr->flags & ATTR_FLAG_STACKADDR, 0)) + { + uintptr_t adj; + + /* If the user also specified the size of the stack make sure it + is large enough. */ + if (attr->stacksize != 0 + && attr->stacksize < (__static_tls_size + MINIMAL_REST_STACK)) + return EINVAL; + + /* Adjust stack size for alignment of the TLS block. */ +#if defined(TLS_TCB_AT_TP) + adj = ((uintptr_t) attr->stackaddr - TLS_TCB_SIZE) + & __static_tls_align_m1; + assert (size > adj + TLS_TCB_SIZE); +#elif defined(TLS_DTV_AT_TP) + adj = ((uintptr_t) attr->stackaddr - __static_tls_size) + & __static_tls_align_m1; + assert (size > adj); +#endif + + /* The user provided some memory. Let's hope it matches the + size... We do not allocate guard pages if the user provided + the stack. It is the user's responsibility to do this if it + is wanted. */ +#if defined(TLS_TCB_AT_TP) + pd = (struct pthread *) ((uintptr_t) attr->stackaddr + - TLS_TCB_SIZE - adj); +#elif defined(TLS_DTV_AT_TP) + pd = (struct pthread *) (((uintptr_t) attr->stackaddr + - __static_tls_size - adj) + - TLS_PRE_TCB_SIZE); +#endif + + /* The user provided stack memory needs to be cleared. */ + memset (pd, '\0', sizeof (struct pthread)); + + /* The first TSD block is included in the TCB. */ + pd->specific[0] = pd->specific_1stblock; + + /* Remember the stack-related values. */ + pd->stackblock = (char *) attr->stackaddr - size; + pd->stackblock_size = size; + + /* This is a user-provided stack. It will not be queued in the + stack cache nor will the memory (except the TLS memory) be freed. */ + pd->user_stack = true; + + /* This is at least the second thread. */ + pd->header.multiple_threads = 1; +#ifndef TLS_MULTIPLE_THREADS_IN_TCB + __pthread_multiple_threads = *__libc_multiple_threads_ptr = 1; +#endif + +#ifndef __ASSUME_PRIVATE_FUTEX + /* The thread must know when private futexes are supported. */ + pd->header.private_futex = THREAD_GETMEM (THREAD_SELF, + header.private_futex); +#endif + +#ifdef NEED_DL_SYSINFO + /* Copy the sysinfo value from the parent. */ + THREAD_SYSINFO(pd) = THREAD_SELF_SYSINFO; +#endif + + /* The process ID is also the same as that of the caller. */ + pd->pid = THREAD_GETMEM (THREAD_SELF, pid); + + /* Allocate the DTV for this thread. */ + if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL) + { + /* Something went wrong. */ + assert (errno == ENOMEM); + return EAGAIN; + } + + + /* Prepare to modify global data. */ + lll_lock (stack_cache_lock, LLL_PRIVATE); + + /* And add to the list of stacks in use. */ + list_add (&pd->list, &__stack_user); + + lll_unlock (stack_cache_lock, LLL_PRIVATE); + } + else + { + /* Allocate some anonymous memory. If possible use the cache. */ + size_t guardsize; + size_t reqsize; + void *mem = 0; + const int prot = (PROT_READ | PROT_WRITE); + +#if COLORING_INCREMENT != 0 + /* Add one more page for stack coloring. Don't do it for stacks + with 16 times pagesize or larger. This might just cause + unnecessary misalignment. */ + if (size <= 16 * pagesize_m1) + size += pagesize_m1 + 1; +#endif + + /* Adjust the stack size for alignment. */ + size &= ~__static_tls_align_m1; + assert (size != 0); + + /* Make sure the size of the stack is enough for the guard and + eventually the thread descriptor. */ + guardsize = (attr->guardsize + pagesize_m1) & ~pagesize_m1; + if (__builtin_expect (size < ((guardsize + __static_tls_size + + MINIMAL_REST_STACK + pagesize_m1) + & ~pagesize_m1), + 0)) + /* The stack is too small (or the guard too large). */ + return EINVAL; + + /* Try to get a stack from the cache. */ + reqsize = size; + pd = get_cached_stack (&size, &mem); + if (pd == NULL) + { + /* To avoid aliasing effects on a larger scale than pages we + adjust the allocated stack size if necessary. This way + allocations directly following each other will not have + aliasing problems. */ +#if MULTI_PAGE_ALIASING != 0 + if ((size % MULTI_PAGE_ALIASING) == 0) + size += pagesize_m1 + 1; +#endif + + mem = mmap (NULL, size, prot, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); + + if (__builtin_expect (mem == MAP_FAILED, 0)) + { + if (errno == ENOMEM) + __set_errno (EAGAIN); + + return errno; + } + + /* SIZE is guaranteed to be greater than zero. + So we can never get a null pointer back from mmap. */ + assert (mem != NULL); + +#if COLORING_INCREMENT != 0 + /* Atomically increment NCREATED. */ + unsigned int ncreated = atomic_increment_val (&nptl_ncreated); + + /* We chose the offset for coloring by incrementing it for + every new thread by a fixed amount. The offset used + module the page size. Even if coloring would be better + relative to higher alignment values it makes no sense to + do it since the mmap() interface does not allow us to + specify any alignment for the returned memory block. */ + size_t coloring = (ncreated * COLORING_INCREMENT) & pagesize_m1; + + /* Make sure the coloring offsets does not disturb the alignment + of the TCB and static TLS block. */ + if (__builtin_expect ((coloring & __static_tls_align_m1) != 0, 0)) + coloring = (((coloring + __static_tls_align_m1) + & ~(__static_tls_align_m1)) + & ~pagesize_m1); +#else + /* Unless specified we do not make any adjustments. */ +# define coloring 0 +#endif + + /* Place the thread descriptor at the end of the stack. */ +#if defined(TLS_TCB_AT_TP) + pd = (struct pthread *) ((char *) mem + size - coloring) - 1; +#elif defined(TLS_DTV_AT_TP) + pd = (struct pthread *) ((((uintptr_t) mem + size - coloring + - __static_tls_size) + & ~__static_tls_align_m1) + - TLS_PRE_TCB_SIZE); +#endif + + /* Remember the stack-related values. */ + pd->stackblock = mem; + pd->stackblock_size = size; + + /* We allocated the first block thread-specific data array. + This address will not change for the lifetime of this + descriptor. */ + pd->specific[0] = pd->specific_1stblock; + + /* This is at least the second thread. */ + pd->header.multiple_threads = 1; +#ifndef TLS_MULTIPLE_THREADS_IN_TCB + __pthread_multiple_threads = *__libc_multiple_threads_ptr = 1; +#endif + +#ifndef __ASSUME_PRIVATE_FUTEX + /* The thread must know when private futexes are supported. */ + pd->header.private_futex = THREAD_GETMEM (THREAD_SELF, + header.private_futex); +#endif + +#ifdef NEED_DL_SYSINFO + /* Copy the sysinfo value from the parent. */ + THREAD_SYSINFO(pd) = THREAD_SELF_SYSINFO; +#endif + + /* The process ID is also the same as that of the caller. */ + pd->pid = THREAD_GETMEM (THREAD_SELF, pid); + + /* Allocate the DTV for this thread. */ + if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL) + { + /* Something went wrong. */ + assert (errno == ENOMEM); + + /* Free the stack memory we just allocated. */ + (void) munmap (mem, size); + + return EAGAIN; + } + + + /* Prepare to modify global data. */ + lll_lock (stack_cache_lock, LLL_PRIVATE); + + /* And add to the list of stacks in use. */ + stack_list_add (&pd->list, &stack_used); + + lll_unlock (stack_cache_lock, LLL_PRIVATE); + + + /* Note that all of the stack and the thread descriptor is + zeroed. This means we do not have to initialize fields + with initial value zero. This is specifically true for + the 'tid' field which is always set back to zero once the + stack is not used anymore and for the 'guardsize' field + which will be read next. */ + } + + /* Create or resize the guard area if necessary. */ + if (__builtin_expect (guardsize > pd->guardsize, 0)) + { +#ifdef NEED_SEPARATE_REGISTER_STACK + char *guard = mem + (((size - guardsize) / 2) & ~pagesize_m1); +#elif _STACK_GROWS_DOWN + char *guard = mem; +# elif _STACK_GROWS_UP + char *guard = (char *) (((uintptr_t) pd - guardsize) & ~pagesize_m1); +#endif + if (mprotect (guard, guardsize, PROT_NONE) != 0) + { + int err; + mprot_error: + err = errno; + + lll_lock (stack_cache_lock, LLL_PRIVATE); + + /* Remove the thread from the list. */ + stack_list_del (&pd->list); + + lll_unlock (stack_cache_lock, LLL_PRIVATE); + + /* Get rid of the TLS block we allocated. */ + _dl_deallocate_tls (TLS_TPADJ (pd), false); + + /* Free the stack memory regardless of whether the size + of the cache is over the limit or not. If this piece + of memory caused problems we better do not use it + anymore. Uh, and we ignore possible errors. There + is nothing we could do. */ + (void) munmap (mem, size); + + return err; + } + + pd->guardsize = guardsize; + } + else if (__builtin_expect (pd->guardsize - guardsize > size - reqsize, + 0)) + { + /* The old guard area is too large. */ + +#ifdef NEED_SEPARATE_REGISTER_STACK + char *guard = mem + (((size - guardsize) / 2) & ~pagesize_m1); + char *oldguard = mem + (((size - pd->guardsize) / 2) & ~pagesize_m1); + + if (oldguard < guard + && mprotect (oldguard, guard - oldguard, prot) != 0) + goto mprot_error; + + if (mprotect (guard + guardsize, + oldguard + pd->guardsize - guard - guardsize, + prot) != 0) + goto mprot_error; +#elif _STACK_GROWS_DOWN + if (mprotect ((char *) mem + guardsize, pd->guardsize - guardsize, + prot) != 0) + goto mprot_error; +#elif _STACK_GROWS_UP + if (mprotect ((char *) pd - pd->guardsize, + pd->guardsize - guardsize, prot) != 0) + goto mprot_error; +#endif + + pd->guardsize = guardsize; + } + /* The pthread_getattr_np() calls need to get passed the size + requested in the attribute, regardless of how large the + actually used guardsize is. */ + pd->reported_guardsize = guardsize; + } + + /* Initialize the lock. We have to do this unconditionally since the + stillborn thread could be canceled while the lock is taken. */ + pd->lock = LLL_LOCK_INITIALIZER; + + /* The robust mutex lists also need to be initialized + unconditionally because the cleanup for the previous stack owner + might have happened in the kernel. */ + pd->robust_head.futex_offset = (offsetof (pthread_mutex_t, __data.__lock) + - offsetof (pthread_mutex_t, + __data.__list.__next)); + pd->robust_head.list_op_pending = NULL; +#ifdef __PTHREAD_MUTEX_HAVE_PREV + pd->robust_prev = &pd->robust_head; +#endif + pd->robust_head.list = &pd->robust_head; + + /* We place the thread descriptor at the end of the stack. */ + *pdp = pd; + +#if defined(TLS_TCB_AT_TP) + /* The stack begins before the TCB and the static TLS block. */ + stacktop = ((char *) (pd + 1) - __static_tls_size); +#elif defined(TLS_DTV_AT_TP) + stacktop = (char *) (pd - 1); +#endif + +#ifdef NEED_SEPARATE_REGISTER_STACK + *stack = pd->stackblock; + *stacksize = stacktop - *stack; +#elif _STACK_GROWS_DOWN + *stack = stacktop; +#elif _STACK_GROWS_UP + *stack = pd->stackblock; + assert (*stack > 0); +#endif + + return 0; +} + + +void +internal_function +__deallocate_stack (struct pthread *pd) +{ + lll_lock (stack_cache_lock, LLL_PRIVATE); + + /* Remove the thread from the list of threads with user defined + stacks. */ + stack_list_del (&pd->list); + + /* Not much to do. Just free the mmap()ed memory. Note that we do + not reset the 'used' flag in the 'tid' field. This is done by + the kernel. If no thread has been created yet this field is + still zero. */ + if (__builtin_expect (! pd->user_stack, 1)) + (void) queue_stack (pd); + else + /* Free the memory associated with the ELF TLS. */ + _dl_deallocate_tls (TLS_TPADJ (pd), false); + + lll_unlock (stack_cache_lock, LLL_PRIVATE); +} + + +int +internal_function +__make_stacks_executable (void **stack_endp) +{ + /* First the main thread's stack. */ + int err = EPERM; + if (err != 0) + return err; + +#ifdef NEED_SEPARATE_REGISTER_STACK + const size_t pagemask = ~(__getpagesize () - 1); +#endif + + lll_lock (stack_cache_lock, LLL_PRIVATE); + + list_t *runp; + list_for_each (runp, &stack_used) + { + err = change_stack_perm (list_entry (runp, struct pthread, list) +#ifdef NEED_SEPARATE_REGISTER_STACK + , pagemask +#endif + ); + if (err != 0) + break; + } + + /* Also change the permission for the currently unused stacks. This + might be wasted time but better spend it here than adding a check + in the fast path. */ + if (err == 0) + list_for_each (runp, &stack_cache) + { + err = change_stack_perm (list_entry (runp, struct pthread, list) +#ifdef NEED_SEPARATE_REGISTER_STACK + , pagemask +#endif + ); + if (err != 0) + break; + } + + lll_unlock (stack_cache_lock, LLL_PRIVATE); + + return err; +} + + +/* In case of a fork() call the memory allocation in the child will be + the same but only one thread is running. All stacks except that of + the one running thread are not used anymore. We have to recycle + them. */ +void +__reclaim_stacks (void) +{ + struct pthread *self = (struct pthread *) THREAD_SELF; + + /* No locking necessary. The caller is the only stack in use. But + we have to be aware that we might have interrupted a list + operation. */ + + if (in_flight_stack != 0) + { + bool add_p = in_flight_stack & 1; + list_t *elem = (list_t *) (in_flight_stack & ~UINTMAX_C (1)); + + if (add_p) + { + /* We always add at the beginning of the list. So in this + case we only need to check the beginning of these lists. */ + int check_list (list_t *l) + { + if (l->next->prev != l) + { + assert (l->next->prev == elem); + + elem->next = l->next; + elem->prev = l; + l->next = elem; + + return 1; + } + + return 0; + } + + if (check_list (&stack_used) == 0) + (void) check_list (&stack_cache); + } + else + { + /* We can simply always replay the delete operation. */ + elem->next->prev = elem->prev; + elem->prev->next = elem->next; + } + } + + /* Mark all stacks except the still running one as free. */ + list_t *runp; + list_for_each (runp, &stack_used) + { + struct pthread *curp = list_entry (runp, struct pthread, list); + if (curp != self) + { + /* This marks the stack as free. */ + curp->tid = 0; + + /* The PID field must be initialized for the new process. */ + curp->pid = self->pid; + + /* Account for the size of the stack. */ + stack_cache_actsize += curp->stackblock_size; + + if (curp->specific_used) + { + /* Clear the thread-specific data. */ + memset (curp->specific_1stblock, '\0', + sizeof (curp->specific_1stblock)); + + curp->specific_used = false; + + for (size_t cnt = 1; cnt < PTHREAD_KEY_1STLEVEL_SIZE; ++cnt) + if (curp->specific[cnt] != NULL) + { + memset (curp->specific[cnt], '\0', + sizeof (curp->specific_1stblock)); + + /* We have allocated the block which we do not + free here so re-set the bit. */ + curp->specific_used = true; + } + } + } + } + + /* Reset the PIDs in any cached stacks. */ + list_for_each (runp, &stack_cache) + { + struct pthread *curp = list_entry (runp, struct pthread, list); + curp->pid = self->pid; + } + + /* Add the stack of all running threads to the cache. */ + list_splice (&stack_used, &stack_cache); + + /* Remove the entry for the current thread to from the cache list + and add it to the list of running threads. Which of the two + lists is decided by the user_stack flag. */ + stack_list_del (&self->list); + + /* Re-initialize the lists for all the threads. */ + INIT_LIST_HEAD (&stack_used); + INIT_LIST_HEAD (&__stack_user); + + if (__builtin_expect (THREAD_GETMEM (self, user_stack), 0)) + list_add (&self->list, &__stack_user); + else + list_add (&self->list, &stack_used); + + /* There is one thread running. */ + __nptl_nthreads = 1; + + in_flight_stack = 0; + + /* Initialize the lock. */ + stack_cache_lock = LLL_LOCK_INITIALIZER; +} + + +#if HP_TIMING_AVAIL +# undef __find_thread_by_id +/* Find a thread given the thread ID. */ +attribute_hidden +struct pthread * +__find_thread_by_id (pid_t tid) +{ + struct pthread *result = NULL; + + lll_lock (stack_cache_lock, LLL_PRIVATE); + + /* Iterate over the list with system-allocated threads first. */ + list_t *runp; + list_for_each (runp, &stack_used) + { + struct pthread *curp; + + curp = list_entry (runp, struct pthread, list); + + if (curp->tid == tid) + { + result = curp; + goto out; + } + } + + /* Now the list with threads using user-allocated stacks. */ + list_for_each (runp, &__stack_user) + { + struct pthread *curp; + + curp = list_entry (runp, struct pthread, list); + + if (curp->tid == tid) + { + result = curp; + goto out; + } + } + + out: + lll_unlock (stack_cache_lock, LLL_PRIVATE); + + return result; +} +#endif + + +static void +internal_function +setxid_mark_thread (struct xid_command *cmdp, struct pthread *t) +{ + int ch; + + /* Don't let the thread exit before the setxid handler runs. */ + t->setxid_futex = 0; + + do + { + ch = t->cancelhandling; + + /* If the thread is exiting right now, ignore it. */ + if ((ch & EXITING_BITMASK) != 0) + return; + } + while (atomic_compare_and_exchange_bool_acq (&t->cancelhandling, + ch | SETXID_BITMASK, ch)); +} + + +static void +internal_function +setxid_unmark_thread (struct xid_command *cmdp, struct pthread *t) +{ + int ch; + + do + { + ch = t->cancelhandling; + if ((ch & SETXID_BITMASK) == 0) + return; + } + while (atomic_compare_and_exchange_bool_acq (&t->cancelhandling, + ch & ~SETXID_BITMASK, ch)); + + /* Release the futex just in case. */ + t->setxid_futex = 1; + lll_futex_wake (&t->setxid_futex, 1, LLL_PRIVATE); +} + + +static int +internal_function +setxid_signal_thread (struct xid_command *cmdp, struct pthread *t) +{ + if ((t->cancelhandling & SETXID_BITMASK) == 0) + return 0; + + int val; + INTERNAL_SYSCALL_DECL (err); +#if __ASSUME_TGKILL + val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), + t->tid, SIGSETXID); +#else +# ifdef __NR_tgkill + val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), + t->tid, SIGSETXID); + if (INTERNAL_SYSCALL_ERROR_P (val, err) + && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS) +# endif + val = INTERNAL_SYSCALL (tkill, err, 2, t->tid, SIGSETXID); +#endif + + /* If this failed, it must have had not started yet or else exited. */ + if (!INTERNAL_SYSCALL_ERROR_P (val, err)) + { + atomic_increment (&cmdp->cntr); + return 1; + } + else + return 0; +} + + +int +attribute_hidden +__nptl_setxid (struct xid_command *cmdp) +{ + int signalled; + int result; + lll_lock (stack_cache_lock, LLL_PRIVATE); + + __xidcmd = cmdp; + cmdp->cntr = 0; + + 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) + continue; + + setxid_mark_thread (cmdp, t); + } + + /* 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) + continue; + + setxid_mark_thread (cmdp, t); + } + + /* Iterate until we don't succeed in signalling anyone. That means + we have gotten all running threads, and their children will be + automatically correct once started. */ + do + { + signalled = 0; + + list_for_each (runp, &stack_used) + { + struct pthread *t = list_entry (runp, struct pthread, list); + if (t == self) + continue; + + signalled += setxid_signal_thread (cmdp, t); + } + + list_for_each (runp, &__stack_user) + { + struct pthread *t = list_entry (runp, struct pthread, list); + if (t == self) + continue; + + signalled += setxid_signal_thread (cmdp, t); + } + + int cur = cmdp->cntr; + while (cur != 0) + { + lll_futex_wait (&cmdp->cntr, cur, LLL_PRIVATE); + cur = cmdp->cntr; + } + } + while (signalled != 0); + + /* Clean up flags, so that no thread blocks during exit waiting + for a signal which will never come. */ + list_for_each (runp, &stack_used) + { + struct pthread *t = list_entry (runp, struct pthread, list); + if (t == self) + continue; + + setxid_unmark_thread (cmdp, t); + } + + list_for_each (runp, &__stack_user) + { + struct pthread *t = list_entry (runp, struct pthread, list); + if (t == self) + continue; + + setxid_unmark_thread (cmdp, t); + } + + /* This must be last, otherwise the current thread might not have + permissions to send SIGSETXID syscall to the other threads. */ + INTERNAL_SYSCALL_DECL (err); + result = INTERNAL_SYSCALL_NCS (cmdp->syscall_no, err, 3, + cmdp->id[0], cmdp->id[1], cmdp->id[2]); + if (INTERNAL_SYSCALL_ERROR_P (result, err)) + { + __set_errno (INTERNAL_SYSCALL_ERRNO (result, err)); + result = -1; + } + + lll_unlock (stack_cache_lock, LLL_PRIVATE); + return result; +} + +static inline void __attribute__((always_inline)) +init_one_static_tls (struct pthread *curp, struct link_map *map) +{ + dtv_t *dtv = GET_DTV (TLS_TPADJ (curp)); +# if defined(TLS_TCB_AT_TP) + void *dest = (char *) curp - map->l_tls_offset; +# elif defined(TLS_DTV_AT_TP) + void *dest = (char *) curp + map->l_tls_offset + TLS_PRE_TCB_SIZE; +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* Fill in the DTV slot so that a later LD/GD access will find it. */ + dtv[map->l_tls_modid].pointer.val = dest; + dtv[map->l_tls_modid].pointer.is_static = true; + + /* Initialize the memory. */ + memset (mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size), + '\0', map->l_tls_blocksize - map->l_tls_initimage_size); +} + +void +attribute_hidden +__pthread_init_static_tls (struct link_map *map) +{ + lll_lock (stack_cache_lock, LLL_PRIVATE); + + /* Iterate over the list with system-allocated threads first. */ + list_t *runp; + list_for_each (runp, &stack_used) + init_one_static_tls (list_entry (runp, struct pthread, list), map); + + /* Now the list with threads using user-allocated stacks. */ + list_for_each (runp, &__stack_user) + init_one_static_tls (list_entry (runp, struct pthread, list), map); + + lll_unlock (stack_cache_lock, LLL_PRIVATE); +} + + +void +attribute_hidden +__wait_lookup_done (void) +{ + lll_lock (stack_cache_lock, LLL_PRIVATE); + + 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, LLL_PRIVATE); + 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, LLL_PRIVATE); + while (*gscope_flagp == THREAD_GSCOPE_FLAG_WAIT); + } + + lll_unlock (stack_cache_lock, LLL_PRIVATE); +} diff --git a/libpthread/nptl/banner.h b/libpthread/nptl/banner.h new file mode 100644 index 000000000..9982f4287 --- /dev/null +++ b/libpthread/nptl/banner.h @@ -0,0 +1 @@ +"Native POSIX Threads Library by Ulrich Drepper et al, uClibc port by Steven Hill\n" diff --git a/libpthread/nptl/cancellation.c b/libpthread/nptl/cancellation.c new file mode 100644 index 000000000..eac7973db --- /dev/null +++ b/libpthread/nptl/cancellation.c @@ -0,0 +1,100 @@ +/* Copyright (C) 2002, 2003, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <setjmp.h> +#include <stdlib.h> +#include "pthreadP.h" + + +/* The next two functions are similar to pthread_setcanceltype() but + more specialized for the use in the cancelable functions like write(). + They do not need to check parameters etc. */ +int +attribute_hidden +__pthread_enable_asynccancel (void) +{ + struct pthread *self = THREAD_SELF; + int oldval = THREAD_GETMEM (self, cancelhandling); + + while (1) + { + int newval = oldval | CANCELTYPE_BITMASK; + + if (newval == oldval) + break; + + int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval, + oldval); + if (__builtin_expect (curval == oldval, 1)) + { + if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval)) + { + THREAD_SETMEM (self, result, PTHREAD_CANCELED); + __do_cancel (); + } + + break; + } + + /* Prepare the next round. */ + oldval = curval; + } + + return oldval; +} + + +void +internal_function attribute_hidden +__pthread_disable_asynccancel (int oldtype) +{ + /* If asynchronous cancellation was enabled before we do not have + anything to do. */ + if (oldtype & CANCELTYPE_BITMASK) + return; + + struct pthread *self = THREAD_SELF; + int newval; + + int oldval = THREAD_GETMEM (self, cancelhandling); + + while (1) + { + newval = oldval & ~CANCELTYPE_BITMASK; + + int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval, + oldval); + if (__builtin_expect (curval == oldval, 1)) + break; + + /* Prepare the next round. */ + oldval = curval; + } + + /* We cannot return when we are being canceled. Upon return the + thread might be things which would have to be undone. The + following loop should loop until the cancellation signal is + delivered. */ + while (__builtin_expect ((newval & (CANCELING_BITMASK | CANCELED_BITMASK)) + == CANCELING_BITMASK, 0)) + { + lll_futex_wait (&self->cancelhandling, newval, LLL_PRIVATE); + newval = THREAD_GETMEM (self, cancelhandling); + } +} diff --git a/libpthread/nptl/cleanup.c b/libpthread/nptl/cleanup.c new file mode 100644 index 000000000..af828c49f --- /dev/null +++ b/libpthread/nptl/cleanup.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stdlib.h> +#include "pthreadP.h" + + +void +__cleanup_fct_attribute +__pthread_register_cancel (__pthread_unwind_buf_t *buf) +{ + struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf; + struct pthread *self = THREAD_SELF; + + /* Store old info. */ + ibuf->priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf); + ibuf->priv.data.cleanup = THREAD_GETMEM (self, cleanup); + + /* Store the new cleanup handler info. */ + THREAD_SETMEM (self, cleanup_jmp_buf, (struct pthread_unwind_buf *) buf); +} +hidden_def (__pthread_register_cancel) + + +void +__cleanup_fct_attribute +__pthread_unregister_cancel (__pthread_unwind_buf_t *buf) +{ + struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf; + + THREAD_SETMEM (THREAD_SELF, cleanup_jmp_buf, ibuf->priv.data.prev); +} +hidden_def (__pthread_unregister_cancel) diff --git a/libpthread/nptl/cleanup_compat.c b/libpthread/nptl/cleanup_compat.c new file mode 100644 index 000000000..77d714f7f --- /dev/null +++ b/libpthread/nptl/cleanup_compat.c @@ -0,0 +1,55 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stdlib.h> +#include "pthreadP.h" + + +void +_pthread_cleanup_push ( + struct _pthread_cleanup_buffer *buffer, + void (*routine) (void *), + void *arg) +{ + struct pthread *self = THREAD_SELF; + + buffer->__routine = routine; + buffer->__arg = arg; + buffer->__prev = THREAD_GETMEM (self, cleanup); + + THREAD_SETMEM (self, cleanup, buffer); +} +strong_alias (_pthread_cleanup_push, __pthread_cleanup_push) + + +void +_pthread_cleanup_pop ( + struct _pthread_cleanup_buffer *buffer, + int execute) +{ + struct pthread *self __attribute ((unused)) = THREAD_SELF; + + THREAD_SETMEM (self, cleanup, buffer->__prev); + + /* If necessary call the cleanup routine after we removed the + current cleanup block from the list. */ + if (execute) + buffer->__routine (buffer->__arg); +} +strong_alias (_pthread_cleanup_pop, __pthread_cleanup_pop) diff --git a/libpthread/nptl/cleanup_defer.c b/libpthread/nptl/cleanup_defer.c new file mode 100644 index 000000000..498d9557d --- /dev/null +++ b/libpthread/nptl/cleanup_defer.c @@ -0,0 +1,92 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stdlib.h> +#include "pthreadP.h" + + +void +__cleanup_fct_attribute +__pthread_register_cancel_defer (__pthread_unwind_buf_t *buf) +{ + struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf; + struct pthread *self = THREAD_SELF; + + /* Store old info. */ + ibuf->priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf); + ibuf->priv.data.cleanup = THREAD_GETMEM (self, cleanup); + + int cancelhandling = THREAD_GETMEM (self, cancelhandling); + + /* Disable asynchronous cancellation for now. */ + if (__builtin_expect (cancelhandling & CANCELTYPE_BITMASK, 0)) + while (1) + { + int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, + cancelhandling + & ~CANCELTYPE_BITMASK, + cancelhandling); + if (__builtin_expect (curval == cancelhandling, 1)) + /* Successfully replaced the value. */ + break; + + /* Prepare for the next round. */ + cancelhandling = curval; + } + + ibuf->priv.data.canceltype = (cancelhandling & CANCELTYPE_BITMASK + ? PTHREAD_CANCEL_ASYNCHRONOUS + : PTHREAD_CANCEL_DEFERRED); + + /* Store the new cleanup handler info. */ + THREAD_SETMEM (self, cleanup_jmp_buf, (struct pthread_unwind_buf *) buf); +} + + +void +__cleanup_fct_attribute +__pthread_unregister_cancel_restore (__pthread_unwind_buf_t *buf) +{ + struct pthread *self = THREAD_SELF; + struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf; + + THREAD_SETMEM (self, cleanup_jmp_buf, ibuf->priv.data.prev); + + int cancelhandling; + if (ibuf->priv.data.canceltype != PTHREAD_CANCEL_DEFERRED + && ((cancelhandling = THREAD_GETMEM (self, cancelhandling)) + & CANCELTYPE_BITMASK) == 0) + { + while (1) + { + int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, + cancelhandling + | CANCELTYPE_BITMASK, + cancelhandling); + if (__builtin_expect (curval == cancelhandling, 1)) + /* Successfully replaced the value. */ + break; + + /* Prepare for the next round. */ + cancelhandling = curval; + } + + CANCELLATION_P (self); + } +} diff --git a/libpthread/nptl/cleanup_defer_compat.c b/libpthread/nptl/cleanup_defer_compat.c new file mode 100644 index 000000000..cc6889332 --- /dev/null +++ b/libpthread/nptl/cleanup_defer_compat.c @@ -0,0 +1,100 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +void +attribute_hidden +_pthread_cleanup_push_defer ( + struct _pthread_cleanup_buffer *buffer, + void (*routine) (void *), + void *arg) +{ + struct pthread *self = THREAD_SELF; + + buffer->__routine = routine; + buffer->__arg = arg; + buffer->__prev = THREAD_GETMEM (self, cleanup); + + int cancelhandling = THREAD_GETMEM (self, cancelhandling); + + /* Disable asynchronous cancellation for now. */ + if (__builtin_expect (cancelhandling & CANCELTYPE_BITMASK, 0)) + while (1) + { + int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, + cancelhandling + & ~CANCELTYPE_BITMASK, + cancelhandling); + if (__builtin_expect (curval == cancelhandling, 1)) + /* Successfully replaced the value. */ + break; + + /* Prepare for the next round. */ + cancelhandling = curval; + } + + buffer->__canceltype = (cancelhandling & CANCELTYPE_BITMASK + ? PTHREAD_CANCEL_ASYNCHRONOUS + : PTHREAD_CANCEL_DEFERRED); + + THREAD_SETMEM (self, cleanup, buffer); +} +strong_alias (_pthread_cleanup_push_defer, __pthread_cleanup_push_defer) + + +void +attribute_hidden +_pthread_cleanup_pop_restore ( + struct _pthread_cleanup_buffer *buffer, + int execute) +{ + struct pthread *self = THREAD_SELF; + + THREAD_SETMEM (self, cleanup, buffer->__prev); + + int cancelhandling; + if (__builtin_expect (buffer->__canceltype != PTHREAD_CANCEL_DEFERRED, 0) + && ((cancelhandling = THREAD_GETMEM (self, cancelhandling)) + & CANCELTYPE_BITMASK) == 0) + { + while (1) + { + int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, + cancelhandling + | CANCELTYPE_BITMASK, + cancelhandling); + if (__builtin_expect (curval == cancelhandling, 1)) + /* Successfully replaced the value. */ + break; + + /* Prepare for the next round. */ + cancelhandling = curval; + } + + CANCELLATION_P (self); + } + + /* If necessary call the cleanup routine after we removed the + current cleanup block from the list. */ + if (execute) + buffer->__routine (buffer->__arg); +} +strong_alias (_pthread_cleanup_pop_restore, __pthread_cleanup_pop_restore) diff --git a/libpthread/nptl/cleanup_routine.c b/libpthread/nptl/cleanup_routine.c new file mode 100644 index 000000000..cbf231834 --- /dev/null +++ b/libpthread/nptl/cleanup_routine.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 <pthread.h> + + +void +__pthread_cleanup_routine (struct __pthread_cleanup_frame *f) +{ + if (f->__do_it) + f->__cancel_routine (f->__cancel_arg); +} diff --git a/libpthread/nptl/descr.h b/libpthread/nptl/descr.h new file mode 100644 index 000000000..40f552d6d --- /dev/null +++ b/libpthread/nptl/descr.h @@ -0,0 +1,377 @@ +/* Copyright (C) 2002-2006, 2007, 2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _DESCR_H +#define _DESCR_H 1 + +#include <limits.h> +#include <sched.h> +#include <setjmp.h> +#include <stdbool.h> +#include <sys/types.h> +#include <hp-timing.h> +#include <list.h> +#include <lowlevellock.h> +#include <pthreaddef.h> +#include "../nptl_db/thread_db.h" +#include <tls.h> +#ifdef HAVE_FORCED_UNWIND +# include <unwind.h> +#endif +#define __need_res_state +#include <resolv.h> +#include <bits/kernel-features.h> +#include "uClibc-glue.h" + +#ifndef TCB_ALIGNMENT +# define TCB_ALIGNMENT sizeof (double) +#endif + + +/* We keep thread specific data in a special data structure, a two-level + array. The top-level array contains pointers to dynamically allocated + arrays of a certain number of data pointers. So we can implement a + sparse array. Each dynamic second-level array has + PTHREAD_KEY_2NDLEVEL_SIZE + entries. This value shouldn't be too large. */ +#define PTHREAD_KEY_2NDLEVEL_SIZE 32 + +/* We need to address PTHREAD_KEYS_MAX key with PTHREAD_KEY_2NDLEVEL_SIZE + keys in each subarray. */ +#define PTHREAD_KEY_1STLEVEL_SIZE \ + ((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1) \ + / PTHREAD_KEY_2NDLEVEL_SIZE) + + + + +/* Internal version of the buffer to store cancellation handler + information. */ +struct pthread_unwind_buf +{ + struct + { + __jmp_buf jmp_buf; + int mask_was_saved; + } cancel_jmp_buf[1]; + + union + { + /* This is the placeholder of the public version. */ + void *pad[4]; + + struct + { + /* Pointer to the previous cleanup buffer. */ + struct pthread_unwind_buf *prev; + + /* Backward compatibility: state of the old-style cleanup + handler at the time of the previous new-style cleanup handler + installment. */ + struct _pthread_cleanup_buffer *cleanup; + + /* Cancellation type before the push call. */ + int canceltype; + } data; + } priv; +}; + + +/* Opcodes and data types for communication with the signal handler to + change user/group IDs. */ +struct xid_command +{ + int syscall_no; + long int id[3]; + volatile int cntr; +}; + + +/* Data structure used by the kernel to find robust futexes. */ +struct robust_list_head +{ + void *list; + long int futex_offset; + void *list_op_pending; +}; + + +/* Data strcture used to handle thread priority protection. */ +struct priority_protection_data +{ + int priomax; + unsigned int priomap[]; +}; + + +/* Thread descriptor data structure. */ +struct pthread +{ + union + { +#if !defined(TLS_DTV_AT_TP) + /* This overlaps the TCB as used for TLS without threads (see tls.h). */ + tcbhead_t header; +#else + struct + { + int multiple_threads; + int gscope_flag; +# ifndef __ASSUME_PRIVATE_FUTEX + int private_futex; +# endif + } header; +#endif + + /* This extra padding has no special purpose, and this structure layout + is private and subject to change without affecting the official ABI. + We just have it here in case it might be convenient for some + implementation-specific instrumentation hack or suchlike. */ + void *__padding[24]; + }; + + /* This descriptor's link on the `stack_used' or `__stack_user' list. */ + list_t list; + + /* Thread ID - which is also a 'is this thread descriptor (and + therefore stack) used' flag. */ + pid_t tid; + + /* Process ID - thread group ID in kernel speak. */ + pid_t pid; + + /* List of robust mutexes the thread is holding. */ +#ifdef __PTHREAD_MUTEX_HAVE_PREV + void *robust_prev; + struct robust_list_head robust_head; + + /* The list above is strange. It is basically a double linked list + but the pointer to the next/previous element of the list points + in the middle of the object, the __next element. Whenever + casting to __pthread_list_t we need to adjust the pointer + first. */ +# define QUEUE_PTR_ADJUST (offsetof (__pthread_list_t, __next)) + +# define ENQUEUE_MUTEX_BOTH(mutex, val) \ + do { \ + __pthread_list_t *next = (__pthread_list_t *) \ + ((((uintptr_t) THREAD_GETMEM (THREAD_SELF, robust_head.list)) & ~1ul) \ + - QUEUE_PTR_ADJUST); \ + next->__prev = (void *) &mutex->__data.__list.__next; \ + mutex->__data.__list.__next = THREAD_GETMEM (THREAD_SELF, \ + robust_head.list); \ + mutex->__data.__list.__prev = (void *) &THREAD_SELF->robust_head; \ + THREAD_SETMEM (THREAD_SELF, robust_head.list, \ + (void *) (((uintptr_t) &mutex->__data.__list.__next) \ + | val)); \ + } while (0) +# define DEQUEUE_MUTEX(mutex) \ + do { \ + __pthread_list_t *next = (__pthread_list_t *) \ + ((char *) (((uintptr_t) mutex->__data.__list.__next) & ~1ul) \ + - QUEUE_PTR_ADJUST); \ + next->__prev = mutex->__data.__list.__prev; \ + __pthread_list_t *prev = (__pthread_list_t *) \ + ((char *) (((uintptr_t) mutex->__data.__list.__prev) & ~1ul) \ + - QUEUE_PTR_ADJUST); \ + prev->__next = mutex->__data.__list.__next; \ + mutex->__data.__list.__prev = NULL; \ + mutex->__data.__list.__next = NULL; \ + } while (0) +#else + union + { + __pthread_slist_t robust_list; + struct robust_list_head robust_head; + }; + +# define ENQUEUE_MUTEX_BOTH(mutex, val) \ + do { \ + mutex->__data.__list.__next \ + = THREAD_GETMEM (THREAD_SELF, robust_list.__next); \ + THREAD_SETMEM (THREAD_SELF, robust_list.__next, \ + (void *) (((uintptr_t) &mutex->__data.__list) | val)); \ + } while (0) +# define DEQUEUE_MUTEX(mutex) \ + do { \ + __pthread_slist_t *runp = (__pthread_slist_t *) \ + (((uintptr_t) THREAD_GETMEM (THREAD_SELF, robust_list.__next)) & ~1ul); \ + if (runp == &mutex->__data.__list) \ + THREAD_SETMEM (THREAD_SELF, robust_list.__next, runp->__next); \ + else \ + { \ + __pthread_slist_t *next = (__pthread_slist_t *) \ + (((uintptr_t) runp->__next) & ~1ul); \ + while (next != &mutex->__data.__list) \ + { \ + runp = next; \ + next = (__pthread_slist_t *) (((uintptr_t) runp->__next) & ~1ul); \ + } \ + \ + runp->__next = next->__next; \ + mutex->__data.__list.__next = NULL; \ + } \ + } while (0) +#endif +#define ENQUEUE_MUTEX(mutex) ENQUEUE_MUTEX_BOTH (mutex, 0) +#define ENQUEUE_MUTEX_PI(mutex) ENQUEUE_MUTEX_BOTH (mutex, 1) + + /* List of cleanup buffers. */ + struct _pthread_cleanup_buffer *cleanup; + + /* Unwind information. */ + struct pthread_unwind_buf *cleanup_jmp_buf; +#define HAVE_CLEANUP_JMP_BUF + + /* Flags determining processing of cancellation. */ + int cancelhandling; + /* Bit set if cancellation is disabled. */ +#define CANCELSTATE_BIT 0 +#define CANCELSTATE_BITMASK (0x01 << CANCELSTATE_BIT) + /* Bit set if asynchronous cancellation mode is selected. */ +#define CANCELTYPE_BIT 1 +#define CANCELTYPE_BITMASK (0x01 << CANCELTYPE_BIT) + /* Bit set if canceling has been initiated. */ +#define CANCELING_BIT 2 +#define CANCELING_BITMASK (0x01 << CANCELING_BIT) + /* Bit set if canceled. */ +#define CANCELED_BIT 3 +#define CANCELED_BITMASK (0x01 << CANCELED_BIT) + /* Bit set if thread is exiting. */ +#define EXITING_BIT 4 +#define EXITING_BITMASK (0x01 << EXITING_BIT) + /* Bit set if thread terminated and TCB is freed. */ +#define TERMINATED_BIT 5 +#define TERMINATED_BITMASK (0x01 << TERMINATED_BIT) + /* Bit set if thread is supposed to change XID. */ +#define SETXID_BIT 6 +#define SETXID_BITMASK (0x01 << SETXID_BIT) + /* Mask for the rest. Helps the compiler to optimize. */ +#define CANCEL_RESTMASK 0xffffff80 + +#define CANCEL_ENABLED_AND_CANCELED(value) \ + (((value) & (CANCELSTATE_BITMASK | CANCELED_BITMASK | EXITING_BITMASK \ + | CANCEL_RESTMASK | TERMINATED_BITMASK)) == CANCELED_BITMASK) +#define CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS(value) \ + (((value) & (CANCELSTATE_BITMASK | CANCELTYPE_BITMASK | CANCELED_BITMASK \ + | EXITING_BITMASK | CANCEL_RESTMASK | TERMINATED_BITMASK)) \ + == (CANCELTYPE_BITMASK | CANCELED_BITMASK)) + + /* Flags. Including those copied from the thread attribute. */ + int flags; + + /* We allocate one block of references here. This should be enough + to avoid allocating any memory dynamically for most applications. */ + struct pthread_key_data + { + /* Sequence number. We use uintptr_t to not require padding on + 32- and 64-bit machines. On 64-bit machines it helps to avoid + wrapping, too. */ + uintptr_t seq; + + /* Data pointer. */ + void *data; + } specific_1stblock[PTHREAD_KEY_2NDLEVEL_SIZE]; + + /* Two-level array for the thread-specific data. */ + struct pthread_key_data *specific[PTHREAD_KEY_1STLEVEL_SIZE]; + + /* Flag which is set when specific data is set. */ + bool specific_used; + + /* True if events must be reported. */ + bool report_events; + + /* True if the user provided the stack. */ + bool user_stack; + + /* True if thread must stop at startup time. */ + bool stopped_start; + + /* The parent's cancel handling at the time of the pthread_create + call. This might be needed to undo the effects of a cancellation. */ + int parent_cancelhandling; + + /* Lock to synchronize access to the descriptor. */ + int lock; + + /* Lock for synchronizing setxid calls. */ + int setxid_futex; + +#if HP_TIMING_AVAIL + /* Offset of the CPU clock at start thread start time. */ + hp_timing_t cpuclock_offset; +#endif + + /* If the thread waits to join another one the ID of the latter is + stored here. + + In case a thread is detached this field contains a pointer of the + TCB if the thread itself. This is something which cannot happen + in normal operation. */ + struct pthread *joinid; + /* Check whether a thread is detached. */ +#define IS_DETACHED(pd) ((pd)->joinid == (pd)) + + /* The result of the thread function. */ + void *result; + + /* Scheduling parameters for the new thread. */ + struct sched_param schedparam; + int schedpolicy; + + /* Start position of the code to be executed and the argument passed + to the function. */ + void *(*start_routine) (void *); + void *arg; + + /* Debug state. */ + td_eventbuf_t eventbuf; + /* Next descriptor with a pending event. */ + struct pthread *nextevent; + +#ifdef HAVE_FORCED_UNWIND + /* Machine-specific unwind info. */ + struct _Unwind_Exception exc; +#endif + + /* If nonzero pointer to area allocated for the stack and its + size. */ + void *stackblock; + size_t stackblock_size; + /* Size of the included guard area. */ + size_t guardsize; + /* This is what the user specified and what we will report. */ + size_t reported_guardsize; + + /* Thread Priority Protection data. */ + struct priority_protection_data *tpp; + + /* Resolver state. */ + struct __res_state res; + + /* This member must be last. */ + char end_padding[]; + +#define PTHREAD_STRUCT_END_PADDING \ + (sizeof (struct pthread) - offsetof (struct pthread, end_padding)) +} __attribute ((aligned (TCB_ALIGNMENT))); + + +#endif /* descr.h */ diff --git a/libpthread/nptl/eintr.c b/libpthread/nptl/eintr.c new file mode 100644 index 000000000..933c5d81b --- /dev/null +++ b/libpthread/nptl/eintr.c @@ -0,0 +1,89 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 <pthread.h> +#include <signal.h> +#include <unistd.h> + + +static int the_sig; + + +static void +eintr_handler (int sig) +{ + if (sig != the_sig) + { + write (STDOUT_FILENO, "eintr_handler: signal number wrong\n", 35); + _exit (1); + } + write (STDOUT_FILENO, ".", 1); +} + + +static void * +eintr_source (void *arg) +{ + struct timespec ts = { .tv_sec = 0, .tv_nsec = 500000 }; + + if (arg == NULL) + { + sigset_t ss; + sigemptyset (&ss); + sigaddset (&ss, the_sig); + pthread_sigmask (SIG_BLOCK, &ss, NULL); + } + + while (1) + { + if (arg != NULL) + pthread_kill (*(pthread_t *) arg, the_sig); + else + kill (getpid (), the_sig); + + nanosleep (&ts, NULL); + } + + /* NOTREACHED */ + return NULL; +} + + +static void +setup_eintr (int sig, pthread_t *thp) +{ + struct sigaction sa; + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = eintr_handler; + if (sigaction (sig, &sa, NULL) != 0) + { + puts ("setup_eintr: sigaction failed"); + exit (1); + } + the_sig = sig; + + /* Create the thread which will fire off the signals. */ + pthread_t th; + if (pthread_create (&th, NULL, eintr_source, thp) != 0) + { + puts ("setup_eintr: pthread_create failed"); + exit (1); + } +} diff --git a/libpthread/nptl/events.c b/libpthread/nptl/events.c new file mode 100644 index 000000000..df97e54f6 --- /dev/null +++ b/libpthread/nptl/events.c @@ -0,0 +1,34 @@ +/* Event functions used while debugging. + Copyright (C) 1999, 2000, 2002 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 functions contained here do nothing, they just return. */ + +#include "pthreadP.h" + +void +__nptl_create_event (void) +{ +} +hidden_def (__nptl_create_event) + +void +__nptl_death_event (void) +{ +} +hidden_def (__nptl_death_event) diff --git a/libpthread/nptl/forward.c b/libpthread/nptl/forward.c new file mode 100644 index 000000000..8f528d0a8 --- /dev/null +++ b/libpthread/nptl/forward.c @@ -0,0 +1,153 @@ +/* Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <dlfcn.h> +#include <pthreadP.h> +#include <signal.h> +#include <stdlib.h> + +#include <atomic.h> +#include <sysdep.h> + + +/* Pointers to the libc functions. */ +struct pthread_functions __libc_pthread_functions attribute_hidden; +int __libc_pthread_functions_init attribute_hidden; + + +#define FORWARD2(name, rettype, decl, params, defaction) \ +rettype \ +name decl \ +{ \ + if (!__libc_pthread_functions_init) \ + defaction; \ + \ + return PTHFCT_CALL (ptr_##name, params); \ +} + +#define FORWARD(name, decl, params, defretval) \ + FORWARD2 (name, int, decl, params, return defretval) + + +FORWARD (pthread_attr_destroy, (pthread_attr_t *attr), (attr), 0) + +FORWARD (__pthread_attr_init_2_1, (pthread_attr_t *attr), (attr), 0) +weak_alias(__pthread_attr_init_2_1, pthread_attr_init) + +FORWARD (pthread_attr_getdetachstate, + (const pthread_attr_t *attr, int *detachstate), (attr, detachstate), + 0) +FORWARD (pthread_attr_setdetachstate, (pthread_attr_t *attr, int detachstate), + (attr, detachstate), 0) + +FORWARD (pthread_attr_getinheritsched, + (const pthread_attr_t *attr, int *inherit), (attr, inherit), 0) +FORWARD (pthread_attr_setinheritsched, (pthread_attr_t *attr, int inherit), + (attr, inherit), 0) + +FORWARD (pthread_attr_getschedparam, + (const pthread_attr_t *attr, struct sched_param *param), + (attr, param), 0) +FORWARD (pthread_attr_setschedparam, + (pthread_attr_t *attr, const struct sched_param *param), + (attr, param), 0) + +FORWARD (pthread_attr_getschedpolicy, + (const pthread_attr_t *attr, int *policy), (attr, policy), 0) +FORWARD (pthread_attr_setschedpolicy, (pthread_attr_t *attr, int policy), + (attr, policy), 0) + +FORWARD (pthread_attr_getscope, + (const pthread_attr_t *attr, int *scope), (attr, scope), 0) +FORWARD (pthread_attr_setscope, (pthread_attr_t *attr, int scope), + (attr, scope), 0) + + +FORWARD (pthread_condattr_destroy, (pthread_condattr_t *attr), (attr), 0) +FORWARD (pthread_condattr_init, (pthread_condattr_t *attr), (attr), 0) + +FORWARD (__pthread_cond_broadcast, (pthread_cond_t *cond), (cond), 0) +weak_alias(__pthread_cond_broadcast, pthread_cond_broadcast) + +FORWARD (__pthread_cond_destroy, (pthread_cond_t *cond), (cond), 0) +weak_alias(__pthread_cond_destroy, pthread_cond_destroy) + +FORWARD (__pthread_cond_init, + (pthread_cond_t *cond, const pthread_condattr_t *cond_attr), + (cond, cond_attr), 0) +weak_alias(__pthread_cond_init, pthread_cond_init) + +FORWARD (__pthread_cond_signal, (pthread_cond_t *cond), (cond), 0) +weak_alias(__pthread_cond_signal, pthread_cond_signal) + +FORWARD (__pthread_cond_wait, (pthread_cond_t *cond, pthread_mutex_t *mutex), + (cond, mutex), 0) +weak_alias(__pthread_cond_wait, pthread_cond_wait) + +FORWARD (__pthread_cond_timedwait, + (pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime), (cond, mutex, abstime), 0) +weak_alias(__pthread_cond_timedwait, pthread_cond_timedwait) + + +FORWARD (pthread_equal, (pthread_t thread1, pthread_t thread2), + (thread1, thread2), 1) + + +/* Use an alias to avoid warning, as pthread_exit is declared noreturn. */ +FORWARD2 (__pthread_exit, void, (void *retval), (retval), exit (EXIT_SUCCESS)) +strong_alias (__pthread_exit, pthread_exit); + + +FORWARD (pthread_getschedparam, + (pthread_t target_thread, int *policy, struct sched_param *param), + (target_thread, policy, param), 0) +FORWARD (pthread_setschedparam, + (pthread_t target_thread, int policy, + const struct sched_param *param), (target_thread, policy, param), 0) + + +FORWARD (pthread_mutex_destroy, (pthread_mutex_t *mutex), (mutex), 0) + +FORWARD (pthread_mutex_init, + (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr), + (mutex, mutexattr), 0) + +FORWARD (pthread_mutex_lock, (pthread_mutex_t *mutex), (mutex), 0) + +FORWARD (pthread_mutex_unlock, (pthread_mutex_t *mutex), (mutex), 0) + + +FORWARD2 (pthread_self, pthread_t, (void), (), return 0) + + +FORWARD (pthread_setcancelstate, (int state, int *oldstate), (state, oldstate), + 0) + +FORWARD (pthread_setcanceltype, (int type, int *oldtype), (type, oldtype), 0) + +#define return /* value is void */ +FORWARD2(__pthread_unwind, + void attribute_hidden __attribute ((noreturn)) __cleanup_fct_attribute, + (__pthread_unwind_buf_t *buf), (buf), { + /* We cannot call abort() here. */ + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (kill, err, 1, SIGKILL); + }) +#undef return diff --git a/libpthread/nptl/herrno.c b/libpthread/nptl/herrno.c new file mode 100644 index 000000000..6e8339d43 --- /dev/null +++ b/libpthread/nptl/herrno.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1996,97,98,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <features.h> +#include <netdb.h> +#undef h_errno + +#include <tls.h> + +/* We need to have the error status variable of the resolver + accessible in the libc. */ +extern __thread int h_errno; + + +/* When threaded, h_errno may be a per-thread variable. */ +int * +__h_errno_location (void) +{ + return &h_errno; +} diff --git a/libpthread/nptl/init.c b/libpthread/nptl/init.c new file mode 100644 index 000000000..44f2c86f1 --- /dev/null +++ b/libpthread/nptl/init.c @@ -0,0 +1,440 @@ +/* Copyright (C) 2002-2007, 2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <signal.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/param.h> +#include <sys/resource.h> +#include <pthreadP.h> +#include <atomic.h> +#include <ldsodefs.h> +#include <tls.h> +#include <fork.h> +#include <version.h> +#include <smp.h> +#include <lowlevellock.h> +#include <bits/kernel-features.h> + +#include <stdio.h> + +/* Size and alignment of static TLS block. */ +size_t __static_tls_size; +size_t __static_tls_align_m1; + +#ifndef __ASSUME_SET_ROBUST_LIST +/* Negative if we do not have the system call and we can use it. */ +int __set_robust_list_avail; +# define set_robust_list_not_avail() \ + __set_robust_list_avail = -1 +#else +# define set_robust_list_not_avail() do { } while (0) +#endif + +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +/* Nonzero if we do not have FUTEX_CLOCK_REALTIME. */ +int __have_futex_clock_realtime; +# define __set_futex_clock_realtime() \ + __have_futex_clock_realtime = 1 +#else +#define __set_futex_clock_realtime() do { } while (0) +#endif + +/* Version of the library, used in libthread_db to detect mismatches. */ +static const char nptl_version[] __attribute_used__ = VERSION; + + +#ifndef SHARED +extern void __libc_setup_tls (size_t tcbsize, size_t tcbalign); +#endif + +#ifdef SHARED +static void nptl_freeres (void); + + +static const struct pthread_functions pthread_functions = + { + .ptr_pthread_attr_destroy = __pthread_attr_destroy, + .ptr___pthread_attr_init_2_1 = __pthread_attr_init_2_1, + .ptr_pthread_attr_getdetachstate = __pthread_attr_getdetachstate, + .ptr_pthread_attr_setdetachstate = __pthread_attr_setdetachstate, + .ptr_pthread_attr_getinheritsched = __pthread_attr_getinheritsched, + .ptr_pthread_attr_setinheritsched = __pthread_attr_setinheritsched, + .ptr_pthread_attr_getschedparam = __pthread_attr_getschedparam, + .ptr_pthread_attr_setschedparam = __pthread_attr_setschedparam, + .ptr_pthread_attr_getschedpolicy = __pthread_attr_getschedpolicy, + .ptr_pthread_attr_setschedpolicy = __pthread_attr_setschedpolicy, + .ptr_pthread_attr_getscope = __pthread_attr_getscope, + .ptr_pthread_attr_setscope = __pthread_attr_setscope, + .ptr_pthread_condattr_destroy = __pthread_condattr_destroy, + .ptr_pthread_condattr_init = __pthread_condattr_init, + .ptr___pthread_cond_broadcast = __pthread_cond_broadcast, + .ptr___pthread_cond_destroy = __pthread_cond_destroy, + .ptr___pthread_cond_init = __pthread_cond_init, + .ptr___pthread_cond_signal = __pthread_cond_signal, + .ptr___pthread_cond_wait = __pthread_cond_wait, + .ptr___pthread_cond_timedwait = __pthread_cond_timedwait, + .ptr_pthread_equal = __pthread_equal, + .ptr___pthread_exit = __pthread_exit, + .ptr_pthread_getschedparam = __pthread_getschedparam, + .ptr_pthread_setschedparam = __pthread_setschedparam, + .ptr_pthread_mutex_destroy = INTUSE(__pthread_mutex_destroy), + .ptr_pthread_mutex_init = INTUSE(__pthread_mutex_init), + .ptr_pthread_mutex_lock = INTUSE(__pthread_mutex_lock), + .ptr_pthread_mutex_unlock = INTUSE(__pthread_mutex_unlock), + .ptr_pthread_self = __pthread_self, + .ptr_pthread_setcancelstate = __pthread_setcancelstate, + .ptr_pthread_setcanceltype = __pthread_setcanceltype, + .ptr___pthread_cleanup_upto = __pthread_cleanup_upto, + .ptr___pthread_once = __pthread_once_internal, + .ptr___pthread_rwlock_rdlock = __pthread_rwlock_rdlock_internal, + .ptr___pthread_rwlock_wrlock = __pthread_rwlock_wrlock_internal, + .ptr___pthread_rwlock_unlock = __pthread_rwlock_unlock_internal, + .ptr___pthread_key_create = __pthread_key_create_internal, + .ptr___pthread_getspecific = __pthread_getspecific_internal, + .ptr___pthread_setspecific = __pthread_setspecific_internal, + .ptr__pthread_cleanup_push_defer = _pthread_cleanup_push_defer, + .ptr__pthread_cleanup_pop_restore = _pthread_cleanup_pop_restore, + .ptr_nthreads = &__nptl_nthreads, + .ptr___pthread_unwind = &__pthread_unwind, + .ptr__nptl_deallocate_tsd = __nptl_deallocate_tsd, + .ptr__nptl_setxid = __nptl_setxid, + /* For now only the stack cache needs to be freed. */ + .ptr_freeres = nptl_freeres + }; +# define ptr_pthread_functions &pthread_functions +#else +# define ptr_pthread_functions NULL +#endif + + +#ifdef SHARED +/* This function is called indirectly from the freeres code in libc. */ +static void +__libc_freeres_fn_section +nptl_freeres (void) +{ + __unwind_freeres (); + __free_stacks (0); +} +#endif + + +/* For asynchronous cancellation we use a signal. This is the handler. */ +static void +sigcancel_handler (int sig, siginfo_t *si, void *ctx) +{ +#ifdef __ASSUME_CORRECT_SI_PID + /* Determine the process ID. It might be negative if the thread is + in the middle of a fork() call. */ + pid_t pid = THREAD_GETMEM (THREAD_SELF, pid); + if (__builtin_expect (pid < 0, 0)) + pid = -pid; +#endif + + /* Safety check. It would be possible to call this function for + other signals and send a signal from another process. This is not + correct and might even be a security problem. Try to catch as + many incorrect invocations as possible. */ + if (sig != SIGCANCEL +#ifdef __ASSUME_CORRECT_SI_PID + /* Kernels before 2.5.75 stored the thread ID and not the process + ID in si_pid so we skip this test. */ + || si->si_pid != pid +#endif + || si->si_code != SI_TKILL) + return; + + struct pthread *self = THREAD_SELF; + + int oldval = THREAD_GETMEM (self, cancelhandling); + while (1) + { + /* We are canceled now. When canceled by another thread this flag + is already set but if the signal is directly send (internally or + from another process) is has to be done here. */ + int newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK; + + if (oldval == newval || (oldval & EXITING_BITMASK) != 0) + /* Already canceled or exiting. */ + break; + + int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval, + oldval); + if (curval == oldval) + { + /* Set the return value. */ + THREAD_SETMEM (self, result, PTHREAD_CANCELED); + + /* Make sure asynchronous cancellation is still enabled. */ + if ((newval & CANCELTYPE_BITMASK) != 0) + /* Run the registered destructors and terminate the thread. */ + __do_cancel (); + + break; + } + + oldval = curval; + } +} + + +struct xid_command *__xidcmd attribute_hidden; + +/* For asynchronous cancellation we use a signal. This is the handler. */ +static void +sighandler_setxid (int sig, siginfo_t *si, void *ctx) +{ +#ifdef __ASSUME_CORRECT_SI_PID + /* Determine the process ID. It might be negative if the thread is + in the middle of a fork() call. */ + pid_t pid = THREAD_GETMEM (THREAD_SELF, pid); + if (__builtin_expect (pid < 0, 0)) + pid = -pid; +#endif + + /* Safety check. It would be possible to call this function for + other signals and send a signal from another process. This is not + correct and might even be a security problem. Try to catch as + many incorrect invocations as possible. */ + if (sig != SIGSETXID +#ifdef __ASSUME_CORRECT_SI_PID + /* Kernels before 2.5.75 stored the thread ID and not the process + ID in si_pid so we skip this test. */ + || si->si_pid != pid +#endif + || si->si_code != SI_TKILL) + return; + + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL_NCS (__xidcmd->syscall_no, err, 3, __xidcmd->id[0], + __xidcmd->id[1], __xidcmd->id[2]); + + /* Reset the SETXID flag. */ + struct pthread *self = THREAD_SELF; + int flags, newval; + do + { + flags = THREAD_GETMEM (self, cancelhandling); + newval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, + flags & ~SETXID_BITMASK, flags); + } + while (flags != newval); + + /* And release the futex. */ + self->setxid_futex = 1; + lll_futex_wake (&self->setxid_futex, 1, LLL_PRIVATE); + + if (atomic_decrement_val (&__xidcmd->cntr) == 0) + lll_futex_wake (&__xidcmd->cntr, 1, LLL_PRIVATE); +} + + +/* When using __thread for this, we do it in libc so as not + to give libpthread its own TLS segment just for this. */ +extern void **__libc_dl_error_tsd (void) __attribute__ ((const)); + + +/* This can be set by the debugger before initialization is complete. */ +static bool __nptl_initial_report_events __attribute_used__; + +void +__pthread_initialize_minimal_internal (void) +{ +#ifndef SHARED + /* Unlike in the dynamically linked case the dynamic linker has not + taken care of initializing the TLS data structures. */ + __libc_setup_tls (TLS_TCB_SIZE, TLS_TCB_ALIGN); + + /* We must prevent gcc from being clever and move any of the + following code ahead of the __libc_setup_tls call. This function + will initialize the thread register which is subsequently + used. */ + __asm __volatile (""); +#endif + + /* Minimal initialization of the thread descriptor. */ + struct pthread *pd = THREAD_SELF; + INTERNAL_SYSCALL_DECL (err); + pd->pid = pd->tid = INTERNAL_SYSCALL (set_tid_address, err, 1, &pd->tid); + THREAD_SETMEM (pd, specific[0], &pd->specific_1stblock[0]); + THREAD_SETMEM (pd, user_stack, true); + if (LLL_LOCK_INITIALIZER != 0) + THREAD_SETMEM (pd, lock, LLL_LOCK_INITIALIZER); +#if HP_TIMING_AVAIL + THREAD_SETMEM (pd, cpuclock_offset, GL(dl_cpuclock_offset)); +#endif + + /* Initialize the robust mutex data. */ +#ifdef __PTHREAD_MUTEX_HAVE_PREV + pd->robust_prev = &pd->robust_head; +#endif + pd->robust_head.list = &pd->robust_head; +#ifdef __NR_set_robust_list + pd->robust_head.futex_offset = (offsetof (pthread_mutex_t, __data.__lock) + - offsetof (pthread_mutex_t, + __data.__list.__next)); + int res = INTERNAL_SYSCALL (set_robust_list, err, 2, &pd->robust_head, + sizeof (struct robust_list_head)); + if (INTERNAL_SYSCALL_ERROR_P (res, err)) +#endif + set_robust_list_not_avail (); + +#ifndef __ASSUME_PRIVATE_FUTEX + /* Private futexes are always used (at least internally) so that + doing the test once this early is beneficial. */ + { + int word = 0; + word = INTERNAL_SYSCALL (futex, err, 3, &word, + FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1); + if (!INTERNAL_SYSCALL_ERROR_P (word, err)) + THREAD_SETMEM (pd, header.private_futex, FUTEX_PRIVATE_FLAG); + } + + /* Private futexes have been introduced earlier than the + FUTEX_CLOCK_REALTIME flag. We don't have to run the test if we + know the former are not supported. This also means we know the + kernel will return ENOSYS for unknown operations. */ + if (THREAD_GETMEM (pd, header.private_futex) != 0) +#endif +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME + { + int word = 0; + /* NB: the syscall actually takes six parameters. The last is the + bit mask. But since we will not actually wait at all the value + is irrelevant. Given that passing six parameters is difficult + on some architectures we just pass whatever random value the + calling convention calls for to the kernel. It causes no harm. */ + word = INTERNAL_SYSCALL (futex, err, 5, &word, + FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME + | FUTEX_PRIVATE_FLAG, 1, NULL, 0); + assert (INTERNAL_SYSCALL_ERROR_P (word, err)); + if (INTERNAL_SYSCALL_ERRNO (word, err) != ENOSYS) + __set_futex_clock_realtime (); + } +#endif + + /* Set initial thread's stack block from 0 up to __libc_stack_end. + It will be bigger than it actually is, but for unwind.c/pt-longjmp.c + purposes this is good enough. */ + THREAD_SETMEM (pd, stackblock_size, (size_t) __libc_stack_end); + + /* Initialize the list of all running threads with the main thread. */ + INIT_LIST_HEAD (&__stack_user); + list_add (&pd->list, &__stack_user); + + /* Before initializing __stack_user, the debugger could not find us and + had to set __nptl_initial_report_events. Propagate its setting. */ + THREAD_SETMEM (pd, report_events, __nptl_initial_report_events); + + /* Install the cancellation signal handler. If for some reason we + cannot install the handler we do not abort. Maybe we should, but + it is only asynchronous cancellation which is affected. */ + struct sigaction sa; + sa.sa_sigaction = sigcancel_handler; + sa.sa_flags = SA_SIGINFO; + __sigemptyset (&sa.sa_mask); + + (void) __libc_sigaction (SIGCANCEL, &sa, NULL); + + /* Install the handle to change the threads' uid/gid. */ + sa.sa_sigaction = sighandler_setxid; + sa.sa_flags = SA_SIGINFO | SA_RESTART; + + (void) __libc_sigaction (SIGSETXID, &sa, NULL); + + /* The parent process might have left the signals blocked. Just in + case, unblock it. We reuse the signal mask in the sigaction + structure. It is already cleared. */ + __sigaddset (&sa.sa_mask, SIGCANCEL); + __sigaddset (&sa.sa_mask, SIGSETXID); + (void) INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_UNBLOCK, &sa.sa_mask, + NULL, _NSIG / 8); + + /* Get the size of the static and alignment requirements for the TLS + block. */ + size_t static_tls_align; + _dl_get_tls_static_info (&__static_tls_size, &static_tls_align); + + /* Make sure the size takes all the alignments into account. */ + if (STACK_ALIGN > static_tls_align) + static_tls_align = STACK_ALIGN; + __static_tls_align_m1 = static_tls_align - 1; + + __static_tls_size = roundup (__static_tls_size, static_tls_align); + + /* Determine the default allowed stack size. This is the size used + in case the user does not specify one. */ + struct rlimit limit; + if (getrlimit (RLIMIT_STACK, &limit) != 0 + || limit.rlim_cur == RLIM_INFINITY) + /* The system limit is not usable. Use an architecture-specific + default. */ + limit.rlim_cur = ARCH_STACK_DEFAULT_SIZE; + else if (limit.rlim_cur < PTHREAD_STACK_MIN) + /* The system limit is unusably small. + Use the minimal size acceptable. */ + limit.rlim_cur = PTHREAD_STACK_MIN; + + /* Make sure it meets the minimum size that allocate_stack + (allocatestack.c) will demand, which depends on the page size. */ + const uintptr_t pagesz = sysconf (_SC_PAGESIZE); + const size_t minstack = pagesz + __static_tls_size + MINIMAL_REST_STACK; + if (limit.rlim_cur < minstack) + limit.rlim_cur = minstack; + + /* Round the resource limit up to page size. */ + limit.rlim_cur = (limit.rlim_cur + pagesz - 1) & -pagesz; + __default_stacksize = limit.rlim_cur; + +#ifdef SHARED + /* Transfer the old value from the dynamic linker's internal location. */ + *__libc_dl_error_tsd () = *(*GL(dl_error_catch_tsd)) (); + GL(dl_error_catch_tsd) = &__libc_dl_error_tsd; + +#endif + + GL(dl_init_static_tls) = &__pthread_init_static_tls; + + /* Register the fork generation counter with the libc. */ +#ifndef TLS_MULTIPLE_THREADS_IN_TCB + __libc_multiple_threads_ptr = +#endif + __libc_pthread_init (&__fork_generation, __reclaim_stacks, + ptr_pthread_functions); + + /* Determine whether the machine is SMP or not. */ + __is_smp = is_smp_system (); + + /* uClibc-specific stdio initialization for threads. */ + { + FILE *fp; + _stdio_user_locking = 0; /* 2 if threading not initialized */ + for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen) { + if (fp->__user_locking != 1) { + fp->__user_locking = 0; + } + } + } +} +strong_alias (__pthread_initialize_minimal_internal, + __pthread_initialize_minimal) diff --git a/libpthread/nptl/libc-cancellation.c b/libpthread/nptl/libc-cancellation.c new file mode 100644 index 000000000..e9334a4c5 --- /dev/null +++ b/libpthread/nptl/libc-cancellation.c @@ -0,0 +1,25 @@ +/* Copyright (C) 2002, 2003, 2005, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +#define __pthread_enable_asynccancel __libc_enable_asynccancel +#define __pthread_disable_asynccancel __libc_disable_asynccancel +#include "cancellation.c" diff --git a/libpthread/nptl/linux_fsinfo.h b/libpthread/nptl/linux_fsinfo.h new file mode 100644 index 000000000..13c385626 --- /dev/null +++ b/libpthread/nptl/linux_fsinfo.h @@ -0,0 +1,153 @@ +/* Constants from kernel header for various FSes. + Copyright (C) 1998,1999,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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LINUX_FSINFO_H +#define _LINUX_FSINFO_H 1 + +/* These definitions come from the kernel headers. But we cannot + include the headers here because of type clashes. If new + filesystem types will become available we have to add the + appropriate definitions here.*/ + +/* Constants that identify the `adfs' filesystem. */ +#define ADFS_SUPER_MAGIC 0xadf5 + +/* Constants that identify the `affs' filesystem. */ +#define AFFS_SUPER_MAGIC 0xadff + +/* Constants that identify the `autofs' filesystem. */ +#define AUTOFS_SUPER_MAGIC 0x187 + +/* Constants that identify the `bfs' filesystem. */ +#define BFS_MAGIC 0x1BADFACE + +/* Constants that identify the `coda' filesystem. */ +#define CODA_SUPER_MAGIC 0x73757245 + +/* Constants that identify the `coherent' filesystem. */ +#define COH_SUPER_MAGIC 0x012ff7b7 + +/* Constant that identifies the `ramfs' filesystem. */ +#define CRAMFS_MAGIC 0x28cd3d45 + +/* Constant that identifies the `devfs' filesystem. */ +#define DEVFS_SUPER_MAGIC 0x1373 + +/* Constant that identifies the `devpts' filesystem. */ +#define DEVPTS_SUPER_MAGIC 0x1cd1 + +/* Constant that identifies the `efs' filesystem. */ +#define EFS_SUPER_MAGIC 0x414A53 +#define EFS_MAGIC 0x072959 + +/* Constant that identifies the `ext2' and `ext3' filesystems. */ +#define EXT2_SUPER_MAGIC 0xef53 + +/* Constant that identifies the `hpfs' filesystem. */ +#define HPFS_SUPER_MAGIC 0xf995e849 + +/* Constant that identifies the `iso9660' filesystem. */ +#define ISOFS_SUPER_MAGIC 0x9660 + +/* Constant that identifies the `jffs' filesystem. */ +#define JFFS_SUPER_MAGIC 0x07c0 + +/* Constant that identifies the `jffs2' filesystem. */ +#define JFFS2_SUPER_MAGIC 0x72b6 + +/* Constant that identifies the `jfs' filesystem. */ +#define JFS_SUPER_MAGIC 0x3153464a + +/* Constants that identify the `minix2' filesystem. */ +#define MINIX2_SUPER_MAGIC 0x2468 +#define MINIX2_SUPER_MAGIC2 0x2478 + +/* Constants that identify the `minix' filesystem. */ +#define MINIX_SUPER_MAGIC 0x137f +#define MINIX_SUPER_MAGIC2 0x138F + +/* Constants that identify the `msdos' filesystem. */ +#define MSDOS_SUPER_MAGIC 0x4d44 + +/* Constants that identify the `ncp' filesystem. */ +#define NCP_SUPER_MAGIC 0x564c + +/* Constants that identify the `nfs' filesystem. */ +#define NFS_SUPER_MAGIC 0x6969 + +/* Constants that identify the `ntfs' filesystem. */ +#define NTFS_SUPER_MAGIC 0x5346544e + +/* Constants that identify the `proc' filesystem. */ +#define PROC_SUPER_MAGIC 0x9fa0 + +/* Constant that identifies the `usbdevfs' filesystem. */ +#define USBDEVFS_SUPER_MAGIC 0x9fa2 + +/* Constants that identify the `qnx4' filesystem. */ +#define QNX4_SUPER_MAGIC 0x002f + +/* Constants that identify the `reiser' filesystem. */ +#define REISERFS_SUPER_MAGIC 0x52654973 + +/* Constant that identifies the `romfs' filesystem. */ +#define ROMFS_SUPER_MAGIC 0x7275 + +/* Constants that identify the `smb' filesystem. */ +#define SMB_SUPER_MAGIC 0x517b + +/* Constants that identify the `sysV' filesystem. */ +#define SYSV2_SUPER_MAGIC 0x012ff7b6 +#define SYSV4_SUPER_MAGIC 0x012ff7b5 + +/* Constants that identify the `udf' filesystem. */ +#define UDF_SUPER_MAGIC 0x15013346 + +/* Constants that identify the `ufs' filesystem. */ +#define UFS_MAGIC 0x00011954 +#define UFS_CIGAM 0x54190100 /* byteswapped MAGIC */ + +/* Constants that identify the `xenix' filesystem. */ +#define XENIX_SUPER_MAGIC 0x012ff7b4 + +/* Constant that identifies the `shm' filesystem. */ +#define SHMFS_SUPER_MAGIC 0x01021994 + +/* Constants that identify the `xfs' filesystem. */ +#define XFS_SUPER_MAGIC 0x58465342 + +/* Constants that identify the `vxfs' filesystem. */ +#define VXFS_SUPER_MAGIC 0xa501fcf5 + +/* Maximum link counts. */ +#define COH_LINK_MAX 10000 +#define EXT2_LINK_MAX 32000 +#define MINIX2_LINK_MAX 65530 +#define MINIX_LINK_MAX 250 +#define REISERFS_LINK_MAX 64535 +#define SYSV_LINK_MAX 126 /* 127? 251? */ +#define UFS_LINK_MAX EXT2_LINK_MAX +#define XENIX_LINK_MAX 126 /* ?? */ +#define XFS_LINK_MAX 2147483647 + +/* The Linux kernel header mentioned this as a kind of generic value. */ +#define LINUX_LINK_MAX 127 + + +#endif /* linux_fsinfo.h */ diff --git a/libpthread/nptl/pt-cleanup.c b/libpthread/nptl/pt-cleanup.c new file mode 100644 index 000000000..619eb8b61 --- /dev/null +++ b/libpthread/nptl/pt-cleanup.c @@ -0,0 +1,64 @@ +/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <setjmp.h> +#include <stdlib.h> +#include "pthreadP.h" +#include <jmpbuf-unwind.h> + +void +attribute_hidden +__pthread_cleanup_upto (__jmp_buf target, char *targetframe) +{ + struct pthread *self = THREAD_SELF; + struct _pthread_cleanup_buffer *cbuf; + + /* Adjust all pointers used in comparisons, so that top of thread's + stack is at the top of address space. Without that, things break + if stack is allocated above the main stack. */ + uintptr_t adj = (uintptr_t) self->stackblock + self->stackblock_size; + uintptr_t targetframe_adj = (uintptr_t) targetframe - adj; + + for (cbuf = THREAD_GETMEM (self, cleanup); + cbuf != NULL && _JMPBUF_UNWINDS_ADJ (target, cbuf, adj); + cbuf = cbuf->__prev) + { +#if _STACK_GROWS_DOWN + if ((uintptr_t) cbuf - adj <= targetframe_adj) + { + cbuf = NULL; + break; + } +#elif _STACK_GROWS_UP + if ((uintptr_t) cbuf - adj >= targetframe_adj) + { + cbuf = NULL; + break; + } +#else +# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +#endif + + /* Call the cleanup code. */ + cbuf->__routine (cbuf->__arg); + } + + THREAD_SETMEM (self, cleanup, cbuf); +} +hidden_def (__pthread_cleanup_upto) diff --git a/libpthread/nptl/pt-system.c b/libpthread/nptl/pt-system.c new file mode 100644 index 000000000..4728a7c08 --- /dev/null +++ b/libpthread/nptl/pt-system.c @@ -0,0 +1,36 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdlib.h> +#include <sysdep.h> +#include "pthreadP.h" + +extern __typeof(system) __libc_system; +#include <system.c> + + +int +system (const char *line) +{ + return __libc_system (line); +} + +/* __libc_system in libc.so handles cancellation. */ +LIBC_CANCEL_HANDLED (); diff --git a/libpthread/nptl/pthread-errnos.sym b/libpthread/nptl/pthread-errnos.sym new file mode 100644 index 000000000..0975b7a37 --- /dev/null +++ b/libpthread/nptl/pthread-errnos.sym @@ -0,0 +1,13 @@ +#include <errno.h> + +-- These errno codes are used by some assembly code. + +EAGAIN EAGAIN +EBUSY EBUSY +EDEADLK EDEADLK +EINTR EINTR +EINVAL EINVAL +ENOSYS ENOSYS +EOVERFLOW EOVERFLOW +ETIMEDOUT ETIMEDOUT +EWOULDBLOCK EWOULDBLOCK diff --git a/libpthread/nptl/pthreadP.h b/libpthread/nptl/pthreadP.h new file mode 100644 index 000000000..85601d435 --- /dev/null +++ b/libpthread/nptl/pthreadP.h @@ -0,0 +1,587 @@ +/* Copyright (C) 2002-2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _PTHREADP_H +#define _PTHREADP_H 1 + +#include <pthread.h> +#include <setjmp.h> +#include <stdbool.h> +#include <sys/syscall.h> +#include "descr.h" +#include <tls.h> +#include <lowlevellock.h> +#include <bits/stackinfo.h> +#include <internaltypes.h> +#include <pthread-functions.h> +#include <atomic.h> +#include <bits/kernel-features.h> + + +/* Atomic operations on TLS memory. */ +#ifndef THREAD_ATOMIC_CMPXCHG_VAL +# define THREAD_ATOMIC_CMPXCHG_VAL(descr, member, new, old) \ + atomic_compare_and_exchange_val_acq (&(descr)->member, new, old) +#endif + +#ifndef THREAD_ATOMIC_BIT_SET +# define THREAD_ATOMIC_BIT_SET(descr, member, bit) \ + atomic_bit_set (&(descr)->member, bit) +#endif + + +/* Adaptive mutex definitions. */ +#ifndef MAX_ADAPTIVE_COUNT +# define MAX_ADAPTIVE_COUNT 100 +#endif + + +/* Magic cookie representing robust mutex with dead owner. */ +#define PTHREAD_MUTEX_INCONSISTENT INT_MAX +/* Magic cookie representing not recoverable robust mutex. */ +#define PTHREAD_MUTEX_NOTRECOVERABLE (INT_MAX - 1) + + +/* Internal mutex type value. */ +enum +{ + PTHREAD_MUTEX_KIND_MASK_NP = 3, + PTHREAD_MUTEX_ROBUST_NORMAL_NP = 16, + PTHREAD_MUTEX_ROBUST_RECURSIVE_NP + = PTHREAD_MUTEX_ROBUST_NORMAL_NP | PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP + = PTHREAD_MUTEX_ROBUST_NORMAL_NP | PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP + = PTHREAD_MUTEX_ROBUST_NORMAL_NP | PTHREAD_MUTEX_ADAPTIVE_NP, + PTHREAD_MUTEX_PRIO_INHERIT_NP = 32, + PTHREAD_MUTEX_PI_NORMAL_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_NORMAL, + PTHREAD_MUTEX_PI_RECURSIVE_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_PI_ERRORCHECK_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_PI_ADAPTIVE_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ADAPTIVE_NP, + PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_NORMAL_NP, + PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_RECURSIVE_NP, + PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP, + PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP, + PTHREAD_MUTEX_PRIO_PROTECT_NP = 64, + PTHREAD_MUTEX_PP_NORMAL_NP + = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_NORMAL, + PTHREAD_MUTEX_PP_RECURSIVE_NP + = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_PP_ERRORCHECK_NP + = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_PP_ADAPTIVE_NP + = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_ADAPTIVE_NP +}; +#define PTHREAD_MUTEX_PSHARED_BIT 128 + +#define PTHREAD_MUTEX_TYPE(m) \ + ((m)->__data.__kind & 127) + +#if LLL_PRIVATE == 0 && LLL_SHARED == 128 +# define PTHREAD_MUTEX_PSHARED(m) \ + ((m)->__data.__kind & 128) +#else +# define PTHREAD_MUTEX_PSHARED(m) \ + (((m)->__data.__kind & 128) ? LLL_SHARED : LLL_PRIVATE) +#endif + +/* The kernel when waking robust mutexes on exit never uses + FUTEX_PRIVATE_FLAG FUTEX_WAKE. */ +#define PTHREAD_ROBUST_MUTEX_PSHARED(m) LLL_SHARED + +/* Ceiling in __data.__lock. __data.__lock is signed, so don't + use the MSB bit in there, but in the mask also include that bit, + so that the compiler can optimize & PTHREAD_MUTEX_PRIO_CEILING_MASK + masking if the value is then shifted down by + PTHREAD_MUTEX_PRIO_CEILING_SHIFT. */ +#define PTHREAD_MUTEX_PRIO_CEILING_SHIFT 19 +#define PTHREAD_MUTEX_PRIO_CEILING_MASK 0xfff80000 + + +/* Flags in mutex attr. */ +#define PTHREAD_MUTEXATTR_PROTOCOL_SHIFT 28 +#define PTHREAD_MUTEXATTR_PROTOCOL_MASK 0x30000000 +#define PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT 12 +#define PTHREAD_MUTEXATTR_PRIO_CEILING_MASK 0x00fff000 +#define PTHREAD_MUTEXATTR_FLAG_ROBUST 0x40000000 +#define PTHREAD_MUTEXATTR_FLAG_PSHARED 0x80000000 +#define PTHREAD_MUTEXATTR_FLAG_BITS \ + (PTHREAD_MUTEXATTR_FLAG_ROBUST | PTHREAD_MUTEXATTR_FLAG_PSHARED \ + | PTHREAD_MUTEXATTR_PROTOCOL_MASK | PTHREAD_MUTEXATTR_PRIO_CEILING_MASK) + + +/* Check whether rwlock prefers readers. */ +#define PTHREAD_RWLOCK_PREFER_READER_P(rwlock) \ + ((rwlock)->__data.__flags == 0) + + +/* Bits used in robust mutex implementation. */ +#define FUTEX_WAITERS 0x80000000 +#define FUTEX_OWNER_DIED 0x40000000 +#define FUTEX_TID_MASK 0x3fffffff + + +/* Internal variables. */ + + +/* Default stack size. */ +extern size_t __default_stacksize attribute_hidden; + +/* Size and alignment of static TLS block. */ +extern size_t __static_tls_size attribute_hidden; +extern size_t __static_tls_align_m1 attribute_hidden; + +/* Flag whether the machine is SMP or not. */ +extern int __is_smp attribute_hidden; + +/* Thread descriptor handling. */ +extern list_t __stack_user; +hidden_proto (__stack_user) + +/* Attribute handling. */ +extern struct pthread_attr *__attr_list attribute_hidden; +extern int __attr_list_lock attribute_hidden; + +/* First available RT signal. */ +extern int __current_sigrtmin attribute_hidden; +/* Last available RT signal. */ +extern int __current_sigrtmax attribute_hidden; + +/* Concurrency handling. */ +extern int __concurrency_level attribute_hidden; + +/* Thread-local data key handling. */ +extern struct pthread_key_struct __pthread_keys[PTHREAD_KEYS_MAX]; +hidden_proto (__pthread_keys) + +/* Number of threads running. */ +extern unsigned int __nptl_nthreads attribute_hidden; + +#ifndef __ASSUME_SET_ROBUST_LIST +/* Negative if we do not have the system call and we can use it. */ +extern int __set_robust_list_avail attribute_hidden; +#endif + +/* Thread Priority Protection. */ +extern int __sched_fifo_min_prio attribute_hidden; +extern int __sched_fifo_max_prio attribute_hidden; +extern void __init_sched_fifo_prio (void) attribute_hidden; +extern int __pthread_tpp_change_priority (int prev_prio, int new_prio) + attribute_hidden; +extern int __pthread_current_priority (void) attribute_hidden; + +/* The library can run in debugging mode where it performs a lot more + tests. */ +extern int __pthread_debug attribute_hidden; +/** For now disable debugging support. */ +#if 0 +# define DEBUGGING_P __builtin_expect (__pthread_debug, 0) +# define INVALID_TD_P(pd) (DEBUGGING_P && __find_in_stack_list (pd) == NULL) +# define INVALID_NOT_TERMINATED_TD_P(pd) INVALID_TD_P (pd) +#else +# define DEBUGGING_P 0 +/* Simplified test. This will not catch all invalid descriptors but + is better than nothing. And if the test triggers the thread + descriptor is guaranteed to be invalid. */ +# define INVALID_TD_P(pd) __builtin_expect ((pd)->tid <= 0, 0) +# define INVALID_NOT_TERMINATED_TD_P(pd) __builtin_expect ((pd)->tid < 0, 0) +#endif + + +/* Cancellation test. */ +#define CANCELLATION_P(self) \ + do { \ + int cancelhandling = THREAD_GETMEM (self, cancelhandling); \ + if (CANCEL_ENABLED_AND_CANCELED (cancelhandling)) \ + { \ + THREAD_SETMEM (self, result, PTHREAD_CANCELED); \ + __do_cancel (); \ + } \ + } while (0) + + +extern void __pthread_unwind (__pthread_unwind_buf_t *__buf) + __cleanup_fct_attribute __attribute ((__noreturn__)) +#if !defined SHARED && !defined IS_IN_libpthread + weak_function +#endif + ; +extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf) + __cleanup_fct_attribute __attribute ((__noreturn__)) +#ifndef SHARED + weak_function +#endif + ; +extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf) + __cleanup_fct_attribute; +extern void __pthread_unregister_cancel (__pthread_unwind_buf_t *__buf) + __cleanup_fct_attribute; +#if defined NOT_IN_libc && defined IS_IN_libpthread +hidden_proto (__pthread_unwind) +hidden_proto (__pthread_unwind_next) +hidden_proto (__pthread_register_cancel) +hidden_proto (__pthread_unregister_cancel) +# ifdef SHARED +extern void attribute_hidden pthread_cancel_init (void); +extern void __unwind_freeres (void); +# endif +#endif + + +/* Called when a thread reacts on a cancellation request. */ +static inline void +__attribute ((noreturn, always_inline)) +__do_cancel (void) +{ + struct pthread *self = THREAD_SELF; + + /* Make sure we get no more cancellations. */ + THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT); + + __pthread_unwind ((__pthread_unwind_buf_t *) + THREAD_GETMEM (self, cleanup_jmp_buf)); +} + + +/* Set cancellation mode to asynchronous. */ +#define CANCEL_ASYNC() \ + __pthread_enable_asynccancel () +/* Reset to previous cancellation mode. */ +#define CANCEL_RESET(oldtype) \ + __pthread_disable_asynccancel (oldtype) + +#if !defined NOT_IN_libc +/* Same as CANCEL_ASYNC, but for use in libc.so. */ +# define LIBC_CANCEL_ASYNC() \ + __libc_enable_asynccancel () +/* Same as CANCEL_RESET, but for use in libc.so. */ +# define LIBC_CANCEL_RESET(oldtype) \ + __libc_disable_asynccancel (oldtype) +# define LIBC_CANCEL_HANDLED() \ + __asm__ (".globl " __USER_LABEL_PREFIX__ "__libc_enable_asynccancel"); \ + __asm__ (".globl " __USER_LABEL_PREFIX__ "__libc_disable_asynccancel") +#elif defined NOT_IN_libc && defined IS_IN_libpthread +# define LIBC_CANCEL_ASYNC() CANCEL_ASYNC () +# define LIBC_CANCEL_RESET(val) CANCEL_RESET (val) +# define LIBC_CANCEL_HANDLED() \ + __asm__ (".globl " __USER_LABEL_PREFIX__ "__pthread_enable_asynccancel"); \ + __asm__ (".globl " __USER_LABEL_PREFIX__ "__pthread_disable_asynccancel") +#elif defined NOT_IN_libc && defined IS_IN_librt +# define LIBC_CANCEL_ASYNC() \ + __librt_enable_asynccancel () +# define LIBC_CANCEL_RESET(val) \ + __librt_disable_asynccancel (val) +# define LIBC_CANCEL_HANDLED() \ + __asm__ (".globl " __USER_LABEL_PREFIX__ "__librt_enable_asynccancel"); \ + __asm__ (".globl " __USER_LABEL_PREFIX__ "__librt_disable_asynccancel") +#else +# define LIBC_CANCEL_ASYNC() 0 /* Just a dummy value. */ +# define LIBC_CANCEL_RESET(val) ((void)(val)) /* Nothing, but evaluate it. */ +# define LIBC_CANCEL_HANDLED() /* Nothing. */ +#endif + +/* The signal used for asynchronous cancelation. */ +#define SIGCANCEL __SIGRTMIN + + +/* Signal needed for the kernel-supported POSIX timer implementation. + We can reuse the cancellation signal since we can distinguish + cancellation from timer expirations. */ +#define SIGTIMER SIGCANCEL + + +/* Signal used to implement the setuid et.al. functions. */ +#define SIGSETXID (__SIGRTMIN + 1) + +/* Used to communicate with signal handler. */ +extern struct xid_command *__xidcmd attribute_hidden; + + +/* Internal prototypes. */ + +/* Thread list handling. */ +extern struct pthread *__find_in_stack_list (struct pthread *pd) + attribute_hidden internal_function; + +/* Deallocate a thread's stack after optionally making sure the thread + descriptor is still valid. */ +extern void __free_tcb (struct pthread *pd) attribute_hidden internal_function; + +/* Free allocated stack. */ +extern void __deallocate_stack (struct pthread *pd) + attribute_hidden internal_function; + +/* Mark all the stacks except for the current one as available. This + function also re-initializes the lock for the stack cache. */ +extern void __reclaim_stacks (void) attribute_hidden; + +/* Make all threads's stacks executable. */ +extern int __make_stacks_executable (void **stack_endp) + internal_function attribute_hidden; + +/* longjmp handling. */ +extern void __pthread_cleanup_upto (__jmp_buf target, char *targetframe); +#if defined NOT_IN_libc && defined IS_IN_libpthread +hidden_proto (__pthread_cleanup_upto) +#endif + + +/* Functions with versioned interfaces. */ +extern int __pthread_create_2_1 (pthread_t *newthread, + const pthread_attr_t *attr, + void *(*start_routine) (void *), void *arg); +extern int __pthread_create_2_0 (pthread_t *newthread, + const pthread_attr_t *attr, + void *(*start_routine) (void *), void *arg); +extern int __pthread_attr_init_2_1 (pthread_attr_t *attr); +extern int __pthread_attr_init_2_0 (pthread_attr_t *attr); + + +/* Event handlers for libthread_db interface. */ +extern void __nptl_create_event (void); +extern void __nptl_death_event (void); +hidden_proto (__nptl_create_event) +hidden_proto (__nptl_death_event) + +/* Register the generation counter in the libpthread with the libc. */ +#ifdef TLS_MULTIPLE_THREADS_IN_TCB +extern void __libc_pthread_init (unsigned long int *ptr, + void (*reclaim) (void), + const struct pthread_functions *functions); +#else +extern int *__libc_pthread_init (unsigned long int *ptr, + void (*reclaim) (void), + const struct pthread_functions *functions); + +/* Variable set to a nonzero value if more than one thread runs or ran. */ +extern int __pthread_multiple_threads attribute_hidden; +/* Pointer to the corresponding variable in libc. */ +extern int *__libc_multiple_threads_ptr attribute_hidden; +#endif + +/* Find a thread given its TID. */ +extern struct pthread *__find_thread_by_id (pid_t tid) attribute_hidden +#ifdef SHARED +; +#else +weak_function; +#define __find_thread_by_id(tid) \ + (__find_thread_by_id ? (__find_thread_by_id) (tid) : (struct pthread *) NULL) +#endif + +extern void __pthread_init_static_tls (struct link_map *) attribute_hidden; + + +/* Namespace save aliases. */ +extern int __pthread_getschedparam (pthread_t thread_id, int *policy, + struct sched_param *param); +extern int __pthread_setschedparam (pthread_t thread_id, int policy, + const struct sched_param *param); +extern int __pthread_setcancelstate (int state, int *oldstate); +extern int __pthread_mutex_init (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutexattr); +extern int __pthread_mutex_init_internal (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutexattr) + attribute_hidden; +extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex); +extern int __pthread_mutex_destroy_internal (pthread_mutex_t *__mutex) + attribute_hidden; +extern int __pthread_mutex_trylock (pthread_mutex_t *_mutex); +extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); +extern int __pthread_mutex_lock_internal (pthread_mutex_t *__mutex) + attribute_hidden; +extern int __pthread_mutex_cond_lock (pthread_mutex_t *__mutex); +extern void __pthread_mutex_cond_lock_adjust (pthread_mutex_t *__mutex); +extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); +extern int __pthread_mutex_unlock_internal (pthread_mutex_t *__mutex) + attribute_hidden; +extern int __pthread_mutex_unlock_usercnt (pthread_mutex_t *__mutex, + int __decr) + attribute_hidden internal_function; +extern int __pthread_mutexattr_init (pthread_mutexattr_t *attr); +extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *attr); +extern int __pthread_mutexattr_settype (pthread_mutexattr_t *attr, int kind); +extern int __pthread_attr_destroy (pthread_attr_t *attr); +extern int __pthread_attr_getdetachstate (const pthread_attr_t *attr, + int *detachstate); +extern int __pthread_attr_setdetachstate (pthread_attr_t *attr, + int detachstate); +extern int __pthread_attr_getinheritsched (const pthread_attr_t *attr, + int *inherit); +extern int __pthread_attr_setinheritsched (pthread_attr_t *attr, int inherit); +extern int __pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param); +extern int __pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param); +extern int __pthread_attr_getschedpolicy (const pthread_attr_t *attr, + int *policy); +extern int __pthread_attr_setschedpolicy (pthread_attr_t *attr, int policy); +extern int __pthread_attr_getscope (const pthread_attr_t *attr, int *scope); +extern int __pthread_attr_setscope (pthread_attr_t *attr, int scope); +extern int __pthread_attr_getstackaddr (__const pthread_attr_t *__restrict + __attr, void **__restrict __stackaddr); +extern int __pthread_attr_setstackaddr (pthread_attr_t *__attr, + void *__stackaddr); +extern int __pthread_attr_getstacksize (__const pthread_attr_t *__restrict + __attr, + size_t *__restrict __stacksize); +extern int __pthread_attr_setstacksize (pthread_attr_t *__attr, + size_t __stacksize); +extern int __pthread_attr_getstack (__const pthread_attr_t *__restrict __attr, + void **__restrict __stackaddr, + size_t *__restrict __stacksize); +extern int __pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr, + size_t __stacksize); +extern int __pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock, + __const pthread_rwlockattr_t *__restrict + __attr); +extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_rdlock_internal (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_wrlock_internal (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_unlock_internal (pthread_rwlock_t *__rwlock); +extern int __pthread_cond_broadcast (pthread_cond_t *cond); +extern int __pthread_cond_destroy (pthread_cond_t *cond); +extern int __pthread_cond_init (pthread_cond_t *cond, + const pthread_condattr_t *cond_attr); +extern int __pthread_cond_signal (pthread_cond_t *cond); +extern int __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex); +extern int __pthread_cond_timedwait (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime); +extern int __pthread_condattr_destroy (pthread_condattr_t *attr); +extern int __pthread_condattr_init (pthread_condattr_t *attr); +extern int __pthread_key_create (pthread_key_t *key, void (*destr) (void *)); +extern int __pthread_key_create_internal (pthread_key_t *key, + void (*destr) (void *)); +extern void *__pthread_getspecific (pthread_key_t key); +extern void *__pthread_getspecific_internal (pthread_key_t key); +extern int __pthread_setspecific (pthread_key_t key, const void *value); +extern int __pthread_setspecific_internal (pthread_key_t key, + const void *value); +extern int __pthread_once (pthread_once_t *once_control, + void (*init_routine) (void)); +extern int __pthread_once_internal (pthread_once_t *once_control, + void (*init_routine) (void)); +extern int __pthread_atfork (void (*prepare) (void), void (*parent) (void), + void (*child) (void)); +extern pthread_t __pthread_self (void); +extern int __pthread_equal (pthread_t thread1, pthread_t thread2); +extern int __pthread_kill (pthread_t threadid, int signo); +extern void __pthread_exit (void *value); +extern int __pthread_setcanceltype (int type, int *oldtype); +extern int __pthread_enable_asynccancel (void) attribute_hidden; +extern void __pthread_disable_asynccancel (int oldtype) + internal_function attribute_hidden; + +extern int __pthread_cond_broadcast_2_0 (pthread_cond_2_0_t *cond); +extern int __pthread_cond_destroy_2_0 (pthread_cond_2_0_t *cond); +extern int __pthread_cond_init_2_0 (pthread_cond_2_0_t *cond, + const pthread_condattr_t *cond_attr); +extern int __pthread_cond_signal_2_0 (pthread_cond_2_0_t *cond); +extern int __pthread_cond_timedwait_2_0 (pthread_cond_2_0_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime); +extern int __pthread_cond_wait_2_0 (pthread_cond_2_0_t *cond, + pthread_mutex_t *mutex); + +extern int __pthread_getaffinity_np (pthread_t th, size_t cpusetsize, + cpu_set_t *cpuset); + +/* The two functions are in libc.so and not exported. */ +extern int __libc_enable_asynccancel (void) attribute_hidden; +extern void __libc_disable_asynccancel (int oldtype) + internal_function attribute_hidden; + + +/* The two functions are in librt.so and not exported. */ +extern int __librt_enable_asynccancel (void) attribute_hidden; +extern void __librt_disable_asynccancel (int oldtype) + internal_function attribute_hidden; + +#ifdef IS_IN_libpthread +/* Special versions which use non-exported functions. */ +extern void __pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer, + void (*routine) (void *), void *arg) + attribute_hidden; +# undef pthread_cleanup_push +# define pthread_cleanup_push(routine,arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + __pthread_cleanup_push (&_buffer, (routine), (arg)); + +extern void __pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer, + int execute) attribute_hidden; +# undef pthread_cleanup_pop +# define pthread_cleanup_pop(execute) \ + __pthread_cleanup_pop (&_buffer, (execute)); } +#endif + +extern void __pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer, + void (*routine) (void *), void *arg); +extern void __pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer, + int execute); + +/* Old cleanup interfaces, still used in libc.so. */ +extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer, + void (*routine) (void *), void *arg); +extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer, + int execute); +extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer, + void (*routine) (void *), void *arg); +extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer, + int execute); + +extern void __nptl_deallocate_tsd (void) attribute_hidden; + +extern int __nptl_setxid (struct xid_command *cmdp) attribute_hidden; + +extern void __free_stacks (size_t limit) attribute_hidden; + +extern void __wait_lookup_done (void) attribute_hidden; + +#ifdef SHARED +# define PTHREAD_STATIC_FN_REQUIRE(name) +#else +# define PTHREAD_STATIC_FN_REQUIRE(name) __asm__ (".globl " #name); +#endif + + +#ifndef __NR_set_robust_list +/* XXX For the time being... Once we can rely on the kernel headers + having the definition remove these lines. */ +# if defined __i386__ +# define __NR_set_robust_list 311 +# elif defined __x86_64__ +# define __NR_set_robust_list 273 +# endif +#endif + +#endif /* pthreadP.h */ diff --git a/libpthread/nptl/pthread_atfork.c b/libpthread/nptl/pthread_atfork.c new file mode 100644 index 000000000..e607d496e --- /dev/null +++ b/libpthread/nptl/pthread_atfork.c @@ -0,0 +1,56 @@ +/* Copyright (C) 2002, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + 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 <fork.h> + +/* This is defined by newer gcc version unique for each module. */ +extern void *__dso_handle __attribute__ ((__weak__)); + //,__visibility__ ("hidden"))); + + +/* Hide the symbol so that no definition but the one locally in the + executable or DSO is used. */ +int +__pthread_atfork ( + void (*prepare) (void), + void (*parent) (void), + void (*child) (void)) +{ + return __register_atfork (prepare, parent, child, + &__dso_handle == NULL ? NULL : __dso_handle); +} +strong_alias (__pthread_atfork, pthread_atfork) diff --git a/libpthread/nptl/pthread_attr_destroy.c b/libpthread/nptl/pthread_attr_destroy.c new file mode 100644 index 000000000..16b71645c --- /dev/null +++ b/libpthread/nptl/pthread_attr_destroy.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include "pthreadP.h" + +int +attribute_hidden +__pthread_attr_destroy ( + pthread_attr_t *attr) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* The affinity CPU set might be allocated dynamically. */ + free (iattr->cpuset); + + return 0; +} +strong_alias (__pthread_attr_destroy, pthread_attr_destroy) diff --git a/libpthread/nptl/pthread_attr_getdetachstate.c b/libpthread/nptl/pthread_attr_getdetachstate.c new file mode 100644 index 000000000..14b91df13 --- /dev/null +++ b/libpthread/nptl/pthread_attr_getdetachstate.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include "pthreadP.h" + + +int +attribute_hidden +__pthread_attr_getdetachstate ( + const pthread_attr_t *attr, + int *detachstate) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + *detachstate = (iattr->flags & ATTR_FLAG_DETACHSTATE + ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE); + + return 0; +} +strong_alias (__pthread_attr_getdetachstate, pthread_attr_getdetachstate) diff --git a/libpthread/nptl/pthread_attr_getguardsize.c b/libpthread/nptl/pthread_attr_getguardsize.c new file mode 100644 index 000000000..6fc3e6af1 --- /dev/null +++ b/libpthread/nptl/pthread_attr_getguardsize.c @@ -0,0 +1,35 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include "pthreadP.h" + + +int +pthread_attr_getguardsize (const pthread_attr_t *attr, size_t *guardsize) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + *guardsize = iattr->guardsize; + + return 0; +} diff --git a/libpthread/nptl/pthread_attr_getinheritsched.c b/libpthread/nptl/pthread_attr_getinheritsched.c new file mode 100644 index 000000000..8ab8657f6 --- /dev/null +++ b/libpthread/nptl/pthread_attr_getinheritsched.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include "pthreadP.h" + + +int +attribute_hidden +__pthread_attr_getinheritsched ( + const pthread_attr_t *attr, + int *inherit) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Store the current values. */ + *inherit = (iattr->flags & ATTR_FLAG_NOTINHERITSCHED + ? PTHREAD_EXPLICIT_SCHED : PTHREAD_INHERIT_SCHED); + + return 0; +} +strong_alias (__pthread_attr_getinheritsched, pthread_attr_getinheritsched) diff --git a/libpthread/nptl/pthread_attr_getschedparam.c b/libpthread/nptl/pthread_attr_getschedparam.c new file mode 100644 index 000000000..ee1d51339 --- /dev/null +++ b/libpthread/nptl/pthread_attr_getschedparam.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <string.h> +#include "pthreadP.h" + + +int +attribute_hidden +__pthread_attr_getschedparam ( + const pthread_attr_t *attr, + struct sched_param *param) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Copy the current values. */ + memcpy (param, &iattr->schedparam, sizeof (struct sched_param)); + + return 0; +} +strong_alias (__pthread_attr_getschedparam, pthread_attr_getschedparam) diff --git a/libpthread/nptl/pthread_attr_getschedpolicy.c b/libpthread/nptl/pthread_attr_getschedpolicy.c new file mode 100644 index 000000000..54666daba --- /dev/null +++ b/libpthread/nptl/pthread_attr_getschedpolicy.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include "pthreadP.h" + + +int +attribute_hidden +__pthread_attr_getschedpolicy ( + const pthread_attr_t *attr, + int *policy) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Store the current values. */ + *policy = iattr->schedpolicy; + + return 0; +} +strong_alias (__pthread_attr_getschedpolicy, pthread_attr_getschedpolicy) diff --git a/libpthread/nptl/pthread_attr_getscope.c b/libpthread/nptl/pthread_attr_getscope.c new file mode 100644 index 000000000..ccbebfa43 --- /dev/null +++ b/libpthread/nptl/pthread_attr_getscope.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include "pthreadP.h" + + +int +attribute_hidden +__pthread_attr_getscope ( + const pthread_attr_t *attr, + int *scope) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Store the current values. */ + *scope = (iattr->flags & ATTR_FLAG_SCOPEPROCESS + ? PTHREAD_SCOPE_PROCESS : PTHREAD_SCOPE_SYSTEM); + + return 0; +} +strong_alias (__pthread_attr_getscope, pthread_attr_getscope) diff --git a/libpthread/nptl/pthread_attr_getstack.c b/libpthread/nptl/pthread_attr_getstack.c new file mode 100644 index 000000000..cb745368f --- /dev/null +++ b/libpthread/nptl/pthread_attr_getstack.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include "pthreadP.h" + + +int +__pthread_attr_getstack ( + const pthread_attr_t *attr, + void **stackaddr, + size_t *stacksize) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Store the result. */ + *stackaddr = (char *) iattr->stackaddr - iattr->stacksize; + *stacksize = iattr->stacksize; + + return 0; +} +strong_alias (__pthread_attr_getstack, pthread_attr_getstack) diff --git a/libpthread/nptl/pthread_attr_getstackaddr.c b/libpthread/nptl/pthread_attr_getstackaddr.c new file mode 100644 index 000000000..305910c16 --- /dev/null +++ b/libpthread/nptl/pthread_attr_getstackaddr.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include "pthreadP.h" + + +int +__pthread_attr_getstackaddr ( + const pthread_attr_t *attr, + void **stackaddr) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Some code assumes this function to work even if no stack address + has been set. Let them figure it out for themselves what the + value means. Simply store the result. */ + *stackaddr = iattr->stackaddr; + + return 0; +} +strong_alias (__pthread_attr_getstackaddr, pthread_attr_getstackaddr) + +link_warning (pthread_attr_getstackaddr, + "the use of `pthread_attr_getstackaddr' is deprecated, use `pthread_attr_getstack'") diff --git a/libpthread/nptl/pthread_attr_getstacksize.c b/libpthread/nptl/pthread_attr_getstacksize.c new file mode 100644 index 000000000..ec20f6b96 --- /dev/null +++ b/libpthread/nptl/pthread_attr_getstacksize.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include "pthreadP.h" + + +int +__pthread_attr_getstacksize ( + const pthread_attr_t *attr, + size_t *stacksize) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* If the user has not set a stack size we return what the system + will use as the default. */ + *stacksize = iattr->stacksize ?: __default_stacksize; + + return 0; +} +strong_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize) diff --git a/libpthread/nptl/pthread_attr_init.c b/libpthread/nptl/pthread_attr_init.c new file mode 100644 index 000000000..d01951489 --- /dev/null +++ b/libpthread/nptl/pthread_attr_init.c @@ -0,0 +1,51 @@ +/* Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include "pthreadP.h" + + +struct pthread_attr *__attr_list; +int __attr_list_lock = LLL_LOCK_INITIALIZER; + + +int +attribute_hidden +__pthread_attr_init_2_1 ( + pthread_attr_t *attr) +{ + struct pthread_attr *iattr; + + /* Many elements are initialized to zero so let us do it all at + once. This also takes care of clearing the bytes which are not + internally used. */ + memset (attr, '\0', __SIZEOF_PTHREAD_ATTR_T); + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Default guard size specified by the standard. */ + iattr->guardsize = getpagesize (); + + return 0; +} +weak_alias(__pthread_attr_init_2_1, pthread_attr_init) diff --git a/libpthread/nptl/pthread_attr_setdetachstate.c b/libpthread/nptl/pthread_attr_setdetachstate.c new file mode 100644 index 000000000..d72fd8360 --- /dev/null +++ b/libpthread/nptl/pthread_attr_setdetachstate.c @@ -0,0 +1,47 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include "pthreadP.h" + + +int +attribute_hidden +__pthread_attr_setdetachstate (pthread_attr_t *attr, int detachstate) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Catch invalid values. */ + if (detachstate != PTHREAD_CREATE_DETACHED + && __builtin_expect (detachstate != PTHREAD_CREATE_JOINABLE, 0)) + return EINVAL; + + /* Set the flag. It is nonzero if threads are created detached. */ + if (detachstate == PTHREAD_CREATE_DETACHED) + iattr->flags |= ATTR_FLAG_DETACHSTATE; + else + iattr->flags &= ~ATTR_FLAG_DETACHSTATE; + + return 0; +} +strong_alias (__pthread_attr_setdetachstate, pthread_attr_setdetachstate) diff --git a/libpthread/nptl/pthread_attr_setguardsize.c b/libpthread/nptl/pthread_attr_setguardsize.c new file mode 100644 index 000000000..a424312f2 --- /dev/null +++ b/libpthread/nptl/pthread_attr_setguardsize.c @@ -0,0 +1,38 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include "pthreadP.h" + + +int +pthread_attr_setguardsize (pthread_attr_t* attr, size_t guardsize) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Note that we don't round the value here. The standard requires + that subsequent pthread_attr_getguardsize calls return the value + set by the user. */ + iattr->guardsize = guardsize; + + return 0; +} diff --git a/libpthread/nptl/pthread_attr_setinheritsched.c b/libpthread/nptl/pthread_attr_setinheritsched.c new file mode 100644 index 000000000..d340df2d9 --- /dev/null +++ b/libpthread/nptl/pthread_attr_setinheritsched.c @@ -0,0 +1,48 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include "pthreadP.h" + + +int +attribute_hidden +__pthread_attr_setinheritsched ( + pthread_attr_t *attr, + int inherit) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Catch invalid values. */ + if (inherit != PTHREAD_INHERIT_SCHED && inherit != PTHREAD_EXPLICIT_SCHED) + return EINVAL; + + /* Store the new values. */ + if (inherit != PTHREAD_INHERIT_SCHED) + iattr->flags |= ATTR_FLAG_NOTINHERITSCHED; + else + iattr->flags &= ~ATTR_FLAG_NOTINHERITSCHED; + + return 0; +} +strong_alias (__pthread_attr_setinheritsched, pthread_attr_setinheritsched) diff --git a/libpthread/nptl/pthread_attr_setschedparam.c b/libpthread/nptl/pthread_attr_setschedparam.c new file mode 100644 index 000000000..aa7140060 --- /dev/null +++ b/libpthread/nptl/pthread_attr_setschedparam.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2002, 2004, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include <string.h> +#include "pthreadP.h" + + +int +attribute_hidden +__pthread_attr_setschedparam ( + pthread_attr_t *attr, + const struct sched_param *param) +{ + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + struct pthread_attr *iattr = (struct pthread_attr *) attr; + + int min = sched_get_priority_min (iattr->schedpolicy); + int max = sched_get_priority_max (iattr->schedpolicy); + if (min == -1 || max == -1 + || param->sched_priority > max || param->sched_priority < min) + return EINVAL; + + /* Copy the new values. */ + memcpy (&iattr->schedparam, param, sizeof (struct sched_param)); + + /* Remember we set the value. */ + iattr->flags |= ATTR_FLAG_SCHED_SET; + + return 0; +} +strong_alias (__pthread_attr_setschedparam, pthread_attr_setschedparam) diff --git a/libpthread/nptl/pthread_attr_setschedpolicy.c b/libpthread/nptl/pthread_attr_setschedpolicy.c new file mode 100644 index 000000000..055890b41 --- /dev/null +++ b/libpthread/nptl/pthread_attr_setschedpolicy.c @@ -0,0 +1,48 @@ +/* Copyright (C) 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include "pthreadP.h" + + +int +attribute_hidden +__pthread_attr_setschedpolicy ( + pthread_attr_t *attr, + int policy) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Catch invalid values. */ + if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR) + return EINVAL; + + /* Store the new values. */ + iattr->schedpolicy = policy; + + /* Remember we set the value. */ + iattr->flags |= ATTR_FLAG_POLICY_SET; + + return 0; +} +strong_alias (__pthread_attr_setschedpolicy, pthread_attr_setschedpolicy) diff --git a/libpthread/nptl/pthread_attr_setscope.c b/libpthread/nptl/pthread_attr_setscope.c new file mode 100644 index 000000000..8155bead8 --- /dev/null +++ b/libpthread/nptl/pthread_attr_setscope.c @@ -0,0 +1,52 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include "pthreadP.h" + + +int +attribute_hidden +__pthread_attr_setscope ( + pthread_attr_t *attr, + int scope) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Catch invalid values. */ + switch (scope) + { + case PTHREAD_SCOPE_SYSTEM: + iattr->flags &= ~ATTR_FLAG_SCOPEPROCESS; + break; + + case PTHREAD_SCOPE_PROCESS: + return ENOTSUP; + + default: + return EINVAL; + } + + return 0; +} +strong_alias (__pthread_attr_setscope, pthread_attr_setscope) diff --git a/libpthread/nptl/pthread_attr_setstack.c b/libpthread/nptl/pthread_attr_setstack.c new file mode 100644 index 000000000..d400f3db2 --- /dev/null +++ b/libpthread/nptl/pthread_attr_setstack.c @@ -0,0 +1,56 @@ +/* Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include "pthreadP.h" + + +int +__pthread_attr_setstack ( + pthread_attr_t *attr, + void *stackaddr, + size_t stacksize) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Catch invalid sizes. */ + if (stacksize < PTHREAD_STACK_MIN) + return EINVAL; + +#ifdef EXTRA_PARAM_CHECKS + EXTRA_PARAM_CHECKS; +#endif + + iattr->stacksize = stacksize; + iattr->stackaddr = (char *) stackaddr + stacksize; + iattr->flags |= ATTR_FLAG_STACKADDR; + + return 0; +} + +#if PTHREAD_STACK_MIN == 16384 +strong_alias(__pthread_attr_setstack, pthread_attr_setstack) +#else +weak_alias(__pthread_attr_setstack, pthread_attr_setstack) +#endif diff --git a/libpthread/nptl/pthread_attr_setstackaddr.c b/libpthread/nptl/pthread_attr_setstackaddr.c new file mode 100644 index 000000000..ead54baf0 --- /dev/null +++ b/libpthread/nptl/pthread_attr_setstackaddr.c @@ -0,0 +1,47 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include "pthreadP.h" + + +int +__pthread_attr_setstackaddr ( + pthread_attr_t *attr, + void *stackaddr) +{ + struct pthread_attr *iattr; + +#ifdef EXTRA_PARAM_CHECKS + EXTRA_PARAM_CHECKS; +#endif + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + iattr->stackaddr = stackaddr; + iattr->flags |= ATTR_FLAG_STACKADDR; + + return 0; +} +strong_alias (__pthread_attr_setstackaddr, pthread_attr_setstackaddr) + +link_warning (pthread_attr_setstackaddr, + "the use of `pthread_attr_setstackaddr' is deprecated, use `pthread_attr_setstack'") diff --git a/libpthread/nptl/pthread_attr_setstacksize.c b/libpthread/nptl/pthread_attr_setstacksize.c new file mode 100644 index 000000000..24e5b0a72 --- /dev/null +++ b/libpthread/nptl/pthread_attr_setstacksize.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include "pthreadP.h" + + +int +__pthread_attr_setstacksize ( + pthread_attr_t *attr, + size_t stacksize) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Catch invalid sizes. */ + if (stacksize < PTHREAD_STACK_MIN) + return EINVAL; + + iattr->stacksize = stacksize; + + return 0; +} + +#if PTHREAD_STACK_MIN == 16384 +strong_alias(__pthread_attr_setstacksize, pthread_attr_setstacksize) +#else +weak_alias(__pthread_attr_setstacksize, pthread_attr_setstacksize) +#endif diff --git a/libpthread/nptl/pthread_barrierattr_destroy.c b/libpthread/nptl/pthread_barrierattr_destroy.c new file mode 100644 index 000000000..5cdcb76fb --- /dev/null +++ b/libpthread/nptl/pthread_barrierattr_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 <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_barrierattr_destroy (pthread_barrierattr_t *attr) +{ + /* Nothing to do. */ + + return 0; +} diff --git a/libpthread/nptl/pthread_barrierattr_getpshared.c b/libpthread/nptl/pthread_barrierattr_getpshared.c new file mode 100644 index 000000000..ee96c0224 --- /dev/null +++ b/libpthread/nptl/pthread_barrierattr_getpshared.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_barrierattr_getpshared ( + const pthread_barrierattr_t *attr, + int *pshared) +{ + *pshared = ((const struct pthread_barrierattr *) attr)->pshared; + + return 0; +} diff --git a/libpthread/nptl/pthread_barrierattr_init.c b/libpthread/nptl/pthread_barrierattr_init.c new file mode 100644 index 000000000..17391f91c --- /dev/null +++ b/libpthread/nptl/pthread_barrierattr_init.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 <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_barrierattr_init (pthread_barrierattr_t *attr) +{ + ((struct pthread_barrierattr *) attr)->pshared = PTHREAD_PROCESS_PRIVATE; + + return 0; +} diff --git a/libpthread/nptl/pthread_barrierattr_setpshared.c b/libpthread/nptl/pthread_barrierattr_setpshared.c new file mode 100644 index 000000000..fbf6fcb21 --- /dev/null +++ b/libpthread/nptl/pthread_barrierattr_setpshared.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include "pthreadP.h" + + +int +pthread_barrierattr_setpshared ( + pthread_barrierattr_t *attr, + int pshared) +{ + struct pthread_barrierattr *iattr; + + if (pshared != PTHREAD_PROCESS_PRIVATE + && __builtin_expect (pshared != PTHREAD_PROCESS_SHARED, 0)) + return EINVAL; + + iattr = (struct pthread_barrierattr *) attr; + + iattr->pshared = pshared; + + return 0; +} diff --git a/libpthread/nptl/pthread_cancel.c b/libpthread/nptl/pthread_cancel.c new file mode 100644 index 000000000..4a958bcde --- /dev/null +++ b/libpthread/nptl/pthread_cancel.c @@ -0,0 +1,108 @@ +/* Copyright (C) 2002, 2003, 2004, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <signal.h> +#include "pthreadP.h" +#include "atomic.h" +#include <sysdep.h> +#include <bits/kernel-features.h> + + +int +pthread_cancel ( + pthread_t th) +{ + volatile struct pthread *pd = (volatile struct pthread *) th; + + /* Make sure the descriptor is valid. */ + if (INVALID_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + +#ifdef SHARED + pthread_cancel_init (); +#endif + int result = 0; + int oldval; + int newval; + do + { + again: + oldval = pd->cancelhandling; + newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK; + + /* Avoid doing unnecessary work. The atomic operation can + potentially be expensive if the bug has to be locked and + remote cache lines have to be invalidated. */ + if (oldval == newval) + break; + + /* If the cancellation is handled asynchronously just send a + signal. We avoid this if possible since it's more + expensive. */ + if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval)) + { + /* Mark the cancellation as "in progress". */ + if (atomic_compare_and_exchange_bool_acq (&pd->cancelhandling, + oldval | CANCELING_BITMASK, + oldval)) + goto again; + + /* The cancellation handler will take care of marking the + thread as canceled. */ + INTERNAL_SYSCALL_DECL (err); + + /* One comment: The PID field in the TCB can temporarily be + changed (in fork). But this must not affect this code + here. Since this function would have to be called while + the thread is executing fork, it would have to happen in + a signal handler. But this is no allowed, pthread_cancel + is not guaranteed to be async-safe. */ + int val; +#if __ASSUME_TGKILL + val = INTERNAL_SYSCALL (tgkill, err, 3, + THREAD_GETMEM (THREAD_SELF, pid), pd->tid, + SIGCANCEL); +#else +# ifdef __NR_tgkill + val = INTERNAL_SYSCALL (tgkill, err, 3, + THREAD_GETMEM (THREAD_SELF, pid), pd->tid, + SIGCANCEL); + if (INTERNAL_SYSCALL_ERROR_P (val, err) + && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS) +# endif + val = INTERNAL_SYSCALL (tkill, err, 2, pd->tid, SIGCANCEL); +#endif + + if (INTERNAL_SYSCALL_ERROR_P (val, err)) + result = INTERNAL_SYSCALL_ERRNO (val, err); + + break; + } + } + /* Mark the thread as canceled. This has to be done + atomically since other bits could be modified as well. */ + while (atomic_compare_and_exchange_bool_acq (&pd->cancelhandling, newval, + oldval)); + + return result; +} + +PTHREAD_STATIC_FN_REQUIRE (pthread_create) diff --git a/libpthread/nptl/pthread_clock_gettime.c b/libpthread/nptl/pthread_clock_gettime.c new file mode 100644 index 000000000..a71174c9c --- /dev/null +++ b/libpthread/nptl/pthread_clock_gettime.c @@ -0,0 +1,69 @@ +/* Copyright (C) 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 <errno.h> +#include <stdlib.h> +#include <time.h> +#include <libc-internal.h> +#include "pthreadP.h" + + +#if HP_TIMING_AVAIL +int +__pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq, + struct timespec *tp) +{ + hp_timing_t tsc; + + /* Get the current counter. */ + HP_TIMING_NOW (tsc); + + /* This is the ID of the thread we are looking for. */ + pid_t tid = ((unsigned int) clock_id) >> CLOCK_IDFIELD_SIZE; + + /* Compute the offset since the start time of the process. */ + if (tid == 0 || tid == THREAD_GETMEM (THREAD_SELF, tid)) + /* Our own clock. */ + tsc -= THREAD_GETMEM (THREAD_SELF, cpuclock_offset); + else + { + /* This is more complicated. We have to locate the thread based + on the ID. This means walking the list of existing + threads. */ + struct pthread *thread = __find_thread_by_id (tid); + if (thread == NULL) + { + __set_errno (EINVAL); + return -1; + } + + /* There is a race here. The thread might terminate and the stack + become unusable. But this is the user's problem. */ + tsc -= thread->cpuclock_offset; + } + + /* Compute the seconds. */ + tp->tv_sec = tsc / freq; + + /* And the nanoseconds. This computation should be stable until + we get machines with about 16GHz frequency. */ + tp->tv_nsec = ((tsc % freq) * 1000000000ull) / freq; + + return 0; +} +#endif diff --git a/libpthread/nptl/pthread_clock_settime.c b/libpthread/nptl/pthread_clock_settime.c new file mode 100644 index 000000000..61002a8f7 --- /dev/null +++ b/libpthread/nptl/pthread_clock_settime.c @@ -0,0 +1,56 @@ +/* Copyright (C) 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 <errno.h> +#include <stdlib.h> +#include <time.h> +#include <libc-internal.h> +#include "pthreadP.h" + + +#if HP_TIMING_AVAIL +int +__pthread_clock_settime (clockid_t clock_id, hp_timing_t offset) +{ + /* This is the ID of the thread we are looking for. */ + pid_t tid = ((unsigned int) clock_id) >> CLOCK_IDFIELD_SIZE; + + /* Compute the offset since the start time of the process. */ + if (tid == 0 || tid == THREAD_GETMEM (THREAD_SELF, tid)) + /* Our own clock. */ + THREAD_SETMEM (THREAD_SELF, cpuclock_offset, offset); + else + { + /* This is more complicated. We have to locate the thread based + on the ID. This means walking the list of existing + threads. */ + struct pthread *thread = __find_thread_by_id (tid); + if (thread == NULL) + { + __set_errno (EINVAL); + return -1; + } + + /* There is a race here. The thread might terminate and the stack + become unusable. But this is the user's problem. */ + thread->cpuclock_offset = offset; + } + + return 0; +} +#endif diff --git a/libpthread/nptl/pthread_cond_destroy.c b/libpthread/nptl/pthread_cond_destroy.c new file mode 100644 index 000000000..6f13d97a4 --- /dev/null +++ b/libpthread/nptl/pthread_cond_destroy.c @@ -0,0 +1,84 @@ +/* Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include "pthreadP.h" + + +int +attribute_hidden +__pthread_cond_destroy ( + pthread_cond_t *cond) +{ + int pshared = (cond->__data.__mutex == (void *) ~0l) + ? LLL_SHARED : LLL_PRIVATE; + + /* Make sure we are alone. */ + lll_lock (cond->__data.__lock, pshared); + + if (cond->__data.__total_seq > cond->__data.__wakeup_seq) + { + /* If there are still some waiters which have not been + woken up, this is an application bug. */ + lll_unlock (cond->__data.__lock, pshared); + return EBUSY; + } + + /* Tell pthread_cond_*wait that this condvar is being destroyed. */ + cond->__data.__total_seq = -1ULL; + + /* If there are waiters which have been already signalled or + broadcasted, but still are using the pthread_cond_t structure, + pthread_cond_destroy needs to wait for them. */ + unsigned int nwaiters = cond->__data.__nwaiters; + + if (nwaiters >= (1 << COND_NWAITERS_SHIFT)) + { + /* Wake everybody on the associated mutex in case there are + threads that have been requeued to it. + Without this, pthread_cond_destroy could block potentially + for a long time or forever, as it would depend on other + thread's using the mutex. + When all threads waiting on the mutex are woken up, pthread_cond_wait + only waits for threads to acquire and release the internal + condvar lock. */ + if (cond->__data.__mutex != NULL + && cond->__data.__mutex != (void *) ~0l) + { + pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex; + lll_futex_wake (&mut->__data.__lock, INT_MAX, + PTHREAD_MUTEX_PSHARED (mut)); + } + + do + { + lll_unlock (cond->__data.__lock, pshared); + + lll_futex_wait (&cond->__data.__nwaiters, nwaiters, pshared); + + lll_lock (cond->__data.__lock, pshared); + + nwaiters = cond->__data.__nwaiters; + } + while (nwaiters >= (1 << COND_NWAITERS_SHIFT)); + } + + return 0; +} +weak_alias(__pthread_cond_destroy, pthread_cond_destroy) diff --git a/libpthread/nptl/pthread_cond_init.c b/libpthread/nptl/pthread_cond_init.c new file mode 100644 index 000000000..e7a18e454 --- /dev/null +++ b/libpthread/nptl/pthread_cond_init.c @@ -0,0 +1,47 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +attribute_hidden +__pthread_cond_init ( + pthread_cond_t *cond, + const pthread_condattr_t *cond_attr) +{ + struct pthread_condattr *icond_attr = (struct pthread_condattr *) cond_attr; + + cond->__data.__lock = LLL_LOCK_INITIALIZER; + cond->__data.__futex = 0; + cond->__data.__nwaiters = (icond_attr != NULL + ? ((icond_attr->value >> 1) + & ((1 << COND_NWAITERS_SHIFT) - 1)) + : CLOCK_REALTIME); + cond->__data.__total_seq = 0; + cond->__data.__wakeup_seq = 0; + cond->__data.__woken_seq = 0; + cond->__data.__mutex = (icond_attr == NULL || (icond_attr->value & 1) == 0 + ? NULL : (void *) ~0l); + cond->__data.__broadcast_seq = 0; + + return 0; +} +weak_alias(__pthread_cond_init, pthread_cond_init) diff --git a/libpthread/nptl/pthread_condattr_destroy.c b/libpthread/nptl/pthread_condattr_destroy.c new file mode 100644 index 000000000..b0da06094 --- /dev/null +++ b/libpthread/nptl/pthread_condattr_destroy.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +attribute_hidden +__pthread_condattr_destroy (pthread_condattr_t *attr) +{ + /* Nothing to be done. */ + return 0; +} +strong_alias (__pthread_condattr_destroy, pthread_condattr_destroy) diff --git a/libpthread/nptl/pthread_condattr_getclock.c b/libpthread/nptl/pthread_condattr_getclock.c new file mode 100644 index 000000000..3603f848d --- /dev/null +++ b/libpthread/nptl/pthread_condattr_getclock.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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_condattr_getclock ( + const pthread_condattr_t *attr, + clockid_t *clock_id) +{ + *clock_id = (((((const struct pthread_condattr *) attr)->value) >> 1) + & ((1 << COND_NWAITERS_SHIFT) - 1)); + return 0; +} diff --git a/libpthread/nptl/pthread_condattr_getpshared.c b/libpthread/nptl/pthread_condattr_getpshared.c new file mode 100644 index 000000000..a558fdb8e --- /dev/null +++ b/libpthread/nptl/pthread_condattr_getpshared.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_condattr_getpshared ( + const pthread_condattr_t *attr, + int *pshared) +{ + *pshared = ((const struct pthread_condattr *) attr)->value & 1; + + return 0; +} diff --git a/libpthread/nptl/pthread_condattr_init.c b/libpthread/nptl/pthread_condattr_init.c new file mode 100644 index 000000000..05ab6a2b4 --- /dev/null +++ b/libpthread/nptl/pthread_condattr_init.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <string.h> +#include "pthreadP.h" + + +int +attribute_hidden +__pthread_condattr_init (pthread_condattr_t *attr) +{ + memset (attr, '\0', sizeof (*attr)); + + return 0; +} +strong_alias (__pthread_condattr_init, pthread_condattr_init) diff --git a/libpthread/nptl/pthread_condattr_setclock.c b/libpthread/nptl/pthread_condattr_setclock.c new file mode 100644 index 000000000..87597c8b5 --- /dev/null +++ b/libpthread/nptl/pthread_condattr_setclock.c @@ -0,0 +1,73 @@ +/* Copyright (C) 2003, 2004, 2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 <assert.h> +#include <errno.h> +#include <stdbool.h> +#include <time.h> +#include <sysdep.h> +#include "pthreadP.h" +#include <bits/kernel-features.h> + + +int +pthread_condattr_setclock ( + pthread_condattr_t *attr, + clockid_t clock_id) +{ + /* Only a few clocks are allowed. CLOCK_REALTIME is always allowed. + CLOCK_MONOTONIC only if the kernel has the necessary support. */ + if (clock_id == CLOCK_MONOTONIC) + { +#ifndef __ASSUME_POSIX_TIMERS +# ifdef __NR_clock_getres + /* Check whether the clock is available. */ + static int avail; + + if (avail == 0) + { + struct timespec ts; + + INTERNAL_SYSCALL_DECL (err); + int val; + val = INTERNAL_SYSCALL (clock_getres, err, 2, CLOCK_MONOTONIC, &ts); + avail = INTERNAL_SYSCALL_ERROR_P (val, err) ? -1 : 1; + } + + if (avail < 0) +# endif + /* Not available. */ + return EINVAL; +#endif + } + else if (clock_id != CLOCK_REALTIME) + /* If more clocks are allowed some day the storing of the clock ID + in the pthread_cond_t structure needs to be adjusted. */ + return EINVAL; + + /* Make sure the value fits in the bits we reserved. */ + assert (clock_id < (1 << COND_NWAITERS_SHIFT)); + + int *valuep = &((struct pthread_condattr *) attr)->value; + + *valuep = ((*valuep & ~(((1 << COND_NWAITERS_SHIFT) - 1) << 1)) + | (clock_id << 1)); + + return 0; +} diff --git a/libpthread/nptl/pthread_condattr_setpshared.c b/libpthread/nptl/pthread_condattr_setpshared.c new file mode 100644 index 000000000..f3d39aa2b --- /dev/null +++ b/libpthread/nptl/pthread_condattr_setpshared.c @@ -0,0 +1,37 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <pthreadP.h> + +int +pthread_condattr_setpshared ( + pthread_condattr_t *attr, + int pshared) +{ + if (pshared != PTHREAD_PROCESS_PRIVATE + && __builtin_expect (pshared != PTHREAD_PROCESS_SHARED, 0)) + return EINVAL; + + int *valuep = &((struct pthread_condattr *) attr)->value; + + *valuep = (*valuep & ~1) | (pshared != PTHREAD_PROCESS_PRIVATE); + + return 0; +} diff --git a/libpthread/nptl/pthread_create.c b/libpthread/nptl/pthread_create.c new file mode 100644 index 000000000..0825873af --- /dev/null +++ b/libpthread/nptl/pthread_create.c @@ -0,0 +1,586 @@ +/* Copyright (C) 2002-2007,2008,2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include "pthreadP.h" +#include <hp-timing.h> +#include <ldsodefs.h> +#include <atomic.h> +#include <libc-internal.h> +#include <resolv.h> +#include <bits/kernel-features.h> + + +/* Local function to start thread and handle cleanup. */ +static int start_thread (void *arg); + + +/* Nozero if debugging mode is enabled. */ +int __pthread_debug; + +/* Globally enabled events. */ +static td_thr_events_t __nptl_threads_events __attribute_used__; + +/* Pointer to descriptor with the last event. */ +static struct pthread *__nptl_last_event __attribute_used__; + +/* Number of threads running. */ +unsigned int attribute_hidden __nptl_nthreads = 1; + + +/* Code to allocate and deallocate a stack. */ +#include "allocatestack.c" + +/* Code to create the thread. */ +#include <createthread.c> + + +struct pthread * +internal_function +__find_in_stack_list ( + struct pthread *pd) +{ + list_t *entry; + struct pthread *result = NULL; + + lll_lock (stack_cache_lock, LLL_PRIVATE); + + list_for_each (entry, &stack_used) + { + struct pthread *curp; + + curp = list_entry (entry, struct pthread, list); + if (curp == pd) + { + result = curp; + break; + } + } + + if (result == NULL) + list_for_each (entry, &__stack_user) + { + struct pthread *curp; + + curp = list_entry (entry, struct pthread, list); + if (curp == pd) + { + result = curp; + break; + } + } + + lll_unlock (stack_cache_lock, LLL_PRIVATE); + + return result; +} + + +/* Deallocate POSIX thread-local-storage. */ +void +attribute_hidden +__nptl_deallocate_tsd (void) +{ + struct pthread *self = THREAD_SELF; + + /* Maybe no data was ever allocated. This happens often so we have + a flag for this. */ + if (THREAD_GETMEM (self, specific_used)) + { + size_t round; + size_t cnt; + + round = 0; + do + { + size_t idx; + + /* So far no new nonzero data entry. */ + THREAD_SETMEM (self, specific_used, false); + + for (cnt = idx = 0; cnt < PTHREAD_KEY_1STLEVEL_SIZE; ++cnt) + { + struct pthread_key_data *level2; + + level2 = THREAD_GETMEM_NC (self, specific, cnt); + + if (level2 != NULL) + { + size_t inner; + + for (inner = 0; inner < PTHREAD_KEY_2NDLEVEL_SIZE; + ++inner, ++idx) + { + void *data = level2[inner].data; + + if (data != NULL) + { + /* Always clear the data. */ + level2[inner].data = NULL; + + /* Make sure the data corresponds to a valid + key. This test fails if the key was + deallocated and also if it was + re-allocated. It is the user's + responsibility to free the memory in this + case. */ + if (level2[inner].seq + == __pthread_keys[idx].seq + /* It is not necessary to register a destructor + function. */ + && __pthread_keys[idx].destr != NULL) + /* Call the user-provided destructor. */ + __pthread_keys[idx].destr (data); + } + } + } + else + idx += PTHREAD_KEY_1STLEVEL_SIZE; + } + + if (THREAD_GETMEM (self, specific_used) == 0) + /* No data has been modified. */ + goto just_free; + } + /* We only repeat the process a fixed number of times. */ + while (__builtin_expect (++round < PTHREAD_DESTRUCTOR_ITERATIONS, 0)); + + /* Just clear the memory of the first block for reuse. */ + memset (&THREAD_SELF->specific_1stblock, '\0', + sizeof (self->specific_1stblock)); + + just_free: + /* Free the memory for the other blocks. */ + for (cnt = 1; cnt < PTHREAD_KEY_1STLEVEL_SIZE; ++cnt) + { + struct pthread_key_data *level2; + + level2 = THREAD_GETMEM_NC (self, specific, cnt); + if (level2 != NULL) + { + /* The first block is allocated as part of the thread + descriptor. */ + free (level2); + THREAD_SETMEM_NC (self, specific, cnt, NULL); + } + } + + THREAD_SETMEM (self, specific_used, false); + } +} + + +/* Deallocate a thread's stack after optionally making sure the thread + descriptor is still valid. */ +void +internal_function +__free_tcb (struct pthread *pd) +{ + /* The thread is exiting now. */ + if (__builtin_expect (atomic_bit_test_set (&pd->cancelhandling, + TERMINATED_BIT) == 0, 1)) + { + /* Remove the descriptor from the list. */ + if (DEBUGGING_P && __find_in_stack_list (pd) == NULL) + /* Something is really wrong. The descriptor for a still + running thread is gone. */ + abort (); + + /* Free TPP data. */ + if (__builtin_expect (pd->tpp != NULL, 0)) + { + struct priority_protection_data *tpp = pd->tpp; + + pd->tpp = NULL; + free (tpp); + } + + /* Queue the stack memory block for reuse and exit the process. The + kernel will signal via writing to the address returned by + QUEUE-STACK when the stack is available. */ + __deallocate_stack (pd); + } +} + + +static int +start_thread (void *arg) +{ + struct pthread *pd = (struct pthread *) arg; + +#if HP_TIMING_AVAIL + /* Remember the time when the thread was started. */ + hp_timing_t now; + HP_TIMING_NOW (now); + THREAD_SETMEM (pd, cpuclock_offset, now); +#endif + + /* Initialize resolver state pointer. */ + __resp = &pd->res; + +#ifdef __NR_set_robust_list +# ifndef __ASSUME_SET_ROBUST_LIST + if (__set_robust_list_avail >= 0) +# endif + { + INTERNAL_SYSCALL_DECL (err); + /* This call should never fail because the initial call in init.c + succeeded. */ + INTERNAL_SYSCALL (set_robust_list, err, 2, &pd->robust_head, + sizeof (struct robust_list_head)); + } +#endif + + /* If the parent was running cancellation handlers while creating + the thread the new thread inherited the signal mask. Reset the + cancellation signal mask. */ + if (__builtin_expect (pd->parent_cancelhandling & CANCELING_BITMASK, 0)) + { + INTERNAL_SYSCALL_DECL (err); + sigset_t mask; + __sigemptyset (&mask); + __sigaddset (&mask, SIGCANCEL); + (void) INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_UNBLOCK, &mask, + NULL, _NSIG / 8); + } + + /* This is where the try/finally block should be created. For + compilers without that support we do use setjmp. */ + struct pthread_unwind_buf unwind_buf; + + /* No previous handlers. */ + unwind_buf.priv.data.prev = NULL; + unwind_buf.priv.data.cleanup = NULL; + + int not_first_call; + not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf); + if (__builtin_expect (! not_first_call, 1)) + { + /* Store the new cleanup handler info. */ + THREAD_SETMEM (pd, cleanup_jmp_buf, &unwind_buf); + + if (__builtin_expect (pd->stopped_start, 0)) + { + int oldtype = CANCEL_ASYNC (); + + /* Get the lock the parent locked to force synchronization. */ + lll_lock (pd->lock, LLL_PRIVATE); + /* And give it up right away. */ + lll_unlock (pd->lock, LLL_PRIVATE); + + CANCEL_RESET (oldtype); + } + + /* Run the code the user provided. */ +#ifdef CALL_THREAD_FCT + THREAD_SETMEM (pd, result, CALL_THREAD_FCT (pd)); +#else + THREAD_SETMEM (pd, result, pd->start_routine (pd->arg)); +#endif + } + + /* Run the destructor for the thread-local data. */ + __nptl_deallocate_tsd (); + + /* Clean up any state libc stored in thread-local variables. */ + /* disable for now + __libc_thread_freeres (); + */ + /* If this is the last thread we terminate the process now. We + do not notify the debugger, it might just irritate it if there + is no thread left. */ + if (__builtin_expect (atomic_decrement_and_test (&__nptl_nthreads), 0)) + /* This was the last thread. */ + exit (0); + + /* Report the death of the thread if this is wanted. */ + if (__builtin_expect (pd->report_events, 0)) + { + /* See whether TD_DEATH is in any of the mask. */ + const int idx = __td_eventword (TD_DEATH); + const uint32_t mask = __td_eventmask (TD_DEATH); + + if ((mask & (__nptl_threads_events.event_bits[idx] + | pd->eventbuf.eventmask.event_bits[idx])) != 0) + { + /* Yep, we have to signal the death. Add the descriptor to + the list but only if it is not already on it. */ + if (pd->nextevent == NULL) + { + pd->eventbuf.eventnum = TD_DEATH; + pd->eventbuf.eventdata = pd; + + do + pd->nextevent = __nptl_last_event; + while (atomic_compare_and_exchange_bool_acq (&__nptl_last_event, + pd, pd->nextevent)); + } + + /* Now call the function to signal the event. */ + __nptl_death_event (); + } + } + + /* The thread is exiting now. Don't set this bit until after we've hit + the event-reporting breakpoint, so that td_thr_get_info on us while at + the breakpoint reports TD_THR_RUN state rather than TD_THR_ZOMBIE. */ + atomic_bit_set (&pd->cancelhandling, EXITING_BIT); + +#ifndef __ASSUME_SET_ROBUST_LIST + /* If this thread has any robust mutexes locked, handle them now. */ +# if __WORDSIZE == 64 + void *robust = pd->robust_head.list; +# else + __pthread_slist_t *robust = pd->robust_list.__next; +# endif + /* We let the kernel do the notification if it is able to do so. + If we have to do it here there for sure are no PI mutexes involved + since the kernel support for them is even more recent. */ + if (__set_robust_list_avail < 0 + && __builtin_expect (robust != (void *) &pd->robust_head, 0)) + { + do + { + struct __pthread_mutex_s *this = (struct __pthread_mutex_s *) + ((char *) robust - offsetof (struct __pthread_mutex_s, + __list.__next)); + robust = *((void **) robust); + +# ifdef __PTHREAD_MUTEX_HAVE_PREV + this->__list.__prev = NULL; +# endif + this->__list.__next = NULL; + + lll_robust_dead (this->__lock, /* XYZ */ LLL_SHARED); + } + while (robust != (void *) &pd->robust_head); + } +#endif + + /* Mark the memory of the stack as usable to the kernel. We free + everything except for the space used for the TCB itself. */ + size_t pagesize_m1 = __getpagesize () - 1; +#ifdef _STACK_GROWS_DOWN + char *sp = CURRENT_STACK_FRAME; + size_t freesize = (sp - (char *) pd->stackblock) & ~pagesize_m1; +#else +# error "to do" +#endif + assert (freesize < pd->stackblock_size); + if (freesize > PTHREAD_STACK_MIN) + madvise (pd->stackblock, freesize - PTHREAD_STACK_MIN, MADV_DONTNEED); + + /* If the thread is detached free the TCB. */ + if (IS_DETACHED (pd)) + /* Free the TCB. */ + __free_tcb (pd); + else if (__builtin_expect (pd->cancelhandling & SETXID_BITMASK, 0)) + { + /* Some other thread might call any of the setXid functions and expect + us to reply. In this case wait until we did that. */ + do + lll_futex_wait (&pd->setxid_futex, 0, LLL_PRIVATE); + while (pd->cancelhandling & SETXID_BITMASK); + + /* Reset the value so that the stack can be reused. */ + pd->setxid_futex = 0; + } + + /* We cannot call '_exit' here. '_exit' will terminate the process. + + The 'exit' implementation in the kernel will signal when the + process is really dead since 'clone' got passed the CLONE_CLEARTID + flag. The 'tid' field in the TCB will be set to zero. + + The exit code is zero since in case all threads exit by calling + 'pthread_exit' the exit status must be 0 (zero). */ + __exit_thread_inline (0); + + /* NOTREACHED */ + return 0; +} + + +/* Default thread attributes for the case when the user does not + provide any. */ +static const struct pthread_attr default_attr = + { + /* Just some value > 0 which gets rounded to the nearest page size. */ + .guardsize = 1, + }; + + +int +__pthread_create_2_1 ( + pthread_t *newthread, + const pthread_attr_t *attr, + void *(*start_routine) (void *), + void *arg) +{ + STACK_VARIABLES; + + const struct pthread_attr *iattr = (struct pthread_attr *) attr; + if (iattr == NULL) + /* Is this the best idea? On NUMA machines this could mean + accessing far-away memory. */ + iattr = &default_attr; + + struct pthread *pd = NULL; + int err = ALLOCATE_STACK (iattr, &pd); + if (__builtin_expect (err != 0, 0)) + /* Something went wrong. Maybe a parameter of the attributes is + invalid or we could not allocate memory. */ + return err; + + + /* Initialize the TCB. All initializations with zero should be + performed in 'get_cached_stack'. This way we avoid doing this if + the stack freshly allocated with 'mmap'. */ + +#ifdef TLS_TCB_AT_TP + /* Reference to the TCB itself. */ + pd->header.self = pd; + + /* Self-reference for TLS. */ + pd->header.tcb = pd; +#endif + + /* Store the address of the start routine and the parameter. Since + we do not start the function directly the stillborn thread will + get the information from its thread descriptor. */ + pd->start_routine = start_routine; + pd->arg = arg; + + /* Copy the thread attribute flags. */ + struct pthread *self = THREAD_SELF; + pd->flags = ((iattr->flags & ~(ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET)) + | (self->flags & (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET))); + + /* Initialize the field for the ID of the thread which is waiting + for us. This is a self-reference in case the thread is created + detached. */ + pd->joinid = iattr->flags & ATTR_FLAG_DETACHSTATE ? pd : NULL; + + /* The debug events are inherited from the parent. */ + pd->eventbuf = self->eventbuf; + + + /* Copy the parent's scheduling parameters. The flags will say what + is valid and what is not. */ + pd->schedpolicy = self->schedpolicy; + pd->schedparam = self->schedparam; + + /* Copy the stack guard canary. */ +#ifdef THREAD_COPY_STACK_GUARD + THREAD_COPY_STACK_GUARD (pd); +#endif + + /* Copy the pointer guard value. */ +#ifdef THREAD_COPY_POINTER_GUARD + THREAD_COPY_POINTER_GUARD (pd); +#endif + + /* Determine scheduling parameters for the thread. */ + if (attr != NULL + && __builtin_expect ((iattr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0, 0) + && (iattr->flags & (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET)) != 0) + { + INTERNAL_SYSCALL_DECL (scerr); + + /* Use the scheduling parameters the user provided. */ + if (iattr->flags & ATTR_FLAG_POLICY_SET) + pd->schedpolicy = iattr->schedpolicy; + else if ((pd->flags & ATTR_FLAG_POLICY_SET) == 0) + { + pd->schedpolicy = INTERNAL_SYSCALL (sched_getscheduler, scerr, 1, 0); + pd->flags |= ATTR_FLAG_POLICY_SET; + } + + if (iattr->flags & ATTR_FLAG_SCHED_SET) + memcpy (&pd->schedparam, &iattr->schedparam, + sizeof (struct sched_param)); + else if ((pd->flags & ATTR_FLAG_SCHED_SET) == 0) + { + INTERNAL_SYSCALL (sched_getparam, scerr, 2, 0, &pd->schedparam); + pd->flags |= ATTR_FLAG_SCHED_SET; + } + + /* Check for valid priorities. */ + int minprio = INTERNAL_SYSCALL (sched_get_priority_min, scerr, 1, + iattr->schedpolicy); + int maxprio = INTERNAL_SYSCALL (sched_get_priority_max, scerr, 1, + iattr->schedpolicy); + if (pd->schedparam.sched_priority < minprio + || pd->schedparam.sched_priority > maxprio) + { + err = EINVAL; + goto errout; + } + } + + /* Pass the descriptor to the caller. */ + *newthread = (pthread_t) pd; + + /* Remember whether the thread is detached or not. In case of an + error we have to free the stacks of non-detached stillborn + threads. */ + bool is_detached = IS_DETACHED (pd); + + /* Start the thread. */ + err = create_thread (pd, iattr, STACK_VARIABLES_ARGS); + if (err != 0) + { + /* Something went wrong. Free the resources. */ + if (!is_detached) + { + errout: + __deallocate_stack (pd); + } + return err; + } + + return 0; +} +weak_alias(__pthread_create_2_1, pthread_create) + +/* Information for libthread_db. */ + +#include "../nptl_db/db_info.c" + +/* If pthread_create is present, libgcc_eh.a and libsupc++.a expects some other POSIX thread + functions to be present as well. */ +PTHREAD_STATIC_FN_REQUIRE (pthread_mutex_lock) +PTHREAD_STATIC_FN_REQUIRE (pthread_mutex_trylock) +PTHREAD_STATIC_FN_REQUIRE (pthread_mutex_unlock) + +PTHREAD_STATIC_FN_REQUIRE (pthread_once) +PTHREAD_STATIC_FN_REQUIRE (pthread_cancel) + +PTHREAD_STATIC_FN_REQUIRE (pthread_key_create) +PTHREAD_STATIC_FN_REQUIRE (pthread_key_delete) +PTHREAD_STATIC_FN_REQUIRE (pthread_setspecific) +PTHREAD_STATIC_FN_REQUIRE (pthread_getspecific) + +/* UCLIBC_MUTEX_xxx macros expects to have these as well */ +PTHREAD_STATIC_FN_REQUIRE (pthread_mutex_init) +PTHREAD_STATIC_FN_REQUIRE (_pthread_cleanup_push_defer) +PTHREAD_STATIC_FN_REQUIRE (_pthread_cleanup_pop_restore) diff --git a/libpthread/nptl/pthread_detach.c b/libpthread/nptl/pthread_detach.c new file mode 100644 index 000000000..054d7793a --- /dev/null +++ b/libpthread/nptl/pthread_detach.c @@ -0,0 +1,56 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include "pthreadP.h" +#include <atomic.h> + + +int +pthread_detach (pthread_t th) +{ + struct pthread *pd = (struct pthread *) th; + + /* Make sure the descriptor is valid. */ + if (INVALID_NOT_TERMINATED_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + + int result = 0; + + /* Mark the thread as detached. */ + if (atomic_compare_and_exchange_bool_acq (&pd->joinid, pd, NULL)) + { + /* There are two possibilities here. First, the thread might + already be detached. In this case we return EINVAL. + Otherwise there might already be a waiter. The standard does + not mention what happens in this case. */ + if (IS_DETACHED (pd)) + result = EINVAL; + } + else + /* Check whether the thread terminated meanwhile. In this case we + will just free the TCB. */ + if ((pd->cancelhandling & EXITING_BITMASK) != 0) + /* Note that the code in __free_tcb makes sure each thread + control block is freed only once. */ + __free_tcb (pd); + + return result; +} diff --git a/libpthread/nptl/pthread_equal.c b/libpthread/nptl/pthread_equal.c new file mode 100644 index 000000000..4c9a24caf --- /dev/null +++ b/libpthread/nptl/pthread_equal.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 <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +attribute_hidden +__pthread_equal (pthread_t thread1, pthread_t thread2) +{ + return thread1 == thread2; +} +strong_alias (__pthread_equal, pthread_equal) diff --git a/libpthread/nptl/pthread_exit.c b/libpthread/nptl/pthread_exit.c new file mode 100644 index 000000000..de43cb886 --- /dev/null +++ b/libpthread/nptl/pthread_exit.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stdlib.h> +#include "pthreadP.h" + + +void +attribute_hidden +__pthread_exit (void* value) +{ + THREAD_SETMEM (THREAD_SELF, result, value); + + __do_cancel (); +} +strong_alias (__pthread_exit, pthread_exit) diff --git a/libpthread/nptl/pthread_getattr_np.c b/libpthread/nptl/pthread_getattr_np.c new file mode 100644 index 000000000..86a43853d --- /dev/null +++ b/libpthread/nptl/pthread_getattr_np.c @@ -0,0 +1,179 @@ +/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdio_ext.h> +#include <stdlib.h> +#include <string.h> +#include <sys/resource.h> +#include "pthreadP.h" +#include <lowlevellock.h> +#include <ldsodefs.h> + + +int +pthread_getattr_np ( + pthread_t thread_id, + pthread_attr_t *attr) +{ + struct pthread *thread = (struct pthread *) thread_id; + struct pthread_attr *iattr = (struct pthread_attr *) attr; + int ret = 0; + + lll_lock (thread->lock, LLL_PRIVATE); + + /* The thread library is responsible for keeping the values in the + thread desriptor up-to-date in case the user changes them. */ + memcpy (&iattr->schedparam, &thread->schedparam, + sizeof (struct sched_param)); + iattr->schedpolicy = thread->schedpolicy; + + /* Clear the flags work. */ + iattr->flags = thread->flags; + + /* The thread might be detached by now. */ + if (IS_DETACHED (thread)) + iattr->flags |= ATTR_FLAG_DETACHSTATE; + + /* This is the guardsize after adjusting it. */ + iattr->guardsize = thread->reported_guardsize; + + /* The sizes are subject to alignment. */ + if (__builtin_expect (thread->stackblock != NULL, 1)) + { + iattr->stacksize = thread->stackblock_size; + iattr->stackaddr = (char *) thread->stackblock + iattr->stacksize; + } + else + { + /* No stack information available. This must be for the initial + thread. Get the info in some magical way. */ + assert (abs (thread->pid) == thread->tid); + + /* Stack size limit. */ + struct rlimit rl; + + /* The safest way to get the top of the stack is to read + /proc/self/maps and locate the line into which + __libc_stack_end falls. */ + FILE *fp = fopen ("/proc/self/maps", "rc"); + if (fp == NULL) + ret = errno; + /* We need the limit of the stack in any case. */ + else + { + if (getrlimit (RLIMIT_STACK, &rl) != 0) + ret = errno; + else + { + /* We need no locking. */ + __fsetlocking (fp, FSETLOCKING_BYCALLER); + + /* Until we found an entry (which should always be the case) + mark the result as a failure. */ + ret = ENOENT; + + char *line = NULL; + size_t linelen = 0; + uintptr_t last_to = 0; + + while (! feof_unlocked (fp)) + { + if (getdelim (&line, &linelen, '\n', fp) <= 0) + break; + + uintptr_t from; + uintptr_t to; + if (sscanf (line, "%" SCNxPTR "-%" SCNxPTR, &from, &to) != 2) + continue; + if (from <= (uintptr_t) __libc_stack_end + && (uintptr_t) __libc_stack_end < to) + { + /* Found the entry. Now we have the info we need. */ + iattr->stacksize = rl.rlim_cur; + iattr->stackaddr = (void *) to; + + /* The limit might be too high. */ + if ((size_t) iattr->stacksize + > (size_t) iattr->stackaddr - last_to) + iattr->stacksize = (size_t) iattr->stackaddr - last_to; + + /* We succeed and no need to look further. */ + ret = 0; + break; + } + last_to = to; + } + + free (line); + } + + fclose (fp); + } + } + + iattr->flags |= ATTR_FLAG_STACKADDR; + + if (ret == 0) + { + size_t size = 16; + cpu_set_t *cpuset = NULL; + + do + { + size <<= 1; + + void *newp = realloc (cpuset, size); + if (newp == NULL) + { + ret = ENOMEM; + break; + } + cpuset = (cpu_set_t *) newp; + + ret = __pthread_getaffinity_np (thread_id, size, cpuset); + } + /* Pick some ridiculous upper limit. Is 8 million CPUs enough? */ + while (ret == EINVAL && size < 1024 * 1024); + + if (ret == 0) + { + iattr->cpuset = cpuset; + iattr->cpusetsize = size; + } + else + { + free (cpuset); + if (ret == ENOSYS) + { + /* There is no such functionality. */ + ret = 0; + iattr->cpuset = NULL; + iattr->cpusetsize = 0; + } + } + } + + lll_unlock (thread->lock, LLL_PRIVATE); + + return ret; +} diff --git a/libpthread/nptl/pthread_getconcurrency.c b/libpthread/nptl/pthread_getconcurrency.c new file mode 100644 index 000000000..52c0c7cbe --- /dev/null +++ b/libpthread/nptl/pthread_getconcurrency.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_getconcurrency (void) +{ + return __concurrency_level; +} diff --git a/libpthread/nptl/pthread_getschedparam.c b/libpthread/nptl/pthread_getschedparam.c new file mode 100644 index 000000000..9c6ea27ec --- /dev/null +++ b/libpthread/nptl/pthread_getschedparam.c @@ -0,0 +1,76 @@ +/* Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <string.h> +#include "pthreadP.h" +#include <lowlevellock.h> + + +int +attribute_hidden +__pthread_getschedparam ( + pthread_t threadid, + int *policy, + struct sched_param *param) +{ + struct pthread *pd = (struct pthread *) threadid; + + /* Make sure the descriptor is valid. */ + if (INVALID_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + + int result = 0; + + lll_lock (pd->lock, LLL_PRIVATE); + + /* The library is responsible for maintaining the values at all + times. If the user uses a interface other than + pthread_setschedparam to modify the scheduler setting it is not + the library's problem. In case the descriptor's values have + not yet been retrieved do it now. */ + if ((pd->flags & ATTR_FLAG_SCHED_SET) == 0) + { + if (sched_getparam (pd->tid, &pd->schedparam) != 0) + result = 1; + else + pd->flags |= ATTR_FLAG_SCHED_SET; + } + + if ((pd->flags & ATTR_FLAG_POLICY_SET) == 0) + { + pd->schedpolicy = sched_getscheduler (pd->tid); + if (pd->schedpolicy == -1) + result = 1; + else + pd->flags |= ATTR_FLAG_POLICY_SET; + } + + if (result == 0) + { + *policy = pd->schedpolicy; + memcpy (param, &pd->schedparam, sizeof (struct sched_param)); + } + + lll_unlock (pd->lock, LLL_PRIVATE); + + return result; +} +strong_alias (__pthread_getschedparam, pthread_getschedparam) diff --git a/libpthread/nptl/pthread_getspecific.c b/libpthread/nptl/pthread_getspecific.c new file mode 100644 index 000000000..183595c67 --- /dev/null +++ b/libpthread/nptl/pthread_getspecific.c @@ -0,0 +1,69 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stdlib.h> +#include "pthreadP.h" + + +void * +attribute_hidden +__pthread_getspecific (pthread_key_t key) +{ + struct pthread_key_data *data; + + /* Special case access to the first 2nd-level block. This is the + usual case. */ + if (__builtin_expect (key < PTHREAD_KEY_2NDLEVEL_SIZE, 1)) + data = &THREAD_SELF->specific_1stblock[key]; + else + { + /* Verify the key is sane. */ + if (key >= PTHREAD_KEYS_MAX) + /* Not valid. */ + return NULL; + + unsigned int idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; + unsigned int idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; + + /* If the sequence number doesn't match or the key cannot be defined + for this thread since the second level array is not allocated + return NULL, too. */ + struct pthread_key_data *level2 = THREAD_GETMEM_NC (THREAD_SELF, + specific, idx1st); + if (level2 == NULL) + /* Not allocated, therefore no data. */ + return NULL; + + /* There is data. */ + data = &level2[idx2nd]; + } + + void *result = data->data; + if (result != NULL) + { + uintptr_t seq = data->seq; + + if (__builtin_expect (seq != __pthread_keys[key].seq, 0)) + result = data->data = NULL; + } + + return result; +} +strong_alias (__pthread_getspecific, pthread_getspecific) +strong_alias (__pthread_getspecific, __pthread_getspecific_internal) diff --git a/libpthread/nptl/pthread_join.c b/libpthread/nptl/pthread_join.c new file mode 100644 index 000000000..ce6cf6fb9 --- /dev/null +++ b/libpthread/nptl/pthread_join.c @@ -0,0 +1,114 @@ +/* Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdlib.h> + +#include <atomic.h> +#include "pthreadP.h" + + +static void +cleanup (void *arg) +{ + /* If we already changed the waiter ID, reset it. The call cannot + fail for any reason but the thread not having done that yet so + there is no reason for a loop. */ + (void) atomic_compare_and_exchange_bool_acq ((struct pthread **) arg, NULL, + THREAD_SELF); +} + + +int +pthread_join ( + pthread_t threadid, + void **thread_return) +{ + struct pthread *pd = (struct pthread *) threadid; + + /* Make sure the descriptor is valid. */ + if (INVALID_NOT_TERMINATED_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + + /* Is the thread joinable?. */ + if (IS_DETACHED (pd)) + /* We cannot wait for the thread. */ + return EINVAL; + + struct pthread *self = THREAD_SELF; + int result = 0; + + /* During the wait we change to asynchronous cancellation. If we + are canceled the thread we are waiting for must be marked as + un-wait-ed for again. */ + pthread_cleanup_push (cleanup, &pd->joinid); + + /* Switch to asynchronous cancellation. */ + int oldtype = CANCEL_ASYNC (); + + if ((pd == self + || (self->joinid == pd + && (pd->cancelhandling + & (CANCELING_BITMASK | CANCELED_BITMASK | EXITING_BITMASK + | TERMINATED_BITMASK)) == 0)) + && !CANCEL_ENABLED_AND_CANCELED (self->cancelhandling)) + /* This is a deadlock situation. The threads are waiting for each + other to finish. Note that this is a "may" error. To be 100% + sure we catch this error we would have to lock the data + structures but it is not necessary. In the unlikely case that + two threads are really caught in this situation they will + deadlock. It is the programmer's problem to figure this + out. */ + result = EDEADLK; + /* Wait for the thread to finish. If it is already locked something + is wrong. There can only be one waiter. */ + else if (__builtin_expect (atomic_compare_and_exchange_bool_acq (&pd->joinid, + self, + NULL), 0)) + /* There is already somebody waiting for the thread. */ + result = EINVAL; + else + /* Wait for the child. */ + lll_wait_tid (pd->tid); + + + /* Restore cancellation mode. */ + CANCEL_RESET (oldtype); + + /* Remove the handler. */ + pthread_cleanup_pop (0); + + + if (__builtin_expect (result == 0, 1)) + { + /* We mark the thread as terminated and as joined. */ + pd->tid = -1; + + /* Store the return value if the caller is interested. */ + if (thread_return != NULL) + *thread_return = pd->result; + + + /* Free the TCB. */ + __free_tcb (pd); + } + + return result; +} diff --git a/libpthread/nptl/pthread_key_create.c b/libpthread/nptl/pthread_key_create.c new file mode 100644 index 000000000..21f60ad60 --- /dev/null +++ b/libpthread/nptl/pthread_key_create.c @@ -0,0 +1,55 @@ +/* Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include "pthreadP.h" +#include <atomic.h> + + +int +attribute_hidden +__pthread_key_create ( + pthread_key_t *key, + void (*destr) (void *)) +{ + /* Find a slot in __pthread_kyes which is unused. */ + for (size_t cnt = 0; cnt < PTHREAD_KEYS_MAX; ++cnt) + { + uintptr_t seq = __pthread_keys[cnt].seq; + + if (KEY_UNUSED (seq) && KEY_USABLE (seq) + /* We found an unused slot. Try to allocate it. */ + && ! atomic_compare_and_exchange_bool_acq (&__pthread_keys[cnt].seq, + seq + 1, seq)) + { + /* Remember the destructor. */ + __pthread_keys[cnt].destr = destr; + + /* Return the key to the caller. */ + *key = cnt; + + /* The call succeeded. */ + return 0; + } + } + + return EAGAIN; +} +strong_alias (__pthread_key_create, pthread_key_create) +strong_alias (__pthread_key_create, __pthread_key_create_internal) diff --git a/libpthread/nptl/pthread_key_delete.c b/libpthread/nptl/pthread_key_delete.c new file mode 100644 index 000000000..cb408f095 --- /dev/null +++ b/libpthread/nptl/pthread_key_delete.c @@ -0,0 +1,42 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include "pthreadP.h" +#include <atomic.h> + + +int +pthread_key_delete (pthread_key_t key) +{ + int result = EINVAL; + + if (__builtin_expect (key < PTHREAD_KEYS_MAX, 1)) + { + unsigned int seq = __pthread_keys[key].seq; + + if (__builtin_expect (! KEY_UNUSED (seq), 1) + && ! atomic_compare_and_exchange_bool_acq (&__pthread_keys[key].seq, + seq + 1, seq)) + /* We deleted a valid key. */ + result = 0; + } + + return result; +} diff --git a/libpthread/nptl/pthread_kill_other_threads.c b/libpthread/nptl/pthread_kill_other_threads.c new file mode 100644 index 000000000..09401aab5 --- /dev/null +++ b/libpthread/nptl/pthread_kill_other_threads.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef SHARED +/* This function does not serve a useful purpose in the thread library + implementation anymore. It used to be necessary when then kernel + could not shut down "processes" but this is not the case anymore. + + We could theoretically provide an equivalent implementation but + this is not necessary since the kernel already does a much better + job than we ever could. */ +void +__pthread_kill_other_threads_np (void) +{ +} +#endif diff --git a/libpthread/nptl/pthread_mutex_consistent.c b/libpthread/nptl/pthread_mutex_consistent.c new file mode 100644 index 000000000..1e8f07470 --- /dev/null +++ b/libpthread/nptl/pthread_mutex_consistent.c @@ -0,0 +1,37 @@ +/* Copyright (C) 2005, 2006, 2010 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2005. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <pthreadP.h> + + +int +pthread_mutex_consistent ( + pthread_mutex_t *mutex) +{ + /* Test whether this is a robust mutex with a dead owner. */ + if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0 + || mutex->__data.__owner != PTHREAD_MUTEX_INCONSISTENT) + return EINVAL; + + mutex->__data.__owner = THREAD_GETMEM (THREAD_SELF, tid); + + return 0; +} +weak_alias (pthread_mutex_consistent, pthread_mutex_consistent_np) diff --git a/libpthread/nptl/pthread_mutex_destroy.c b/libpthread/nptl/pthread_mutex_destroy.c new file mode 100644 index 000000000..5207433ef --- /dev/null +++ b/libpthread/nptl/pthread_mutex_destroy.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include "pthreadP.h" + + +int +attribute_hidden +__pthread_mutex_destroy ( + pthread_mutex_t *mutex) +{ + if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0 + && mutex->__data.__nusers != 0) + return EBUSY; + + /* Set to an invalid value. */ + mutex->__data.__kind = -1; + + return 0; +} +strong_alias (__pthread_mutex_destroy, pthread_mutex_destroy) +INTDEF(__pthread_mutex_destroy) diff --git a/libpthread/nptl/pthread_mutex_getprioceiling.c b/libpthread/nptl/pthread_mutex_getprioceiling.c new file mode 100644 index 000000000..1ce5eaebe --- /dev/null +++ b/libpthread/nptl/pthread_mutex_getprioceiling.c @@ -0,0 +1,38 @@ +/* Get current priority ceiling of pthread_mutex_t. + Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2006. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <pthreadP.h> + + +int +pthread_mutex_getprioceiling (mutex, prioceiling) + const pthread_mutex_t *mutex; + int *prioceiling; +{ + if (__builtin_expect ((mutex->__data.__kind + & PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0, 0)) + return EINVAL; + + *prioceiling = (mutex->__data.__lock & PTHREAD_MUTEX_PRIO_CEILING_MASK) + >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT; + + return 0; +} diff --git a/libpthread/nptl/pthread_mutex_init.c b/libpthread/nptl/pthread_mutex_init.c new file mode 100644 index 000000000..fee82cc5b --- /dev/null +++ b/libpthread/nptl/pthread_mutex_init.c @@ -0,0 +1,142 @@ +/* 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 <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include <string.h> +#include <bits/kernel-features.h> +#include "pthreadP.h" + +static const struct pthread_mutexattr default_attr = + { + /* Default is a normal mutex, not shared between processes. */ + .mutexkind = PTHREAD_MUTEX_NORMAL + }; + + +#ifndef __ASSUME_FUTEX_LOCK_PI +static int tpi_supported; +#endif + + +int +attribute_hidden +__pthread_mutex_init ( + pthread_mutex_t *mutex, + const pthread_mutexattr_t *mutexattr) +{ + const struct pthread_mutexattr *imutexattr; + + assert (sizeof (pthread_mutex_t) <= __SIZEOF_PTHREAD_MUTEX_T); + + imutexattr = (const struct pthread_mutexattr *) mutexattr ?: &default_attr; + + /* Sanity checks. */ + switch (__builtin_expect (imutexattr->mutexkind + & PTHREAD_MUTEXATTR_PROTOCOL_MASK, + PTHREAD_PRIO_NONE + << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT)) + { + case PTHREAD_PRIO_NONE << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT: + break; + + case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT: +#ifndef __ASSUME_FUTEX_LOCK_PI + if (__builtin_expect (tpi_supported == 0, 0)) + { + int lock = 0; + INTERNAL_SYSCALL_DECL (err); + int ret = INTERNAL_SYSCALL (futex, err, 4, &lock, FUTEX_UNLOCK_PI, + 0, 0); + assert (INTERNAL_SYSCALL_ERROR_P (ret, err)); + tpi_supported = INTERNAL_SYSCALL_ERRNO (ret, err) == ENOSYS ? -1 : 1; + } + if (__builtin_expect (tpi_supported < 0, 0)) + return ENOTSUP; +#endif + break; + + default: + /* XXX: For now we don't support robust priority protected mutexes. */ + if (imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) + return ENOTSUP; + break; + } + + /* Clear the whole variable. */ + memset (mutex, '\0', __SIZEOF_PTHREAD_MUTEX_T); + + /* Copy the values from the attribute. */ + mutex->__data.__kind = imutexattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS; + + if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) != 0) + { +#ifndef __ASSUME_SET_ROBUST_LIST + if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_PSHARED) != 0 + && __set_robust_list_avail < 0) + return ENOTSUP; +#endif + + mutex->__data.__kind |= PTHREAD_MUTEX_ROBUST_NORMAL_NP; + } + + switch (imutexattr->mutexkind & PTHREAD_MUTEXATTR_PROTOCOL_MASK) + { + case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT: + mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_INHERIT_NP; + break; + + case PTHREAD_PRIO_PROTECT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT: + mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_PROTECT_NP; + + int ceiling = (imutexattr->mutexkind + & PTHREAD_MUTEXATTR_PRIO_CEILING_MASK) + >> PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT; + if (! ceiling) + { + if (__sched_fifo_min_prio == -1) + __init_sched_fifo_prio (); + if (ceiling < __sched_fifo_min_prio) + ceiling = __sched_fifo_min_prio; + } + mutex->__data.__lock = ceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT; + break; + + default: + break; + } + + /* The kernel when waking robust mutexes on exit never uses + FUTEX_PRIVATE_FLAG FUTEX_WAKE. */ + if ((imutexattr->mutexkind & (PTHREAD_MUTEXATTR_FLAG_PSHARED + | PTHREAD_MUTEXATTR_FLAG_ROBUST)) != 0) + mutex->__data.__kind |= PTHREAD_MUTEX_PSHARED_BIT; + + /* Default values: mutex not used yet. */ + // mutex->__count = 0; already done by memset + // mutex->__owner = 0; already done by memset + // mutex->__nusers = 0; already done by memset + // mutex->__spins = 0; already done by memset + // mutex->__next = NULL; already done by memset + + return 0; +} +strong_alias (__pthread_mutex_init, pthread_mutex_init) +INTDEF(__pthread_mutex_init) diff --git a/libpthread/nptl/pthread_mutex_lock.c b/libpthread/nptl/pthread_mutex_lock.c new file mode 100644 index 000000000..d00e13546 --- /dev/null +++ b/libpthread/nptl/pthread_mutex_lock.c @@ -0,0 +1,495 @@ +/* Copyright (C) 2002-2007, 2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include <not-cancel.h> +#include "pthreadP.h" +#include <lowlevellock.h> + + +#ifndef LLL_MUTEX_LOCK +# define LLL_MUTEX_LOCK(mutex) \ + lll_lock ((mutex)->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex)) +# define LLL_MUTEX_TRYLOCK(mutex) \ + lll_trylock ((mutex)->__data.__lock) +# define LLL_ROBUST_MUTEX_LOCK(mutex, id) \ + lll_robust_lock ((mutex)->__data.__lock, id, \ + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)) +#endif + + +static int __pthread_mutex_lock_full (pthread_mutex_t *mutex) + __attribute_noinline__; + + +int +attribute_hidden +__pthread_mutex_lock ( + pthread_mutex_t *mutex) +{ + assert (sizeof (mutex->__size) >= sizeof (mutex->__data)); + + unsigned int type = PTHREAD_MUTEX_TYPE (mutex); + if (__builtin_expect (type & ~PTHREAD_MUTEX_KIND_MASK_NP, 0)) + return __pthread_mutex_lock_full (mutex); + + pid_t id = THREAD_GETMEM (THREAD_SELF, tid); + + if (__builtin_expect (type, PTHREAD_MUTEX_TIMED_NP) + == PTHREAD_MUTEX_TIMED_NP) + { + simple: + /* Normal mutex. */ + LLL_MUTEX_LOCK (mutex); + assert (mutex->__data.__owner == 0); + } + else if (__builtin_expect (type == PTHREAD_MUTEX_RECURSIVE_NP, 1)) + { + /* Recursive mutex. */ + + /* Check whether we already hold the mutex. */ + if (mutex->__data.__owner == id) + { + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + + /* We have to get the mutex. */ + LLL_MUTEX_LOCK (mutex); + + assert (mutex->__data.__owner == 0); + mutex->__data.__count = 1; + } + else if (__builtin_expect (type == PTHREAD_MUTEX_ADAPTIVE_NP, 1)) + { + if (! __is_smp) + goto simple; + + if (LLL_MUTEX_TRYLOCK (mutex) != 0) + { + int cnt = 0; + int max_cnt = MIN (MAX_ADAPTIVE_COUNT, + mutex->__data.__spins * 2 + 10); + do + { + if (cnt++ >= max_cnt) + { + LLL_MUTEX_LOCK (mutex); + break; + } + +#ifdef BUSY_WAIT_NOP + BUSY_WAIT_NOP; +#endif + } + while (LLL_MUTEX_TRYLOCK (mutex) != 0); + + mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8; + } + assert (mutex->__data.__owner == 0); + } + else + { + assert (type == PTHREAD_MUTEX_ERRORCHECK_NP); + /* Check whether we already hold the mutex. */ + if (__builtin_expect (mutex->__data.__owner == id, 0)) + return EDEADLK; + goto simple; + } + + /* Record the ownership. */ + mutex->__data.__owner = id; +#ifndef NO_INCR + ++mutex->__data.__nusers; +#endif + + return 0; +} + +static int +__pthread_mutex_lock_full (pthread_mutex_t *mutex) +{ + int oldval; + pid_t id = THREAD_GETMEM (THREAD_SELF, tid); + + switch (PTHREAD_MUTEX_TYPE (mutex)) + { + case PTHREAD_MUTEX_ROBUST_RECURSIVE_NP: + case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP: + case PTHREAD_MUTEX_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP: + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + &mutex->__data.__list.__next); + + oldval = mutex->__data.__lock; + do + { + again: + if ((oldval & FUTEX_OWNER_DIED) != 0) + { + /* The previous owner died. Try locking the mutex. */ + int newval = id; +#ifdef NO_INCR + newval |= FUTEX_WAITERS; +#else + newval |= (oldval & FUTEX_WAITERS); +#endif + + newval + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + newval, oldval); + + if (newval != oldval) + { + oldval = newval; + goto again; + } + + /* We got the mutex. */ + mutex->__data.__count = 1; + /* But it is inconsistent unless marked otherwise. */ + mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT; + + ENQUEUE_MUTEX (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Note that we deliberately exit here. If we fall + through to the end of the function __nusers would be + incremented which is not correct because the old + owner has to be discounted. If we are not supposed + to increment __nusers we actually have to decrement + it here. */ +#ifdef NO_INCR + --mutex->__data.__nusers; +#endif + + return EOWNERDEAD; + } + + /* Check whether we already hold the mutex. */ + if (__builtin_expect ((oldval & FUTEX_TID_MASK) == id, 0)) + { + int kind = PTHREAD_MUTEX_TYPE (mutex); + if (kind == PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + NULL); + return EDEADLK; + } + + if (kind == PTHREAD_MUTEX_ROBUST_RECURSIVE_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + NULL); + + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + } + + oldval = LLL_ROBUST_MUTEX_LOCK (mutex, id); + + if (__builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_NOTRECOVERABLE, 0)) + { + /* This mutex is now not recoverable. */ + mutex->__data.__count = 0; + lll_unlock (mutex->__data.__lock, + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return ENOTRECOVERABLE; + } + } + while ((oldval & FUTEX_OWNER_DIED) != 0); + + mutex->__data.__count = 1; + ENQUEUE_MUTEX (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + break; + + case PTHREAD_MUTEX_PI_RECURSIVE_NP: + case PTHREAD_MUTEX_PI_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_NORMAL_NP: + case PTHREAD_MUTEX_PI_ADAPTIVE_NP: + case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP: + case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP: + { + int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; + int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; + + if (robust) + /* Note: robust PI futexes are signaled by setting bit 0. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + (void *) (((uintptr_t) &mutex->__data.__list.__next) + | 1)); + + oldval = mutex->__data.__lock; + + /* Check whether we already hold the mutex. */ + if (__builtin_expect ((oldval & FUTEX_TID_MASK) == id, 0)) + { + if (kind == PTHREAD_MUTEX_ERRORCHECK_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return EDEADLK; + } + + if (kind == PTHREAD_MUTEX_RECURSIVE_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + } + + int newval = id; +#ifdef NO_INCR + newval |= FUTEX_WAITERS; +#endif + oldval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + newval, 0); + + if (oldval != 0) + { + /* The mutex is locked. The kernel will now take care of + everything. */ + int private = (robust + ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex) + : PTHREAD_MUTEX_PSHARED (mutex)); + INTERNAL_SYSCALL_DECL (__err); + int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, + __lll_private_flag (FUTEX_LOCK_PI, + private), 1, 0); + + if (INTERNAL_SYSCALL_ERROR_P (e, __err) + && (INTERNAL_SYSCALL_ERRNO (e, __err) == ESRCH + || INTERNAL_SYSCALL_ERRNO (e, __err) == EDEADLK)) + { + assert (INTERNAL_SYSCALL_ERRNO (e, __err) != EDEADLK + || (kind != PTHREAD_MUTEX_ERRORCHECK_NP + && kind != PTHREAD_MUTEX_RECURSIVE_NP)); + /* ESRCH can happen only for non-robust PI mutexes where + the owner of the lock died. */ + assert (INTERNAL_SYSCALL_ERRNO (e, __err) != ESRCH || !robust); + + /* Delay the thread indefinitely. */ + while (1) + pause_not_cancel (); + } + + oldval = mutex->__data.__lock; + + assert (robust || (oldval & FUTEX_OWNER_DIED) == 0); + } + + if (__builtin_expect (oldval & FUTEX_OWNER_DIED, 0)) + { + atomic_and (&mutex->__data.__lock, ~FUTEX_OWNER_DIED); + + /* We got the mutex. */ + mutex->__data.__count = 1; + /* But it is inconsistent unless marked otherwise. */ + mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT; + + ENQUEUE_MUTEX_PI (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Note that we deliberately exit here. If we fall + through to the end of the function __nusers would be + incremented which is not correct because the old owner + has to be discounted. If we are not supposed to + increment __nusers we actually have to decrement it here. */ +#ifdef NO_INCR + --mutex->__data.__nusers; +#endif + + return EOWNERDEAD; + } + + if (robust + && __builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_NOTRECOVERABLE, 0)) + { + /* This mutex is now not recoverable. */ + mutex->__data.__count = 0; + + INTERNAL_SYSCALL_DECL (__err); + INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, + __lll_private_flag (FUTEX_UNLOCK_PI, + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)), + 0, 0); + + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return ENOTRECOVERABLE; + } + + mutex->__data.__count = 1; + if (robust) + { + ENQUEUE_MUTEX_PI (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + } + } + break; + + case PTHREAD_MUTEX_PP_RECURSIVE_NP: + case PTHREAD_MUTEX_PP_ERRORCHECK_NP: + case PTHREAD_MUTEX_PP_NORMAL_NP: + case PTHREAD_MUTEX_PP_ADAPTIVE_NP: + { + int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; + + oldval = mutex->__data.__lock; + + /* Check whether we already hold the mutex. */ + if (mutex->__data.__owner == id) + { + if (kind == PTHREAD_MUTEX_ERRORCHECK_NP) + return EDEADLK; + + if (kind == PTHREAD_MUTEX_RECURSIVE_NP) + { + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + } + + int oldprio = -1, ceilval; + do + { + int ceiling = (oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) + >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT; + + if (__pthread_current_priority () > ceiling) + { + if (oldprio != -1) + __pthread_tpp_change_priority (oldprio, -1); + return EINVAL; + } + + int retval = __pthread_tpp_change_priority (oldprio, ceiling); + if (retval) + return retval; + + ceilval = ceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT; + oldprio = ceiling; + + oldval + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, +#ifdef NO_INCR + ceilval | 2, +#else + ceilval | 1, +#endif + ceilval); + + if (oldval == ceilval) + break; + + do + { + oldval + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + ceilval | 2, + ceilval | 1); + + if ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval) + break; + + if (oldval != ceilval) + lll_futex_wait (&mutex->__data.__lock, ceilval | 2, + PTHREAD_MUTEX_PSHARED (mutex)); + } + while (atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + ceilval | 2, ceilval) + != ceilval); + } + while ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval); + + assert (mutex->__data.__owner == 0); + mutex->__data.__count = 1; + } + break; + + default: + /* Correct code cannot set any other type. */ + return EINVAL; + } + + /* Record the ownership. */ + mutex->__data.__owner = id; +#ifndef NO_INCR + ++mutex->__data.__nusers; +#endif + + return 0; +} +#ifndef __pthread_mutex_lock +strong_alias (__pthread_mutex_lock, pthread_mutex_lock) +strong_alias (__pthread_mutex_lock, __pthread_mutex_lock_internal) +#endif + + +#ifdef NO_INCR +void +__pthread_mutex_cond_lock_adjust ( + pthread_mutex_t *mutex) +{ + assert ((mutex->__data.__kind & PTHREAD_MUTEX_PRIO_INHERIT_NP) != 0); + assert ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0); + assert ((mutex->__data.__kind & PTHREAD_MUTEX_PSHARED_BIT) == 0); + + /* Record the ownership. */ + pid_t id = THREAD_GETMEM (THREAD_SELF, tid); + mutex->__data.__owner = id; + + if (mutex->__data.__kind == PTHREAD_MUTEX_PI_RECURSIVE_NP) + ++mutex->__data.__count; +} +#endif diff --git a/libpthread/nptl/pthread_mutex_setprioceiling.c b/libpthread/nptl/pthread_mutex_setprioceiling.c new file mode 100644 index 000000000..836c9a3e9 --- /dev/null +++ b/libpthread/nptl/pthread_mutex_setprioceiling.c @@ -0,0 +1,119 @@ +/* Set current priority ceiling of pthread_mutex_t. + Copyright (C) 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2006. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stdbool.h> +#include <errno.h> +#include <pthreadP.h> + + +int +pthread_mutex_setprioceiling (mutex, prioceiling, old_ceiling) + pthread_mutex_t *mutex; + int prioceiling; + int *old_ceiling; +{ + /* The low bits of __kind aren't ever changed after pthread_mutex_init, + so we don't need a lock yet. */ + if ((mutex->__data.__kind & PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0) + return EINVAL; + + if (__sched_fifo_min_prio == -1) + __init_sched_fifo_prio (); + + if (__builtin_expect (prioceiling < __sched_fifo_min_prio, 0) + || __builtin_expect (prioceiling > __sched_fifo_max_prio, 0) + || __builtin_expect ((prioceiling + & (PTHREAD_MUTEXATTR_PRIO_CEILING_MASK + >> PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT)) + != prioceiling, 0)) + return EINVAL; + + /* Check whether we already hold the mutex. */ + bool locked = false; + int kind = PTHREAD_MUTEX_TYPE (mutex); + if (mutex->__data.__owner == THREAD_GETMEM (THREAD_SELF, tid)) + { + if (kind == PTHREAD_MUTEX_PP_ERRORCHECK_NP) + return EDEADLK; + + if (kind == PTHREAD_MUTEX_PP_RECURSIVE_NP) + locked = true; + } + + int oldval = mutex->__data.__lock; + if (! locked) + do + { + /* Need to lock the mutex, but without obeying the priority + protect protocol. */ + int ceilval = (oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK); + + oldval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + ceilval | 1, ceilval); + if (oldval == ceilval) + break; + + do + { + oldval + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + ceilval | 2, + ceilval | 1); + + if ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval) + break; + + if (oldval != ceilval) + lll_futex_wait (&mutex->__data.__lock, ceilval | 2, + PTHREAD_MUTEX_PSHARED (mutex)); + } + while (atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + ceilval | 2, ceilval) + != ceilval); + + if ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval) + continue; + } + while (0); + + int oldprio = (oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) + >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT; + if (locked) + { + int ret = __pthread_tpp_change_priority (oldprio, prioceiling); + if (ret) + return ret; + } + + if (old_ceiling != NULL) + *old_ceiling = oldprio; + + int newlock = 0; + if (locked) + newlock = (mutex->__data.__lock & ~PTHREAD_MUTEX_PRIO_CEILING_MASK); + mutex->__data.__lock = newlock + | (prioceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT); + atomic_full_barrier (); + + lll_futex_wake (&mutex->__data.__lock, INT_MAX, + PTHREAD_MUTEX_PSHARED (mutex)); + + return 0; +} diff --git a/libpthread/nptl/pthread_mutex_timedlock.c b/libpthread/nptl/pthread_mutex_timedlock.c new file mode 100644 index 000000000..d6ab60ec4 --- /dev/null +++ b/libpthread/nptl/pthread_mutex_timedlock.c @@ -0,0 +1,488 @@ +/* Copyright (C) 2002-2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include <time.h> +#include "pthreadP.h" +#include <lowlevellock.h> +#include <not-cancel.h> + +/* We need to build this function with optimization to avoid + * lll_timedlock erroring out with + * error: can't find a register in class ‘GENERAL_REGS’ while reloading ‘asm’ + */ +int +attribute_optimize("Os") +pthread_mutex_timedlock ( + pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + int oldval; + pid_t id = THREAD_GETMEM (THREAD_SELF, tid); + int result = 0; + + /* We must not check ABSTIME here. If the thread does not block + abstime must not be checked for a valid value. */ + + switch (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex), + PTHREAD_MUTEX_TIMED_NP)) + { + /* Recursive mutex. */ + case PTHREAD_MUTEX_RECURSIVE_NP: + /* Check whether we already hold the mutex. */ + if (mutex->__data.__owner == id) + { + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + goto out; + } + + /* We have to get the mutex. */ + result = lll_timedlock (mutex->__data.__lock, abstime, + PTHREAD_MUTEX_PSHARED (mutex)); + + if (result != 0) + goto out; + + /* Only locked once so far. */ + mutex->__data.__count = 1; + break; + + /* Error checking mutex. */ + case PTHREAD_MUTEX_ERRORCHECK_NP: + /* Check whether we already hold the mutex. */ + if (__builtin_expect (mutex->__data.__owner == id, 0)) + return EDEADLK; + + /* FALLTHROUGH */ + + case PTHREAD_MUTEX_TIMED_NP: + simple: + /* Normal mutex. */ + result = lll_timedlock (mutex->__data.__lock, abstime, + PTHREAD_MUTEX_PSHARED (mutex)); + break; + + case PTHREAD_MUTEX_ADAPTIVE_NP: + if (! __is_smp) + goto simple; + + if (lll_trylock (mutex->__data.__lock) != 0) + { + int cnt = 0; + int max_cnt = MIN (MAX_ADAPTIVE_COUNT, + mutex->__data.__spins * 2 + 10); + do + { + if (cnt++ >= max_cnt) + { + result = lll_timedlock (mutex->__data.__lock, abstime, + PTHREAD_MUTEX_PSHARED (mutex)); + break; + } + +#ifdef BUSY_WAIT_NOP + BUSY_WAIT_NOP; +#endif + } + while (lll_trylock (mutex->__data.__lock) != 0); + + mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8; + } + break; + + case PTHREAD_MUTEX_ROBUST_RECURSIVE_NP: + case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP: + case PTHREAD_MUTEX_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP: + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + &mutex->__data.__list.__next); + + oldval = mutex->__data.__lock; + do + { + again: + if ((oldval & FUTEX_OWNER_DIED) != 0) + { + /* The previous owner died. Try locking the mutex. */ + int newval = id | (oldval & FUTEX_WAITERS); + + newval + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + newval, oldval); + if (newval != oldval) + { + oldval = newval; + goto again; + } + + /* We got the mutex. */ + mutex->__data.__count = 1; + /* But it is inconsistent unless marked otherwise. */ + mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT; + + ENQUEUE_MUTEX (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Note that we deliberately exit here. If we fall + through to the end of the function __nusers would be + incremented which is not correct because the old + owner has to be discounted. */ + return EOWNERDEAD; + } + + /* Check whether we already hold the mutex. */ + if (__builtin_expect ((oldval & FUTEX_TID_MASK) == id, 0)) + { + int kind = PTHREAD_MUTEX_TYPE (mutex); + if (kind == PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + NULL); + return EDEADLK; + } + + if (kind == PTHREAD_MUTEX_ROBUST_RECURSIVE_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + NULL); + + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + } + + result = lll_robust_timedlock (mutex->__data.__lock, abstime, id, + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)); + + if (__builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_NOTRECOVERABLE, 0)) + { + /* This mutex is now not recoverable. */ + mutex->__data.__count = 0; + lll_unlock (mutex->__data.__lock, + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return ENOTRECOVERABLE; + } + + if (result == ETIMEDOUT || result == EINVAL) + goto out; + + oldval = result; + } + while ((oldval & FUTEX_OWNER_DIED) != 0); + + mutex->__data.__count = 1; + ENQUEUE_MUTEX (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + break; + + case PTHREAD_MUTEX_PI_RECURSIVE_NP: + case PTHREAD_MUTEX_PI_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_NORMAL_NP: + case PTHREAD_MUTEX_PI_ADAPTIVE_NP: + case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP: + case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP: + { + int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; + int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; + + if (robust) + /* Note: robust PI futexes are signaled by setting bit 0. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + (void *) (((uintptr_t) &mutex->__data.__list.__next) + | 1)); + + oldval = mutex->__data.__lock; + + /* Check whether we already hold the mutex. */ + if (__builtin_expect ((oldval & FUTEX_TID_MASK) == id, 0)) + { + if (kind == PTHREAD_MUTEX_ERRORCHECK_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return EDEADLK; + } + + if (kind == PTHREAD_MUTEX_RECURSIVE_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + } + + oldval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + id, 0); + + if (oldval != 0) + { + /* The mutex is locked. The kernel will now take care of + everything. The timeout value must be a relative value. + Convert it. */ + int private = (robust + ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex) + : PTHREAD_MUTEX_PSHARED (mutex)); + INTERNAL_SYSCALL_DECL (__err); + + int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, + __lll_private_flag (FUTEX_LOCK_PI, + private), 1, + abstime); + if (INTERNAL_SYSCALL_ERROR_P (e, __err)) + { + if (INTERNAL_SYSCALL_ERRNO (e, __err) == ETIMEDOUT) + return ETIMEDOUT; + + if (INTERNAL_SYSCALL_ERRNO (e, __err) == ESRCH + || INTERNAL_SYSCALL_ERRNO (e, __err) == EDEADLK) + { + assert (INTERNAL_SYSCALL_ERRNO (e, __err) != EDEADLK + || (kind != PTHREAD_MUTEX_ERRORCHECK_NP + && kind != PTHREAD_MUTEX_RECURSIVE_NP)); + /* ESRCH can happen only for non-robust PI mutexes where + the owner of the lock died. */ + assert (INTERNAL_SYSCALL_ERRNO (e, __err) != ESRCH + || !robust); + + /* Delay the thread until the timeout is reached. + Then return ETIMEDOUT. */ + struct timespec reltime; + struct timespec now; + + INTERNAL_SYSCALL (clock_gettime, __err, 2, CLOCK_REALTIME, + &now); + reltime.tv_sec = abstime->tv_sec - now.tv_sec; + reltime.tv_nsec = abstime->tv_nsec - now.tv_nsec; + if (reltime.tv_nsec < 0) + { + reltime.tv_nsec += 1000000000; + --reltime.tv_sec; + } + if (reltime.tv_sec >= 0) + while (nanosleep_not_cancel (&reltime, &reltime) != 0) + continue; + + return ETIMEDOUT; + } + + return INTERNAL_SYSCALL_ERRNO (e, __err); + } + + oldval = mutex->__data.__lock; + + assert (robust || (oldval & FUTEX_OWNER_DIED) == 0); + } + + if (__builtin_expect (oldval & FUTEX_OWNER_DIED, 0)) + { + atomic_and (&mutex->__data.__lock, ~FUTEX_OWNER_DIED); + + /* We got the mutex. */ + mutex->__data.__count = 1; + /* But it is inconsistent unless marked otherwise. */ + mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT; + + ENQUEUE_MUTEX_PI (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Note that we deliberately exit here. If we fall + through to the end of the function __nusers would be + incremented which is not correct because the old owner + has to be discounted. */ + return EOWNERDEAD; + } + + if (robust + && __builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_NOTRECOVERABLE, 0)) + { + /* This mutex is now not recoverable. */ + mutex->__data.__count = 0; + + INTERNAL_SYSCALL_DECL (__err); + INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, + __lll_private_flag (FUTEX_UNLOCK_PI, + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)), + 0, 0); + + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return ENOTRECOVERABLE; + } + + mutex->__data.__count = 1; + if (robust) + { + ENQUEUE_MUTEX_PI (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + } + } + break; + + case PTHREAD_MUTEX_PP_RECURSIVE_NP: + case PTHREAD_MUTEX_PP_ERRORCHECK_NP: + case PTHREAD_MUTEX_PP_NORMAL_NP: + case PTHREAD_MUTEX_PP_ADAPTIVE_NP: + { + int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; + + oldval = mutex->__data.__lock; + + /* Check whether we already hold the mutex. */ + if (mutex->__data.__owner == id) + { + if (kind == PTHREAD_MUTEX_ERRORCHECK_NP) + return EDEADLK; + + if (kind == PTHREAD_MUTEX_RECURSIVE_NP) + { + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + } + + int oldprio = -1, ceilval; + do + { + int ceiling = (oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) + >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT; + + if (__pthread_current_priority () > ceiling) + { + result = EINVAL; + failpp: + if (oldprio != -1) + __pthread_tpp_change_priority (oldprio, -1); + return result; + } + + result = __pthread_tpp_change_priority (oldprio, ceiling); + if (result) + return result; + + ceilval = ceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT; + oldprio = ceiling; + + oldval + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + ceilval | 1, ceilval); + + if (oldval == ceilval) + break; + + do + { + oldval + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + ceilval | 2, + ceilval | 1); + + if ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval) + break; + + if (oldval != ceilval) + { + /* Reject invalid timeouts. */ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + { + result = EINVAL; + goto failpp; + } + + struct timeval tv; + struct timespec rt; + + /* Get the current time. */ + (void) gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + + /* Already timed out? */ + if (rt.tv_sec < 0) + { + result = ETIMEDOUT; + goto failpp; + } + + lll_futex_timed_wait (&mutex->__data.__lock, + ceilval | 2, &rt, + PTHREAD_MUTEX_PSHARED (mutex)); + } + } + while (atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + ceilval | 2, ceilval) + != ceilval); + } + while ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval); + + assert (mutex->__data.__owner == 0); + mutex->__data.__count = 1; + } + break; + + default: + /* Correct code cannot set any other type. */ + return EINVAL; + } + + if (result == 0) + { + /* Record the ownership. */ + mutex->__data.__owner = id; + ++mutex->__data.__nusers; + } + + out: + return result; +} diff --git a/libpthread/nptl/pthread_mutex_trylock.c b/libpthread/nptl/pthread_mutex_trylock.c new file mode 100644 index 000000000..5555afcb7 --- /dev/null +++ b/libpthread/nptl/pthread_mutex_trylock.c @@ -0,0 +1,382 @@ +/* Copyright (C) 2002, 2003, 2005-2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include "pthreadP.h" +#include <lowlevellock.h> + + +int +__pthread_mutex_trylock ( + pthread_mutex_t *mutex) +{ + int oldval; + pid_t id = THREAD_GETMEM (THREAD_SELF, tid); + + switch (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex), + PTHREAD_MUTEX_TIMED_NP)) + { + /* Recursive mutex. */ + case PTHREAD_MUTEX_RECURSIVE_NP: + /* Check whether we already hold the mutex. */ + if (mutex->__data.__owner == id) + { + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + return 0; + } + + if (lll_trylock (mutex->__data.__lock) == 0) + { + /* Record the ownership. */ + mutex->__data.__owner = id; + mutex->__data.__count = 1; + ++mutex->__data.__nusers; + return 0; + } + break; + + case PTHREAD_MUTEX_ERRORCHECK_NP: + case PTHREAD_MUTEX_TIMED_NP: + case PTHREAD_MUTEX_ADAPTIVE_NP: + /* Normal mutex. */ + if (lll_trylock (mutex->__data.__lock) != 0) + break; + + /* Record the ownership. */ + mutex->__data.__owner = id; + ++mutex->__data.__nusers; + + return 0; + + case PTHREAD_MUTEX_ROBUST_RECURSIVE_NP: + case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP: + case PTHREAD_MUTEX_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP: + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + &mutex->__data.__list.__next); + + oldval = mutex->__data.__lock; + do + { + again: + if ((oldval & FUTEX_OWNER_DIED) != 0) + { + /* The previous owner died. Try locking the mutex. */ + int newval = id | (oldval & FUTEX_WAITERS); + + newval + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + newval, oldval); + + if (newval != oldval) + { + oldval = newval; + goto again; + } + + /* We got the mutex. */ + mutex->__data.__count = 1; + /* But it is inconsistent unless marked otherwise. */ + mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT; + + ENQUEUE_MUTEX (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Note that we deliberately exist here. If we fall + through to the end of the function __nusers would be + incremented which is not correct because the old + owner has to be discounted. */ + return EOWNERDEAD; + } + + /* Check whether we already hold the mutex. */ + if (__builtin_expect ((oldval & FUTEX_TID_MASK) == id, 0)) + { + int kind = PTHREAD_MUTEX_TYPE (mutex); + if (kind == PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + NULL); + return EDEADLK; + } + + if (kind == PTHREAD_MUTEX_ROBUST_RECURSIVE_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + NULL); + + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + } + + oldval = lll_robust_trylock (mutex->__data.__lock, id); + if (oldval != 0 && (oldval & FUTEX_OWNER_DIED) == 0) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + return EBUSY; + } + + if (__builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_NOTRECOVERABLE, 0)) + { + /* This mutex is now not recoverable. */ + mutex->__data.__count = 0; + if (oldval == id) + lll_unlock (mutex->__data.__lock, + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return ENOTRECOVERABLE; + } + } + while ((oldval & FUTEX_OWNER_DIED) != 0); + + ENQUEUE_MUTEX (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + mutex->__data.__owner = id; + ++mutex->__data.__nusers; + mutex->__data.__count = 1; + + return 0; + + case PTHREAD_MUTEX_PI_RECURSIVE_NP: + case PTHREAD_MUTEX_PI_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_NORMAL_NP: + case PTHREAD_MUTEX_PI_ADAPTIVE_NP: + case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP: + case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP: + { + int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; + int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; + + if (robust) + /* Note: robust PI futexes are signaled by setting bit 0. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + (void *) (((uintptr_t) &mutex->__data.__list.__next) + | 1)); + + oldval = mutex->__data.__lock; + + /* Check whether we already hold the mutex. */ + if (__builtin_expect ((oldval & FUTEX_TID_MASK) == id, 0)) + { + if (kind == PTHREAD_MUTEX_ERRORCHECK_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return EDEADLK; + } + + if (kind == PTHREAD_MUTEX_RECURSIVE_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + } + + oldval + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + id, 0); + + if (oldval != 0) + { + if ((oldval & FUTEX_OWNER_DIED) == 0) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + return EBUSY; + } + + assert (robust); + + /* The mutex owner died. The kernel will now take care of + everything. */ + int private = (robust + ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex) + : PTHREAD_MUTEX_PSHARED (mutex)); + INTERNAL_SYSCALL_DECL (__err); + int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, + __lll_private_flag (FUTEX_TRYLOCK_PI, + private), 0, 0); + + if (INTERNAL_SYSCALL_ERROR_P (e, __err) + && INTERNAL_SYSCALL_ERRNO (e, __err) == EWOULDBLOCK) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + return EBUSY; + } + + oldval = mutex->__data.__lock; + } + + if (__builtin_expect (oldval & FUTEX_OWNER_DIED, 0)) + { + atomic_and (&mutex->__data.__lock, ~FUTEX_OWNER_DIED); + + /* We got the mutex. */ + mutex->__data.__count = 1; + /* But it is inconsistent unless marked otherwise. */ + mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT; + + ENQUEUE_MUTEX (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Note that we deliberately exit here. If we fall + through to the end of the function __nusers would be + incremented which is not correct because the old owner + has to be discounted. */ + return EOWNERDEAD; + } + + if (robust + && __builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_NOTRECOVERABLE, 0)) + { + /* This mutex is now not recoverable. */ + mutex->__data.__count = 0; + + INTERNAL_SYSCALL_DECL (__err); + INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, + __lll_private_flag (FUTEX_UNLOCK_PI, + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)), + 0, 0); + + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return ENOTRECOVERABLE; + } + + if (robust) + { + ENQUEUE_MUTEX_PI (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + } + + mutex->__data.__owner = id; + ++mutex->__data.__nusers; + mutex->__data.__count = 1; + + return 0; + } + + case PTHREAD_MUTEX_PP_RECURSIVE_NP: + case PTHREAD_MUTEX_PP_ERRORCHECK_NP: + case PTHREAD_MUTEX_PP_NORMAL_NP: + case PTHREAD_MUTEX_PP_ADAPTIVE_NP: + { + int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; + + oldval = mutex->__data.__lock; + + /* Check whether we already hold the mutex. */ + if (mutex->__data.__owner == id) + { + if (kind == PTHREAD_MUTEX_ERRORCHECK_NP) + return EDEADLK; + + if (kind == PTHREAD_MUTEX_RECURSIVE_NP) + { + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + } + + int oldprio = -1, ceilval; + do + { + int ceiling = (oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) + >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT; + + if (__pthread_current_priority () > ceiling) + { + if (oldprio != -1) + __pthread_tpp_change_priority (oldprio, -1); + return EINVAL; + } + + int retval = __pthread_tpp_change_priority (oldprio, ceiling); + if (retval) + return retval; + + ceilval = ceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT; + oldprio = ceiling; + + oldval + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + ceilval | 1, ceilval); + + if (oldval == ceilval) + break; + } + while ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval); + + if (oldval != ceilval) + { + __pthread_tpp_change_priority (oldprio, -1); + break; + } + + assert (mutex->__data.__owner == 0); + /* Record the ownership. */ + mutex->__data.__owner = id; + ++mutex->__data.__nusers; + mutex->__data.__count = 1; + + return 0; + } + break; + + default: + /* Correct code cannot set any other type. */ + return EINVAL; + } + + return EBUSY; +} +strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock) diff --git a/libpthread/nptl/pthread_mutex_unlock.c b/libpthread/nptl/pthread_mutex_unlock.c new file mode 100644 index 000000000..15a5d1da9 --- /dev/null +++ b/libpthread/nptl/pthread_mutex_unlock.c @@ -0,0 +1,294 @@ +/* Copyright (C) 2002, 2003, 2005-2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include "pthreadP.h" +#include <lowlevellock.h> + +static int +internal_function +__pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr) + __attribute_noinline__; + +int +internal_function attribute_hidden +__pthread_mutex_unlock_usercnt ( + pthread_mutex_t *mutex, + int decr) +{ + int type = PTHREAD_MUTEX_TYPE (mutex); + if (__builtin_expect (type & ~PTHREAD_MUTEX_KIND_MASK_NP, 0)) + return __pthread_mutex_unlock_full (mutex, decr); + + if (__builtin_expect (type, PTHREAD_MUTEX_TIMED_NP) + == PTHREAD_MUTEX_TIMED_NP) + { + /* Always reset the owner field. */ + normal: + mutex->__data.__owner = 0; + if (decr) + /* One less user. */ + --mutex->__data.__nusers; + + /* Unlock. */ + lll_unlock (mutex->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex)); + return 0; + } + else if (__builtin_expect (type == PTHREAD_MUTEX_RECURSIVE_NP, 1)) + { + /* Recursive mutex. */ + if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)) + return EPERM; + + if (--mutex->__data.__count != 0) + /* We still hold the mutex. */ + return 0; + goto normal; + } + else if (__builtin_expect (type == PTHREAD_MUTEX_ADAPTIVE_NP, 1)) + goto normal; + else + { + /* Error checking mutex. */ + assert (type == PTHREAD_MUTEX_ERRORCHECK_NP); + if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid) + || ! lll_islocked (mutex->__data.__lock)) + return EPERM; + goto normal; + } +} + + +static int +internal_function +__pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr) +{ + int newowner = 0; + + switch (PTHREAD_MUTEX_TYPE (mutex)) + { + case PTHREAD_MUTEX_ROBUST_RECURSIVE_NP: + /* Recursive mutex. */ + if ((mutex->__data.__lock & FUTEX_TID_MASK) + == THREAD_GETMEM (THREAD_SELF, tid) + && __builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_INCONSISTENT, 0)) + { + if (--mutex->__data.__count != 0) + /* We still hold the mutex. */ + return ENOTRECOVERABLE; + + goto notrecoverable; + } + + if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)) + return EPERM; + + if (--mutex->__data.__count != 0) + /* We still hold the mutex. */ + return 0; + + goto robust; + + case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP: + case PTHREAD_MUTEX_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP: + if ((mutex->__data.__lock & FUTEX_TID_MASK) + != THREAD_GETMEM (THREAD_SELF, tid) + || ! lll_islocked (mutex->__data.__lock)) + return EPERM; + + /* If the previous owner died and the caller did not succeed in + making the state consistent, mark the mutex as unrecoverable + and make all waiters. */ + if (__builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_INCONSISTENT, 0)) + notrecoverable: + newowner = PTHREAD_MUTEX_NOTRECOVERABLE; + + robust: + /* Remove mutex from the list. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + &mutex->__data.__list.__next); + DEQUEUE_MUTEX (mutex); + + mutex->__data.__owner = newowner; + if (decr) + /* One less user. */ + --mutex->__data.__nusers; + + /* Unlock. */ + lll_robust_unlock (mutex->__data.__lock, + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)); + + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + break; + + case PTHREAD_MUTEX_PI_RECURSIVE_NP: + /* Recursive mutex. */ + if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)) + return EPERM; + + if (--mutex->__data.__count != 0) + /* We still hold the mutex. */ + return 0; + goto continue_pi_non_robust; + + case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP: + /* Recursive mutex. */ + if ((mutex->__data.__lock & FUTEX_TID_MASK) + == THREAD_GETMEM (THREAD_SELF, tid) + && __builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_INCONSISTENT, 0)) + { + if (--mutex->__data.__count != 0) + /* We still hold the mutex. */ + return ENOTRECOVERABLE; + + goto pi_notrecoverable; + } + + if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)) + return EPERM; + + if (--mutex->__data.__count != 0) + /* We still hold the mutex. */ + return 0; + + goto continue_pi_robust; + + case PTHREAD_MUTEX_PI_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_NORMAL_NP: + case PTHREAD_MUTEX_PI_ADAPTIVE_NP: + case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP: + if ((mutex->__data.__lock & FUTEX_TID_MASK) + != THREAD_GETMEM (THREAD_SELF, tid) + || ! lll_islocked (mutex->__data.__lock)) + return EPERM; + + /* If the previous owner died and the caller did not succeed in + making the state consistent, mark the mutex as unrecoverable + and make all waiters. */ + if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0 + && __builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_INCONSISTENT, 0)) + pi_notrecoverable: + newowner = PTHREAD_MUTEX_NOTRECOVERABLE; + + if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0) + { + continue_pi_robust: + /* Remove mutex from the list. + Note: robust PI futexes are signaled by setting bit 0. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + (void *) (((uintptr_t) &mutex->__data.__list.__next) + | 1)); + DEQUEUE_MUTEX (mutex); + } + + continue_pi_non_robust: + mutex->__data.__owner = newowner; + if (decr) + /* One less user. */ + --mutex->__data.__nusers; + + /* Unlock. */ + if ((mutex->__data.__lock & FUTEX_WAITERS) != 0 + || atomic_compare_and_exchange_bool_rel (&mutex->__data.__lock, 0, + THREAD_GETMEM (THREAD_SELF, + tid))) + { + int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; + int private = (robust + ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex) + : PTHREAD_MUTEX_PSHARED (mutex)); + INTERNAL_SYSCALL_DECL (__err); + INTERNAL_SYSCALL (futex, __err, 2, &mutex->__data.__lock, + __lll_private_flag (FUTEX_UNLOCK_PI, private)); + } + + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + break; + + case PTHREAD_MUTEX_PP_RECURSIVE_NP: + /* Recursive mutex. */ + if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)) + return EPERM; + + if (--mutex->__data.__count != 0) + /* We still hold the mutex. */ + return 0; + goto pp; + + case PTHREAD_MUTEX_PP_ERRORCHECK_NP: + /* Error checking mutex. */ + if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid) + || (mutex->__data.__lock & ~ PTHREAD_MUTEX_PRIO_CEILING_MASK) == 0) + return EPERM; + /* FALLTHROUGH */ + + case PTHREAD_MUTEX_PP_NORMAL_NP: + case PTHREAD_MUTEX_PP_ADAPTIVE_NP: + /* Always reset the owner field. */ + pp: + mutex->__data.__owner = 0; + + if (decr) + /* One less user. */ + --mutex->__data.__nusers; + + /* Unlock. */ + int newval, oldval; + do + { + oldval = mutex->__data.__lock; + newval = oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK; + } + while (atomic_compare_and_exchange_bool_rel (&mutex->__data.__lock, + newval, oldval)); + + if ((oldval & ~PTHREAD_MUTEX_PRIO_CEILING_MASK) > 1) + lll_futex_wake (&mutex->__data.__lock, 1, + PTHREAD_MUTEX_PSHARED (mutex)); + + int oldprio = newval >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT; + return __pthread_tpp_change_priority (oldprio, -1); + + default: + /* Correct code cannot set any other type. */ + return EINVAL; + } + + return 0; +} + + +int +attribute_hidden +__pthread_mutex_unlock ( + pthread_mutex_t *mutex) +{ + return __pthread_mutex_unlock_usercnt (mutex, 1); +} +strong_alias (__pthread_mutex_unlock, pthread_mutex_unlock) +strong_alias (__pthread_mutex_unlock, __pthread_mutex_unlock_internal) diff --git a/libpthread/nptl/pthread_mutexattr_destroy.c b/libpthread/nptl/pthread_mutexattr_destroy.c new file mode 100644 index 000000000..adf2884bf --- /dev/null +++ b/libpthread/nptl/pthread_mutexattr_destroy.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthreadP.h> + + +int +__pthread_mutexattr_destroy (pthread_mutexattr_t *attr) +{ + return 0; +} +strong_alias (__pthread_mutexattr_destroy, pthread_mutexattr_destroy) diff --git a/libpthread/nptl/pthread_mutexattr_getprioceiling.c b/libpthread/nptl/pthread_mutexattr_getprioceiling.c new file mode 100644 index 000000000..29e3eb218 --- /dev/null +++ b/libpthread/nptl/pthread_mutexattr_getprioceiling.c @@ -0,0 +1,48 @@ +/* Get priority ceiling setting from pthread_mutexattr_t. + Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2006. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthreadP.h> + + +int +pthread_mutexattr_getprioceiling ( + const pthread_mutexattr_t *attr, + int *prioceiling) +{ + const struct pthread_mutexattr *iattr; + int ceiling; + + iattr = (const struct pthread_mutexattr *) attr; + + ceiling = ((iattr->mutexkind & PTHREAD_MUTEXATTR_PRIO_CEILING_MASK) + >> PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT); + + if (! ceiling) + { + if (__sched_fifo_min_prio == -1) + __init_sched_fifo_prio (); + if (ceiling < __sched_fifo_min_prio) + ceiling = __sched_fifo_min_prio; + } + + *prioceiling = ceiling; + + return 0; +} diff --git a/libpthread/nptl/pthread_mutexattr_getprotocol.c b/libpthread/nptl/pthread_mutexattr_getprotocol.c new file mode 100644 index 000000000..49c5157f5 --- /dev/null +++ b/libpthread/nptl/pthread_mutexattr_getprotocol.c @@ -0,0 +1,37 @@ +/* Get priority protocol setting from pthread_mutexattr_t. + Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2006. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthreadP.h> + + +int +pthread_mutexattr_getprotocol ( + const pthread_mutexattr_t *attr, + int *protocol) +{ + const struct pthread_mutexattr *iattr; + + iattr = (const struct pthread_mutexattr *) attr; + + *protocol = ((iattr->mutexkind & PTHREAD_MUTEXATTR_PROTOCOL_MASK) + >> PTHREAD_MUTEXATTR_PROTOCOL_SHIFT); + + return 0; +} diff --git a/libpthread/nptl/pthread_mutexattr_getpshared.c b/libpthread/nptl/pthread_mutexattr_getpshared.c new file mode 100644 index 000000000..e67cf15cf --- /dev/null +++ b/libpthread/nptl/pthread_mutexattr_getpshared.c @@ -0,0 +1,36 @@ +/* Copyright (C) 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthreadP.h> + + +int +pthread_mutexattr_getpshared ( + const pthread_mutexattr_t *attr, + int *pshared) +{ + const struct pthread_mutexattr *iattr; + + iattr = (const struct pthread_mutexattr *) attr; + + *pshared = ((iattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_PSHARED) != 0 + ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE); + + return 0; +} diff --git a/libpthread/nptl/pthread_mutexattr_getrobust.c b/libpthread/nptl/pthread_mutexattr_getrobust.c new file mode 100644 index 000000000..7d495f8ff --- /dev/null +++ b/libpthread/nptl/pthread_mutexattr_getrobust.c @@ -0,0 +1,37 @@ +/* Copyright (C) 2005, 2010 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2005. + + 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_mutexattr_getrobust ( + const pthread_mutexattr_t *attr, + int *robustness) +{ + const struct pthread_mutexattr *iattr; + + iattr = (const struct pthread_mutexattr *) attr; + + *robustness = ((iattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) != 0 + ? PTHREAD_MUTEX_ROBUST_NP : PTHREAD_MUTEX_STALLED_NP); + + return 0; +} +weak_alias (pthread_mutexattr_getrobust, pthread_mutexattr_getrobust_np) diff --git a/libpthread/nptl/pthread_mutexattr_gettype.c b/libpthread/nptl/pthread_mutexattr_gettype.c new file mode 100644 index 000000000..25434861f --- /dev/null +++ b/libpthread/nptl/pthread_mutexattr_gettype.c @@ -0,0 +1,36 @@ +/* Copyright (C) 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthreadP.h> + + +int +pthread_mutexattr_gettype ( + const pthread_mutexattr_t *attr, + int *kind) +{ + const struct pthread_mutexattr *iattr; + + iattr = (const struct pthread_mutexattr *) attr; + + *kind = iattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS; + + return 0; +} +weak_alias (pthread_mutexattr_gettype, pthread_mutexattr_getkind_np) diff --git a/libpthread/nptl/pthread_mutexattr_init.c b/libpthread/nptl/pthread_mutexattr_init.c new file mode 100644 index 000000000..1b6728462 --- /dev/null +++ b/libpthread/nptl/pthread_mutexattr_init.c @@ -0,0 +1,38 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <string.h> +#include <pthreadP.h> + + +int +__pthread_mutexattr_init ( + pthread_mutexattr_t *attr) +{ + if (sizeof (struct pthread_mutexattr) != sizeof (pthread_mutexattr_t)) + memset (attr, '\0', sizeof (*attr)); + + /* We use bit 31 to signal whether the mutex is going to be + process-shared or not. By default it is zero, i.e., the mutex is + not process-shared. */ + ((struct pthread_mutexattr *) attr)->mutexkind = PTHREAD_MUTEX_NORMAL; + + return 0; +} +strong_alias (__pthread_mutexattr_init, pthread_mutexattr_init) diff --git a/libpthread/nptl/pthread_mutexattr_setprioceiling.c b/libpthread/nptl/pthread_mutexattr_setprioceiling.c new file mode 100644 index 000000000..3a13fb8e0 --- /dev/null +++ b/libpthread/nptl/pthread_mutexattr_setprioceiling.c @@ -0,0 +1,47 @@ +/* Change priority ceiling setting in pthread_mutexattr_t. + Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2006. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <pthreadP.h> + + +int +pthread_mutexattr_setprioceiling ( + pthread_mutexattr_t *attr, + int prioceiling) +{ + if (__sched_fifo_min_prio == -1) + __init_sched_fifo_prio (); + + if (__builtin_expect (prioceiling < __sched_fifo_min_prio, 0) + || __builtin_expect (prioceiling > __sched_fifo_max_prio, 0) + || __builtin_expect ((prioceiling + & (PTHREAD_MUTEXATTR_PRIO_CEILING_MASK + >> PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT)) + != prioceiling, 0)) + return EINVAL; + + struct pthread_mutexattr *iattr = (struct pthread_mutexattr *) attr; + + iattr->mutexkind = ((iattr->mutexkind & ~PTHREAD_MUTEXATTR_PRIO_CEILING_MASK) + | (prioceiling << PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT)); + + return 0; +} diff --git a/libpthread/nptl/pthread_mutexattr_setprotocol.c b/libpthread/nptl/pthread_mutexattr_setprotocol.c new file mode 100644 index 000000000..1ffcaf63e --- /dev/null +++ b/libpthread/nptl/pthread_mutexattr_setprotocol.c @@ -0,0 +1,41 @@ +/* Change priority protocol setting in pthread_mutexattr_t. + Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2006. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <pthreadP.h> + + +int +pthread_mutexattr_setprotocol ( + pthread_mutexattr_t *attr, + int protocol) +{ + if (protocol != PTHREAD_PRIO_NONE + && protocol != PTHREAD_PRIO_INHERIT + && __builtin_expect (protocol != PTHREAD_PRIO_PROTECT, 0)) + return EINVAL; + + struct pthread_mutexattr *iattr = (struct pthread_mutexattr *) attr; + + iattr->mutexkind = ((iattr->mutexkind & ~PTHREAD_MUTEXATTR_PROTOCOL_MASK) + | (protocol << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT)); + + return 0; +} diff --git a/libpthread/nptl/pthread_mutexattr_setpshared.c b/libpthread/nptl/pthread_mutexattr_setpshared.c new file mode 100644 index 000000000..d84a92ea3 --- /dev/null +++ b/libpthread/nptl/pthread_mutexattr_setpshared.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <pthreadP.h> + + +int +pthread_mutexattr_setpshared ( + pthread_mutexattr_t *attr, + int pshared) +{ + struct pthread_mutexattr *iattr; + + if (pshared != PTHREAD_PROCESS_PRIVATE + && __builtin_expect (pshared != PTHREAD_PROCESS_SHARED, 0)) + return EINVAL; + + iattr = (struct pthread_mutexattr *) attr; + + if (pshared == PTHREAD_PROCESS_PRIVATE) + iattr->mutexkind &= ~PTHREAD_MUTEXATTR_FLAG_PSHARED; + else + iattr->mutexkind |= PTHREAD_MUTEXATTR_FLAG_PSHARED; + + return 0; +} diff --git a/libpthread/nptl/pthread_mutexattr_setrobust.c b/libpthread/nptl/pthread_mutexattr_setrobust.c new file mode 100644 index 000000000..fe94fd266 --- /dev/null +++ b/libpthread/nptl/pthread_mutexattr_setrobust.c @@ -0,0 +1,44 @@ +/* Copyright (C) 2005, 2010 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2005. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <pthreadP.h> + + +int +pthread_mutexattr_setrobust ( + pthread_mutexattr_t *attr, + int robustness) +{ + if (robustness != PTHREAD_MUTEX_STALLED_NP + && __builtin_expect (robustness != PTHREAD_MUTEX_ROBUST_NP, 0)) + return EINVAL; + + struct pthread_mutexattr *iattr = (struct pthread_mutexattr *) attr; + + /* We use bit 30 to signal whether the mutex is going to be + robust or not. */ + if (robustness == PTHREAD_MUTEX_STALLED_NP) + iattr->mutexkind &= ~PTHREAD_MUTEXATTR_FLAG_ROBUST; + else + iattr->mutexkind |= PTHREAD_MUTEXATTR_FLAG_ROBUST; + + return 0; +} +weak_alias (pthread_mutexattr_setrobust, pthread_mutexattr_setrobust_np) diff --git a/libpthread/nptl/pthread_mutexattr_settype.c b/libpthread/nptl/pthread_mutexattr_settype.c new file mode 100644 index 000000000..f86dd63a9 --- /dev/null +++ b/libpthread/nptl/pthread_mutexattr_settype.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <pthreadP.h> + + +int +__pthread_mutexattr_settype ( + pthread_mutexattr_t *attr, + int kind) +{ + struct pthread_mutexattr *iattr; + + if (kind < PTHREAD_MUTEX_NORMAL || kind > PTHREAD_MUTEX_ADAPTIVE_NP) + return EINVAL; + + iattr = (struct pthread_mutexattr *) attr; + + iattr->mutexkind = (iattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_BITS) | kind; + + return 0; +} +weak_alias (__pthread_mutexattr_settype, pthread_mutexattr_setkind_np) +strong_alias (__pthread_mutexattr_settype, pthread_mutexattr_settype) diff --git a/libpthread/nptl/pthread_rwlock_destroy.c b/libpthread/nptl/pthread_rwlock_destroy.c new file mode 100644 index 000000000..d38202b43 --- /dev/null +++ b/libpthread/nptl/pthread_rwlock_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 <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +__pthread_rwlock_destroy (pthread_rwlock_t *rwlock) +{ + /* Nothing to be done. For now. */ + return 0; +} +strong_alias (__pthread_rwlock_destroy, pthread_rwlock_destroy) diff --git a/libpthread/nptl/pthread_rwlock_init.c b/libpthread/nptl/pthread_rwlock_init.c new file mode 100644 index 000000000..aab832eea --- /dev/null +++ b/libpthread/nptl/pthread_rwlock_init.c @@ -0,0 +1,73 @@ +/* Copyright (C) 2002, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" +#include <bits/kernel-features.h> + + +static const struct pthread_rwlockattr default_attr = + { + .lockkind = PTHREAD_RWLOCK_DEFAULT_NP, + .pshared = PTHREAD_PROCESS_PRIVATE + }; + + +int +__pthread_rwlock_init ( + pthread_rwlock_t *rwlock, + const pthread_rwlockattr_t *attr) +{ + const struct pthread_rwlockattr *iattr; + + iattr = ((const struct pthread_rwlockattr *) attr) ?: &default_attr; + + memset (rwlock, '\0', sizeof (*rwlock)); + + rwlock->__data.__flags + = iattr->lockkind == PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP; + + /* The __SHARED field is computed to minimize the work that needs to + be done while handling the futex. There are two inputs: the + availability of private futexes and whether the rwlock is shared + or private. Unfortunately the value of a private rwlock is + fixed: it must be zero. The PRIVATE_FUTEX flag has the value + 0x80 in case private futexes are available and zero otherwise. + This leads to the following table: + + | pshared | result + | shared private | shared private | + ------------+-----------------+-----------------+ + !avail 0 | 0 0 | 0 0 | + avail 0x80 | 0x80 0 | 0 0x80 | + + If the pshared value is in locking functions XORed with avail + we get the expected result. */ +#ifdef __ASSUME_PRIVATE_FUTEX + rwlock->__data.__shared = (iattr->pshared == PTHREAD_PROCESS_PRIVATE + ? 0 : FUTEX_PRIVATE_FLAG); +#else + rwlock->__data.__shared = (iattr->pshared == PTHREAD_PROCESS_PRIVATE + ? 0 + : THREAD_GETMEM (THREAD_SELF, + header.private_futex)); +#endif + + return 0; +} +strong_alias (__pthread_rwlock_init, pthread_rwlock_init) diff --git a/libpthread/nptl/pthread_rwlock_tryrdlock.c b/libpthread/nptl/pthread_rwlock_tryrdlock.c new file mode 100644 index 000000000..30e6dc5a5 --- /dev/null +++ b/libpthread/nptl/pthread_rwlock_tryrdlock.c @@ -0,0 +1,50 @@ +/* Copyright (C) 2002, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include "pthreadP.h" +#include <lowlevellock.h> + + +int +__pthread_rwlock_tryrdlock ( + pthread_rwlock_t *rwlock) +{ + int result = EBUSY; + + lll_lock (rwlock->__data.__lock, rwlock->__data.__shared); + + if (rwlock->__data.__writer == 0 + && (rwlock->__data.__nr_writers_queued == 0 + || PTHREAD_RWLOCK_PREFER_READER_P (rwlock))) + { + if (__builtin_expect (++rwlock->__data.__nr_readers == 0, 0)) + { + --rwlock->__data.__nr_readers; + result = EAGAIN; + } + else + result = 0; + } + + lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + + return result; +} +strong_alias (__pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock) diff --git a/libpthread/nptl/pthread_rwlock_trywrlock.c b/libpthread/nptl/pthread_rwlock_trywrlock.c new file mode 100644 index 000000000..a6f9ee435 --- /dev/null +++ b/libpthread/nptl/pthread_rwlock_trywrlock.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include "pthreadP.h" +#include <lowlevellock.h> + + +int +__pthread_rwlock_trywrlock ( + pthread_rwlock_t *rwlock) +{ + int result = EBUSY; + + lll_lock (rwlock->__data.__lock, rwlock->__data.__shared); + + if (rwlock->__data.__writer == 0 && rwlock->__data.__nr_readers == 0) + { + rwlock->__data.__writer = THREAD_GETMEM (THREAD_SELF, tid); + result = 0; + } + + lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + + return result; +} +strong_alias (__pthread_rwlock_trywrlock, pthread_rwlock_trywrlock) diff --git a/libpthread/nptl/pthread_rwlockattr_destroy.c b/libpthread/nptl/pthread_rwlockattr_destroy.c new file mode 100644 index 000000000..db1870413 --- /dev/null +++ b/libpthread/nptl/pthread_rwlockattr_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 <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr) +{ + /* Nothing to do. For now. */ + + return 0; +} diff --git a/libpthread/nptl/pthread_rwlockattr_getkind_np.c b/libpthread/nptl/pthread_rwlockattr_getkind_np.c new file mode 100644 index 000000000..b15275c4d --- /dev/null +++ b/libpthread/nptl/pthread_rwlockattr_getkind_np.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_rwlockattr_getkind_np ( + const pthread_rwlockattr_t *attr, + int *pref) +{ + *pref = ((const struct pthread_rwlockattr *) attr)->lockkind; + + return 0; +} diff --git a/libpthread/nptl/pthread_rwlockattr_getpshared.c b/libpthread/nptl/pthread_rwlockattr_getpshared.c new file mode 100644 index 000000000..2e0437c78 --- /dev/null +++ b/libpthread/nptl/pthread_rwlockattr_getpshared.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_rwlockattr_getpshared ( + const pthread_rwlockattr_t *attr, + int *pshared) +{ + *pshared = ((const struct pthread_rwlockattr *) attr)->pshared; + + return 0; +} diff --git a/libpthread/nptl/pthread_rwlockattr_init.c b/libpthread/nptl/pthread_rwlockattr_init.c new file mode 100644 index 000000000..b33ae5bff --- /dev/null +++ b/libpthread/nptl/pthread_rwlockattr_init.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_rwlockattr_init (pthread_rwlockattr_t *attr) +{ + struct pthread_rwlockattr *iattr; + + iattr = (struct pthread_rwlockattr *) attr; + + iattr->lockkind = PTHREAD_RWLOCK_DEFAULT_NP; + iattr->pshared = PTHREAD_PROCESS_PRIVATE; + + return 0; +} diff --git a/libpthread/nptl/pthread_rwlockattr_setkind_np.c b/libpthread/nptl/pthread_rwlockattr_setkind_np.c new file mode 100644 index 000000000..186bf737b --- /dev/null +++ b/libpthread/nptl/pthread_rwlockattr_setkind_np.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include "pthreadP.h" + + +int +pthread_rwlockattr_setkind_np ( + pthread_rwlockattr_t *attr, + int pref) +{ + struct pthread_rwlockattr *iattr; + + if (pref != PTHREAD_RWLOCK_PREFER_READER_NP + && pref != PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP + && __builtin_expect (pref != PTHREAD_RWLOCK_PREFER_WRITER_NP, 0)) + return EINVAL; + + iattr = (struct pthread_rwlockattr *) attr; + + iattr->lockkind = pref; + + return 0; +} diff --git a/libpthread/nptl/pthread_rwlockattr_setpshared.c b/libpthread/nptl/pthread_rwlockattr_setpshared.c new file mode 100644 index 000000000..a30de0eeb --- /dev/null +++ b/libpthread/nptl/pthread_rwlockattr_setpshared.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include "pthreadP.h" + + +int +pthread_rwlockattr_setpshared ( + pthread_rwlockattr_t *attr, + int pshared) +{ + struct pthread_rwlockattr *iattr; + + if (pshared != PTHREAD_PROCESS_SHARED + && __builtin_expect (pshared != PTHREAD_PROCESS_PRIVATE, 0)) + return EINVAL; + + iattr = (struct pthread_rwlockattr *) attr; + + iattr->pshared = pshared; + + return 0; +} diff --git a/libpthread/nptl/pthread_self.c b/libpthread/nptl/pthread_self.c new file mode 100644 index 000000000..61cb2a7be --- /dev/null +++ b/libpthread/nptl/pthread_self.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" +#include <tls.h> + + +pthread_t +attribute_hidden +__pthread_self (void) +{ + return (pthread_t) THREAD_SELF; +} +strong_alias (__pthread_self, pthread_self) diff --git a/libpthread/nptl/pthread_setcancelstate.c b/libpthread/nptl/pthread_setcancelstate.c new file mode 100644 index 000000000..0da9a74f9 --- /dev/null +++ b/libpthread/nptl/pthread_setcancelstate.c @@ -0,0 +1,74 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include "pthreadP.h" +#include <atomic.h> + + +int +attribute_hidden +__pthread_setcancelstate ( + int state, + int *oldstate) +{ + volatile struct pthread *self; + + if (state < PTHREAD_CANCEL_ENABLE || state > PTHREAD_CANCEL_DISABLE) + return EINVAL; + + self = THREAD_SELF; + + int oldval = THREAD_GETMEM (self, cancelhandling); + while (1) + { + int newval = (state == PTHREAD_CANCEL_DISABLE + ? oldval | CANCELSTATE_BITMASK + : oldval & ~CANCELSTATE_BITMASK); + + /* Store the old value. */ + if (oldstate != NULL) + *oldstate = ((oldval & CANCELSTATE_BITMASK) + ? PTHREAD_CANCEL_DISABLE : PTHREAD_CANCEL_ENABLE); + + /* Avoid doing unnecessary work. The atomic operation can + potentially be expensive if the memory has to be locked and + remote cache lines have to be invalidated. */ + if (oldval == newval) + break; + + /* Update the cancel handling word. This has to be done + atomically since other bits could be modified as well. */ + int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval, + oldval); + if (__builtin_expect (curval == oldval, 1)) + { + if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval)) + __do_cancel (); + + break; + } + + /* Prepare for the next round. */ + oldval = curval; + } + + return 0; +} +strong_alias (__pthread_setcancelstate, pthread_setcancelstate) diff --git a/libpthread/nptl/pthread_setcanceltype.c b/libpthread/nptl/pthread_setcanceltype.c new file mode 100644 index 000000000..3cb723537 --- /dev/null +++ b/libpthread/nptl/pthread_setcanceltype.c @@ -0,0 +1,77 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include "pthreadP.h" +#include <atomic.h> + + +int +attribute_hidden +__pthread_setcanceltype ( + int type, + int *oldtype) +{ + volatile struct pthread *self; + + if (type < PTHREAD_CANCEL_DEFERRED || type > PTHREAD_CANCEL_ASYNCHRONOUS) + return EINVAL; + + self = THREAD_SELF; + + int oldval = THREAD_GETMEM (self, cancelhandling); + while (1) + { + int newval = (type == PTHREAD_CANCEL_ASYNCHRONOUS + ? oldval | CANCELTYPE_BITMASK + : oldval & ~CANCELTYPE_BITMASK); + + /* Store the old value. */ + if (oldtype != NULL) + *oldtype = ((oldval & CANCELTYPE_BITMASK) + ? PTHREAD_CANCEL_ASYNCHRONOUS : PTHREAD_CANCEL_DEFERRED); + + /* Avoid doing unnecessary work. The atomic operation can + potentially be expensive if the memory has to be locked and + remote cache lines have to be invalidated. */ + if (oldval == newval) + break; + + /* Update the cancel handling word. This has to be done + atomically since other bits could be modified as well. */ + int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval, + oldval); + if (__builtin_expect (curval == oldval, 1)) + { + if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval)) + { + THREAD_SETMEM (self, result, PTHREAD_CANCELED); + __do_cancel (); + } + + break; + } + + /* Prepare for the next round. */ + oldval = curval; + } + + return 0; +} +strong_alias (__pthread_setcanceltype, pthread_setcanceltype) diff --git a/libpthread/nptl/pthread_setconcurrency.c b/libpthread/nptl/pthread_setconcurrency.c new file mode 100644 index 000000000..754fe3f25 --- /dev/null +++ b/libpthread/nptl/pthread_setconcurrency.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include "pthreadP.h" + + +/* Global definition. Needed in pthread_getconcurrency as well. */ +int __concurrency_level; + + +int +pthread_setconcurrency (int level) +{ + if (level < 0) + return EINVAL; + + __concurrency_level = level; + + /* XXX For ports which actually need to handle the concurrency level + some more code is probably needed here. */ + + return 0; +} diff --git a/libpthread/nptl/pthread_setegid.c b/libpthread/nptl/pthread_setegid.c new file mode 100644 index 000000000..9252dfac7 --- /dev/null +++ b/libpthread/nptl/pthread_setegid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define setegid pthread_setegid_np +#include <setegid.c> diff --git a/libpthread/nptl/pthread_seteuid.c b/libpthread/nptl/pthread_seteuid.c new file mode 100644 index 000000000..47bb69802 --- /dev/null +++ b/libpthread/nptl/pthread_seteuid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define seteuid pthread_seteuid_np +#include <seteuid.c> diff --git a/libpthread/nptl/pthread_setgid.c b/libpthread/nptl/pthread_setgid.c new file mode 100644 index 000000000..b06bffbf3 --- /dev/null +++ b/libpthread/nptl/pthread_setgid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setgid pthread_setgid_np +#include <setgid.c> diff --git a/libpthread/nptl/pthread_setregid.c b/libpthread/nptl/pthread_setregid.c new file mode 100644 index 000000000..7461d2b7f --- /dev/null +++ b/libpthread/nptl/pthread_setregid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setregid pthread_setregid_np +#include <setregid.c> diff --git a/libpthread/nptl/pthread_setresgid.c b/libpthread/nptl/pthread_setresgid.c new file mode 100644 index 000000000..369fae267 --- /dev/null +++ b/libpthread/nptl/pthread_setresgid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setresgid pthread_setresgid_np +#include <setresgid.c> diff --git a/libpthread/nptl/pthread_setresuid.c b/libpthread/nptl/pthread_setresuid.c new file mode 100644 index 000000000..ac57c0fa8 --- /dev/null +++ b/libpthread/nptl/pthread_setresuid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setresuid pthread_setresuid_np +#include <setresuid.c> diff --git a/libpthread/nptl/pthread_setreuid.c b/libpthread/nptl/pthread_setreuid.c new file mode 100644 index 000000000..aa804ab01 --- /dev/null +++ b/libpthread/nptl/pthread_setreuid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setreuid pthread_setreuid_np +#include <setreuid.c> diff --git a/libpthread/nptl/pthread_setschedparam.c b/libpthread/nptl/pthread_setschedparam.c new file mode 100644 index 000000000..dabcb7c71 --- /dev/null +++ b/libpthread/nptl/pthread_setschedparam.c @@ -0,0 +1,75 @@ +/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <sched.h> +#include <string.h> +#include "pthreadP.h" +#include <lowlevellock.h> + + +int +attribute_hidden +__pthread_setschedparam ( + pthread_t threadid, + int policy, + const struct sched_param *param) +{ + struct pthread *pd = (struct pthread *) threadid; + + /* Make sure the descriptor is valid. */ + if (INVALID_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + + int result = 0; + + lll_lock (pd->lock, LLL_PRIVATE); + + struct sched_param p; + const struct sched_param *orig_param = param; + + /* If the thread should have higher priority because of some + PTHREAD_PRIO_PROTECT mutexes it holds, adjust the priority. */ + if (__builtin_expect (pd->tpp != NULL, 0) + && pd->tpp->priomax > param->sched_priority) + { + p = *param; + p.sched_priority = pd->tpp->priomax; + param = &p; + } + + /* Try to set the scheduler information. */ + if (__builtin_expect (__sched_setscheduler (pd->tid, policy, + param) == -1, 0)) + result = errno; + else + { + /* We succeeded changing the kernel information. Reflect this + change in the thread descriptor. */ + pd->schedpolicy = policy; + memcpy (&pd->schedparam, orig_param, sizeof (struct sched_param)); + pd->flags |= ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET; + } + + lll_unlock (pd->lock, LLL_PRIVATE); + + return result; +} +strong_alias (__pthread_setschedparam, pthread_setschedparam) diff --git a/libpthread/nptl/pthread_setschedprio.c b/libpthread/nptl/pthread_setschedprio.c new file mode 100644 index 000000000..7951460d8 --- /dev/null +++ b/libpthread/nptl/pthread_setschedprio.c @@ -0,0 +1,66 @@ +/* Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <sched.h> +#include <string.h> +#include <sched.h> +#include "pthreadP.h" +#include <lowlevellock.h> + + +int +pthread_setschedprio ( + pthread_t threadid, + int prio) +{ + struct pthread *pd = (struct pthread *) threadid; + + /* Make sure the descriptor is valid. */ + if (INVALID_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + + int result = 0; + struct sched_param param; + param.sched_priority = prio; + + lll_lock (pd->lock, LLL_PRIVATE); + + /* If the thread should have higher priority because of some + PTHREAD_PRIO_PROTECT mutexes it holds, adjust the priority. */ + if (__builtin_expect (pd->tpp != NULL, 0) && pd->tpp->priomax > prio) + param.sched_priority = pd->tpp->priomax; + + /* Try to set the scheduler information. */ + if (__builtin_expect (sched_setparam (pd->tid, ¶m) == -1, 0)) + result = errno; + else + { + /* We succeeded changing the kernel information. Reflect this + change in the thread descriptor. */ + param.sched_priority = prio; + memcpy (&pd->schedparam, ¶m, sizeof (struct sched_param)); + pd->flags |= ATTR_FLAG_SCHED_SET; + } + + lll_unlock (pd->lock, LLL_PRIVATE); + + return result; +} diff --git a/libpthread/nptl/pthread_setspecific.c b/libpthread/nptl/pthread_setspecific.c new file mode 100644 index 000000000..0f24d6879 --- /dev/null +++ b/libpthread/nptl/pthread_setspecific.c @@ -0,0 +1,97 @@ +/* Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdlib.h> +#include "pthreadP.h" + + +int +attribute_hidden +__pthread_setspecific ( + pthread_key_t key, + const void *value) +{ + struct pthread *self; + unsigned int idx1st; + unsigned int idx2nd; + struct pthread_key_data *level2; + unsigned int seq; + + self = THREAD_SELF; + + /* Special case access to the first 2nd-level block. This is the + usual case. */ + if (__builtin_expect (key < PTHREAD_KEY_2NDLEVEL_SIZE, 1)) + { + /* Verify the key is sane. */ + if (KEY_UNUSED ((seq = __pthread_keys[key].seq))) + /* Not valid. */ + return EINVAL; + + level2 = &self->specific_1stblock[key]; + + /* Remember that we stored at least one set of data. */ + if (value != NULL) + THREAD_SETMEM (self, specific_used, true); + } + else + { + if (key >= PTHREAD_KEYS_MAX + || KEY_UNUSED ((seq = __pthread_keys[key].seq))) + /* Not valid. */ + return EINVAL; + + idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; + idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; + + /* This is the second level array. Allocate it if necessary. */ + level2 = THREAD_GETMEM_NC (self, specific, idx1st); + if (level2 == NULL) + { + if (value == NULL) + /* We don't have to do anything. The value would in any case + be NULL. We can save the memory allocation. */ + return 0; + + level2 + = (struct pthread_key_data *) calloc (PTHREAD_KEY_2NDLEVEL_SIZE, + sizeof (*level2)); + if (level2 == NULL) + return ENOMEM; + + THREAD_SETMEM_NC (self, specific, idx1st, level2); + } + + /* Pointer to the right array element. */ + level2 = &level2[idx2nd]; + + /* Remember that we stored at least one set of data. */ + THREAD_SETMEM (self, specific_used, true); + } + + /* Store the data and the sequence number so that we can recognize + stale data. */ + level2->seq = seq; + level2->data = (void *) value; + + return 0; +} +strong_alias (__pthread_setspecific, pthread_setspecific) +strong_alias (__pthread_setspecific, __pthread_setspecific_internal) diff --git a/libpthread/nptl/pthread_setuid.c b/libpthread/nptl/pthread_setuid.c new file mode 100644 index 000000000..ff949c850 --- /dev/null +++ b/libpthread/nptl/pthread_setuid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setuid pthread_setuid_np +#include <setuid.c> diff --git a/libpthread/nptl/pthread_testcancel.c b/libpthread/nptl/pthread_testcancel.c new file mode 100644 index 000000000..e9b17b493 --- /dev/null +++ b/libpthread/nptl/pthread_testcancel.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stdlib.h> +#include "pthreadP.h" + + +void +pthread_testcancel (void) +{ + CANCELLATION_P (THREAD_SELF); +} diff --git a/libpthread/nptl/pthread_timedjoin.c b/libpthread/nptl/pthread_timedjoin.c new file mode 100644 index 000000000..4098a7373 --- /dev/null +++ b/libpthread/nptl/pthread_timedjoin.c @@ -0,0 +1,107 @@ +/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdlib.h> +#include <atomic.h> +#include "pthreadP.h" + + +static void +cleanup (void *arg) +{ + *(void **) arg = NULL; +} + + +int +pthread_timedjoin_np ( + pthread_t threadid, + void **thread_return, + const struct timespec *abstime) +{ + struct pthread *self; + struct pthread *pd = (struct pthread *) threadid; + int result; + + /* Make sure the descriptor is valid. */ + if (INVALID_NOT_TERMINATED_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + + /* Is the thread joinable?. */ + if (IS_DETACHED (pd)) + /* We cannot wait for the thread. */ + return EINVAL; + + self = THREAD_SELF; + if (pd == self || self->joinid == pd) + /* This is a deadlock situation. The threads are waiting for each + other to finish. Note that this is a "may" error. To be 100% + sure we catch this error we would have to lock the data + structures but it is not necessary. In the unlikely case that + two threads are really caught in this situation they will + deadlock. It is the programmer's problem to figure this + out. */ + return EDEADLK; + + /* Wait for the thread to finish. If it is already locked something + is wrong. There can only be one waiter. */ + if (__builtin_expect (atomic_compare_and_exchange_bool_acq (&pd->joinid, + self, NULL), 0)) + /* There is already somebody waiting for the thread. */ + return EINVAL; + + + /* During the wait we change to asynchronous cancellation. If we + are cancelled the thread we are waiting for must be marked as + un-wait-ed for again. */ + pthread_cleanup_push (cleanup, &pd->joinid); + + /* Switch to asynchronous cancellation. */ + int oldtype = CANCEL_ASYNC (); + + + /* Wait for the child. */ + result = lll_timedwait_tid (pd->tid, abstime); + + + /* Restore cancellation mode. */ + CANCEL_RESET (oldtype); + + /* Remove the handler. */ + pthread_cleanup_pop (0); + + + /* We might have timed out. */ + if (result == 0) + { + /* Store the return value if the caller is interested. */ + if (thread_return != NULL) + *thread_return = pd->result; + + + /* Free the TCB. */ + __free_tcb (pd); + } + else + pd->joinid = NULL; + + return result; +} diff --git a/libpthread/nptl/pthread_tryjoin.c b/libpthread/nptl/pthread_tryjoin.c new file mode 100644 index 000000000..5746a9e9b --- /dev/null +++ b/libpthread/nptl/pthread_tryjoin.c @@ -0,0 +1,75 @@ +/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdlib.h> + +#include <atomic.h> +#include "pthreadP.h" + + +int +pthread_tryjoin_np ( + pthread_t threadid, + void **thread_return) +{ + struct pthread *self; + struct pthread *pd = (struct pthread *) threadid; + + /* Make sure the descriptor is valid. */ + if (DEBUGGING_P && __find_in_stack_list (pd) == NULL) + /* Not a valid thread handle. */ + return ESRCH; + + /* Is the thread joinable?. */ + if (IS_DETACHED (pd)) + /* We cannot wait for the thread. */ + return EINVAL; + + self = THREAD_SELF; + if (pd == self || self->joinid == pd) + /* This is a deadlock situation. The threads are waiting for each + other to finish. Note that this is a "may" error. To be 100% + sure we catch this error we would have to lock the data + structures but it is not necessary. In the unlikely case that + two threads are really caught in this situation they will + deadlock. It is the programmer's problem to figure this + out. */ + return EDEADLK; + + /* Return right away if the thread hasn't terminated yet. */ + if (pd->tid != 0) + return EBUSY; + + /* Wait for the thread to finish. If it is already locked something + is wrong. There can only be one waiter. */ + if (atomic_compare_and_exchange_bool_acq (&pd->joinid, self, NULL)) + /* There is already somebody waiting for the thread. */ + return EINVAL; + + /* Store the return value if the caller is interested. */ + if (thread_return != NULL) + *thread_return = pd->result; + + + /* Free the TCB. */ + __free_tcb (pd); + + return 0; +} diff --git a/libpthread/nptl/res.c b/libpthread/nptl/res.c new file mode 100644 index 000000000..6a4d18b17 --- /dev/null +++ b/libpthread/nptl/res.c @@ -0,0 +1,27 @@ +/* Copyright (C) 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <features.h> +#include <tls.h> +#include <resolv.h> + +struct __res_state * +__res_state (void) +{ + return __resp; +} diff --git a/libpthread/nptl/sem_close.c b/libpthread/nptl/sem_close.c new file mode 100644 index 000000000..dcf30f7b7 --- /dev/null +++ b/libpthread/nptl/sem_close.c @@ -0,0 +1,81 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <search.h> +#include <sys/mman.h> +#include "semaphoreP.h" + + +/* Global variables to parametrize the walk function. This works + since we always have to use locks. And we have to use the twalk + function since the entries are not sorted wrt the mapping + address. */ +static sem_t *the_sem; +static struct inuse_sem *rec; + +static void +walker (const void *inodep, const VISIT which, const int depth) +{ + struct inuse_sem *nodep = *(struct inuse_sem **) inodep; + + if (nodep->sem == the_sem) + rec = nodep; +} + + +int +sem_close ( + sem_t *sem) +{ + int result = 0; + + /* Get the lock. */ + lll_lock (__sem_mappings_lock, LLL_PRIVATE); + + /* Locate the entry for the mapping the caller provided. */ + rec = NULL; + the_sem = sem; + twalk (__sem_mappings, walker); + if (rec != NULL) + { + /* Check the reference counter. If it is going to be zero, free + all the resources. */ + if (--rec->refcnt == 0) + { + /* Remove the record from the tree. */ + (void) tdelete (rec, &__sem_mappings, __sem_search); + + result = munmap (rec->sem, sizeof (sem_t)); + + free (rec); + } + } + else + { + /* This is no valid semaphore. */ + result = -1; + __set_errno (EINVAL); + } + + /* Release the lock. */ + lll_unlock (__sem_mappings_lock, LLL_PRIVATE); + + return result; +} diff --git a/libpthread/nptl/sem_destroy.c b/libpthread/nptl/sem_destroy.c new file mode 100644 index 000000000..6362c0e3c --- /dev/null +++ b/libpthread/nptl/sem_destroy.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <semaphore.h> +#include "semaphoreP.h" + + +int +__new_sem_destroy ( + sem_t *sem) +{ + /* XXX Check for valid parameter. */ + + /* Nothing to do. */ + return 0; +} +weak_alias(__new_sem_destroy, sem_destroy) diff --git a/libpthread/nptl/sem_getvalue.c b/libpthread/nptl/sem_getvalue.c new file mode 100644 index 000000000..928026fcb --- /dev/null +++ b/libpthread/nptl/sem_getvalue.c @@ -0,0 +1,37 @@ +/* Copyright (C) 2002, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <semaphore.h> +#include "semaphoreP.h" + + +int +__new_sem_getvalue ( + sem_t *sem, + int *sval) +{ + struct new_sem *isem = (struct new_sem *) sem; + + /* XXX Check for valid SEM parameter. */ + + *sval = isem->value; + + return 0; +} +weak_alias(__new_sem_getvalue, sem_getvalue) diff --git a/libpthread/nptl/sem_init.c b/libpthread/nptl/sem_init.c new file mode 100644 index 000000000..0a224f3ad --- /dev/null +++ b/libpthread/nptl/sem_init.c @@ -0,0 +1,56 @@ +/* Copyright (C) 2002, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <semaphore.h> +#include <lowlevellock.h> +#include "semaphoreP.h" +#include <bits/kernel-features.h> + + +int +__new_sem_init ( + sem_t *sem, + int pshared, + unsigned int value) +{ + /* Parameter sanity check. */ + if (__builtin_expect (value > SEM_VALUE_MAX, 0)) + { + __set_errno (EINVAL); + return -1; + } + + /* Map to the internal type. */ + struct new_sem *isem = (struct new_sem *) sem; + + /* Use the values the user provided. */ + isem->value = value; +#ifdef __ASSUME_PRIVATE_FUTEX + isem->private = pshared ? 0 : FUTEX_PRIVATE_FLAG; +#else + isem->private = pshared ? 0 : THREAD_GETMEM (THREAD_SELF, + header.private_futex); +#endif + + isem->nwaiters = 0; + + return 0; +} +weak_alias(__new_sem_init, sem_init) diff --git a/libpthread/nptl/sem_open.c b/libpthread/nptl/sem_open.c new file mode 100644 index 000000000..8ded82cf1 --- /dev/null +++ b/libpthread/nptl/sem_open.c @@ -0,0 +1,396 @@ +/* Copyright (C) 2002, 2003, 2006, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <fcntl.h> +#include <mntent.h> +#include <paths.h> +#include <pthread.h> +#include <search.h> +#include <semaphore.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/statfs.h> +#include <linux_fsinfo.h> +#include "semaphoreP.h" +#include "../../libc/misc/internals/tempname.h" + + +/* Compatibility defines. */ +#define __endmntent endmntent +#define __fxstat64(vers, fd, buf) fstat64(fd, buf) +#define __getmntent_r getmntent_r +#define __setmntent setmntent +#define __statfs statfs +#define __libc_close close +#define __libc_open open +#define __libc_write write + + +/* Information about the mount point. */ +struct mountpoint_info mountpoint attribute_hidden; + +/* This is the default mount point. */ +static const char defaultmount[] = "/dev/shm"; +/* This is the default directory. */ +static const char defaultdir[] = "/dev/shm/sem."; + +/* Protect the `mountpoint' variable above. */ +pthread_once_t __namedsem_once attribute_hidden = PTHREAD_ONCE_INIT; + + +/* Determine where the shmfs is mounted (if at all). */ +void +attribute_hidden +__where_is_shmfs (void) +{ + char buf[512]; + struct statfs f; + struct mntent resmem; + struct mntent *mp; + FILE *fp; + + /* The canonical place is /dev/shm. This is at least what the + documentation tells everybody to do. */ + if (__statfs (defaultmount, &f) == 0 && f.f_type == SHMFS_SUPER_MAGIC) + { + /* It is in the normal place. */ + mountpoint.dir = (char *) defaultdir; + mountpoint.dirlen = sizeof (defaultdir) - 1; + + return; + } + + /* OK, do it the hard way. Look through the /proc/mounts file and if + this does not exist through /etc/fstab to find the mount point. */ + fp = __setmntent ("/proc/mounts", "r"); + if (__builtin_expect (fp == NULL, 0)) + { + fp = __setmntent (_PATH_MNTTAB, "r"); + if (__builtin_expect (fp == NULL, 0)) + /* There is nothing we can do. Blind guesses are not helpful. */ + return; + } + + /* Now read the entries. */ + while ((mp = __getmntent_r (fp, &resmem, buf, sizeof buf)) != NULL) + /* The original name is "shm" but this got changed in early Linux + 2.4.x to "tmpfs". */ + if (strcmp (mp->mnt_type, "tmpfs") == 0 + || strcmp (mp->mnt_type, "shm") == 0) + { + /* Found it. There might be more than one place where the + filesystem is mounted but one is enough for us. */ + size_t namelen; + + /* First make sure this really is the correct entry. At least + some versions of the kernel give wrong information because + of the implicit mount of the shmfs for SysV IPC. */ + if (__statfs (mp->mnt_dir, &f) != 0 || f.f_type != SHMFS_SUPER_MAGIC) + continue; + + namelen = strlen (mp->mnt_dir); + + if (namelen == 0) + /* Hum, maybe some crippled entry. Keep on searching. */ + continue; + + mountpoint.dir = (char *) malloc (namelen + 4 + 2); + if (mountpoint.dir != NULL) + { + char *cp = mempcpy (mountpoint.dir, mp->mnt_dir, namelen); + if (cp[-1] != '/') + *cp++ = '/'; + cp = stpcpy (cp, "sem."); + mountpoint.dirlen = cp - mountpoint.dir; + } + + break; + } + + /* Close the stream. */ + __endmntent (fp); +} + + +/* Comparison function for search of existing mapping. */ +int +attribute_hidden +__sem_search (const void *a, const void *b) +{ + const struct inuse_sem *as = (const struct inuse_sem *) a; + const struct inuse_sem *bs = (const struct inuse_sem *) b; + + if (as->ino != bs->ino) + /* Cannot return the difference the type is larger than int. */ + return as->ino < bs->ino ? -1 : (as->ino == bs->ino ? 0 : 1); + + if (as->dev != bs->dev) + /* Cannot return the difference the type is larger than int. */ + return as->dev < bs->dev ? -1 : (as->dev == bs->dev ? 0 : 1); + + return strcmp (as->name, bs->name); +} + + +/* The search tree for existing mappings. */ +void *__sem_mappings attribute_hidden; + +/* Lock to protect the search tree. */ +int __sem_mappings_lock attribute_hidden = LLL_LOCK_INITIALIZER; + + +/* Search for existing mapping and if possible add the one provided. */ +static sem_t * +check_add_mapping (const char *name, size_t namelen, int fd, sem_t *existing) +{ + sem_t *result = SEM_FAILED; + + /* Get the information about the file. */ +#ifdef __UCLIBC_HAS_LFS__ + struct stat64 st; + if (__fxstat64 (_STAT_VER, fd, &st) == 0) +#else + struct stat st; + if (fstat (fd, &st) == 0) +#endif + { + /* Get the lock. */ + lll_lock (__sem_mappings_lock, LLL_PRIVATE); + + /* Search for an existing mapping given the information we have. */ + struct inuse_sem *fake; + fake = (struct inuse_sem *) alloca (sizeof (*fake) + namelen); + memcpy (fake->name, name, namelen); + fake->dev = st.st_dev; + fake->ino = st.st_ino; + + struct inuse_sem **foundp = tfind (fake, &__sem_mappings, __sem_search); + if (foundp != NULL) + { + /* There is already a mapping. Use it. */ + result = (*foundp)->sem; + ++(*foundp)->refcnt; + } + else + { + /* We haven't found a mapping. Install ione. */ + struct inuse_sem *newp; + + newp = (struct inuse_sem *) malloc (sizeof (*newp) + namelen); + if (newp != NULL) + { + /* If the caller hasn't provided any map it now. */ + if (existing == SEM_FAILED) + existing = (sem_t *) mmap (NULL, sizeof (sem_t), + PROT_READ | PROT_WRITE, MAP_SHARED, + fd, 0); + + newp->dev = st.st_dev; + newp->ino = st.st_ino; + newp->refcnt = 1; + newp->sem = existing; + memcpy (newp->name, name, namelen); + + /* Insert the new value. */ + if (existing != MAP_FAILED + && tsearch (newp, &__sem_mappings, __sem_search) != NULL) + /* Successful. */ + result = existing; + else + /* Something went wrong while inserting the new + value. We fail completely. */ + free (newp); + } + } + + /* Release the lock. */ + lll_unlock (__sem_mappings_lock, LLL_PRIVATE); + } + + if (result != existing && existing != SEM_FAILED && existing != MAP_FAILED) + { + /* Do not disturb errno. */ + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (munmap, err, 2, existing, sizeof (sem_t)); + } + + return result; +} + + +sem_t * +sem_open (const char *name, int oflag, ...) +{ + char *finalname; + sem_t *result = SEM_FAILED; + int fd; + + /* Determine where the shmfs is mounted. */ + __pthread_once (&__namedsem_once, __where_is_shmfs); + + /* If we don't know the mount points there is nothing we can do. Ever. */ + if (mountpoint.dir == NULL) + { + __set_errno (ENOSYS); + return SEM_FAILED; + } + + /* Construct the filename. */ + while (name[0] == '/') + ++name; + + if (name[0] == '\0') + { + /* The name "/" is not supported. */ + __set_errno (EINVAL); + return SEM_FAILED; + } + size_t namelen = strlen (name) + 1; + + /* Create the name of the final file. */ + finalname = (char *) alloca (mountpoint.dirlen + namelen); + mempcpy (mempcpy (finalname, mountpoint.dir, mountpoint.dirlen), + name, namelen); + + /* If the semaphore object has to exist simply open it. */ + if ((oflag & O_CREAT) == 0 || (oflag & O_EXCL) == 0) + { + try_again: + fd = __libc_open (finalname, + (oflag & ~(O_CREAT|O_ACCMODE)) | O_NOFOLLOW | O_RDWR); + + if (fd == -1) + { + /* If we are supposed to create the file try this next. */ + if ((oflag & O_CREAT) != 0 && errno == ENOENT) + goto try_create; + + /* Return. errno is already set. */ + } + else + /* Check whether we already have this semaphore mapped and + create one if necessary. */ + result = check_add_mapping (name, namelen, fd, SEM_FAILED); + } + else + { + /* We have to open a temporary file first since it must have the + correct form before we can start using it. */ + char *tmpfname; + mode_t mode; + unsigned int value; + va_list ap; + + try_create: + va_start (ap, oflag); + + mode = va_arg (ap, mode_t); + value = va_arg (ap, unsigned int); + + va_end (ap); + + if (value > SEM_VALUE_MAX) + { + __set_errno (EINVAL); + return SEM_FAILED; + } + + /* Create the initial file content. */ + union + { + sem_t initsem; + struct new_sem newsem; + } sem; + + sem.newsem.value = value; + sem.newsem.private = 0; + sem.newsem.nwaiters = 0; + + /* Initialize the remaining bytes as well. */ + memset ((char *) &sem.initsem + sizeof (struct new_sem), '\0', + sizeof (sem_t) - sizeof (struct new_sem)); + + tmpfname = (char *) alloca (mountpoint.dirlen + 6 + 1); + mempcpy (tmpfname, mountpoint.dir, mountpoint.dirlen); + + fd = __gen_tempname (tmpfname, __GT_FILE, mode); + if (fd == -1) + return SEM_FAILED; + + if (TEMP_FAILURE_RETRY (__libc_write (fd, &sem.initsem, sizeof (sem_t))) + == sizeof (sem_t) + /* Map the sem_t structure from the file. */ + && (result = (sem_t *) mmap (NULL, sizeof (sem_t), + PROT_READ | PROT_WRITE, MAP_SHARED, + fd, 0)) != MAP_FAILED) + { + /* Create the file. Don't overwrite an existing file. */ + if (link (tmpfname, finalname) != 0) + { + /* Undo the mapping. */ + (void) munmap (result, sizeof (sem_t)); + + /* Reinitialize 'result'. */ + result = SEM_FAILED; + + /* This failed. If O_EXCL is not set and the problem was + that the file exists, try again. */ + if ((oflag & O_EXCL) == 0 && errno == EEXIST) + { + /* Remove the file. */ + (void) unlink (tmpfname); + + /* Close the file. */ + (void) __libc_close (fd); + + goto try_again; + } + } + else + /* Insert the mapping into the search tree. This also + determines whether another thread sneaked by and already + added such a mapping despite the fact that we created it. */ + result = check_add_mapping (name, namelen, fd, result); + } + + /* Now remove the temporary name. This should never fail. If + it fails we leak a file name. Better fix the kernel. */ + (void) unlink (tmpfname); + } + + /* Map the mmap error to the error we need. */ + if (MAP_FAILED != (void *) SEM_FAILED && result == MAP_FAILED) + result = SEM_FAILED; + + /* We don't need the file descriptor anymore. */ + if (fd != -1) + { + /* Do not disturb errno. */ + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (close, err, 1, fd); + } + + return result; +} diff --git a/libpthread/nptl/sem_unlink.c b/libpthread/nptl/sem_unlink.c new file mode 100644 index 000000000..beed02ee5 --- /dev/null +++ b/libpthread/nptl/sem_unlink.c @@ -0,0 +1,67 @@ +/* Copyright (C) 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <semaphore.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "semaphoreP.h" + + +int +sem_unlink ( + const char *name) +{ + char *fname; + size_t namelen; + + /* Determine where the shmfs is mounted. */ + __pthread_once (&__namedsem_once, __where_is_shmfs); + + /* If we don't know the mount points there is nothing we can do. Ever. */ + if (mountpoint.dir == NULL) + { + __set_errno (ENOSYS); + return -1; + } + + /* Construct the filename. */ + while (name[0] == '/') + ++name; + + if (name[0] == '\0') + { + /* The name "/" is not supported. */ + __set_errno (ENOENT); + return -1; + } + namelen = strlen (name); + + /* Create the name of the file. */ + fname = (char *) alloca (mountpoint.dirlen + namelen + 1); + mempcpy (mempcpy (fname, mountpoint.dir, mountpoint.dirlen), + name, namelen + 1); + + /* Now try removing it. */ + int ret = unlink (fname); + if (ret < 0 && errno == EPERM) + __set_errno (EACCES); + return ret; +} diff --git a/libpthread/nptl/semaphore.h b/libpthread/nptl/semaphore.h new file mode 100644 index 000000000..4f13725b3 --- /dev/null +++ b/libpthread/nptl/semaphore.h @@ -0,0 +1,79 @@ +/* Copyright (C) 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SEMAPHORE_H +#define _SEMAPHORE_H 1 + +#include <features.h> +#include <sys/types.h> +#ifdef __USE_XOPEN2K +# define __need_timespec +# include <time.h> +#endif + +/* Get the definition for sem_t. */ +#include <bits/semaphore.h> + + +__BEGIN_DECLS + +/* Initialize semaphore object SEM to VALUE. If PSHARED then share it + with other processes. */ +extern int sem_init (sem_t *__sem, int __pshared, unsigned int __value) + __THROW; +/* Free resources associated with semaphore object SEM. */ +extern int sem_destroy (sem_t *__sem) __THROW; + +/* Open a named semaphore NAME with open flags OFLAG. */ +extern sem_t *sem_open (__const char *__name, int __oflag, ...) __THROW; + +/* Close descriptor for named semaphore SEM. */ +extern int sem_close (sem_t *__sem) __THROW; + +/* Remove named semaphore NAME. */ +extern int sem_unlink (__const char *__name) __THROW; + +/* Wait for SEM being posted. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int sem_wait (sem_t *__sem); + +#ifdef __USE_XOPEN2K +/* Similar to `sem_wait' but wait only until ABSTIME. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int sem_timedwait (sem_t *__restrict __sem, + __const struct timespec *__restrict __abstime); +#endif + +/* Test whether SEM is posted. */ +extern int sem_trywait (sem_t *__sem) __THROW; + +/* Post SEM. */ +extern int sem_post (sem_t *__sem) __THROW; + +/* Get current value of SEM and store it in *SVAL. */ +extern int sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval) + __THROW; + + +__END_DECLS + +#endif /* semaphore.h */ diff --git a/libpthread/nptl/semaphoreP.h b/libpthread/nptl/semaphoreP.h new file mode 100644 index 000000000..7d6fd2525 --- /dev/null +++ b/libpthread/nptl/semaphoreP.h @@ -0,0 +1,69 @@ +/* Copyright (C) 2002, 2003, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <semaphore.h> +#include "pthreadP.h" + + +/* Mount point of the shared memory filesystem. */ +struct mountpoint_info +{ + char *dir; + size_t dirlen; +}; + +/* Keeping track of currently used mappings. */ +struct inuse_sem +{ + dev_t dev; + ino_t ino; + int refcnt; + sem_t *sem; + char name[0]; +}; + + +/* Variables used in multiple interfaces. */ +extern struct mountpoint_info mountpoint attribute_hidden; + +extern pthread_once_t __namedsem_once attribute_hidden; + +/* The search tree for existing mappings. */ +extern void *__sem_mappings attribute_hidden; + +/* Lock to protect the search tree. */ +extern int __sem_mappings_lock attribute_hidden; + + +/* Initializer for mountpoint. */ +extern void __where_is_shmfs (void) attribute_hidden; + +/* Comparison function for search in tree with existing mappings. */ +extern int __sem_search (const void *a, const void *b) attribute_hidden; + + +/* Prototypes of functions with multiple interfaces. */ +extern int __new_sem_init (sem_t *sem, int pshared, unsigned int value); +extern int __old_sem_init (sem_t *sem, int pshared, unsigned int value); +extern int __new_sem_destroy (sem_t *sem); +extern int __new_sem_post (sem_t *sem); +extern int __new_sem_wait (sem_t *sem); +extern int __old_sem_wait (sem_t *sem); +extern int __new_sem_trywait (sem_t *sem); +extern int __new_sem_getvalue (sem_t *sem, int *sval); diff --git a/libpthread/nptl/sysdeps/alpha/Makefile b/libpthread/nptl/sysdeps/alpha/Makefile new file mode 100644 index 000000000..88c106bbb --- /dev/null +++ b/libpthread/nptl/sysdeps/alpha/Makefile @@ -0,0 +1,21 @@ +# Copyright (C) 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; if not, write to the Free +# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +# 02111-1307 USA. + +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif diff --git a/libpthread/nptl/sysdeps/alpha/dl-tls.h b/libpthread/nptl/sysdeps/alpha/dl-tls.h new file mode 100644 index 000000000..f81f95d75 --- /dev/null +++ b/libpthread/nptl/sysdeps/alpha/dl-tls.h @@ -0,0 +1,29 @@ +/* Thread-local storage handling in the ELF dynamic linker. Alpha version. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + + +extern void *__tls_get_addr (tls_index *ti); diff --git a/libpthread/nptl/sysdeps/alpha/elf/pt-initfini.c b/libpthread/nptl/sysdeps/alpha/elf/pt-initfini.c new file mode 100644 index 000000000..ba2e419d6 --- /dev/null +++ b/libpthread/nptl/sysdeps/alpha/elf/pt-initfini.c @@ -0,0 +1,89 @@ +/* Special .init and .fini section support for Alpha. NPTL version. + Copyright (C) 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the .init and .fini + sections and defines global symbols for those addresses, so they can be + called as functions. + + * crtn.s puts the corresponding function epilogues in the .init and .fini + sections. + + This differs from what would be generated by the generic code in that + we save and restore the GP within the function. In order for linker + relaxation to work, the value in the GP register on exit from a function + must be valid for the function entry point. Normally, a function is + contained within one object file and this is not an issue, provided + that the function reloads the gp after making any function calls. + However, _init and _fini are constructed from pieces of many object + files, all of which may have different GP values. So we must reload + the GP value from crti.o in crtn.o. */ + +__asm__ (" \n\ +#include \"defs.h\" \n\ + \n\ +/*@HEADER_ENDS*/ \n\ + \n\ +/*@_init_PROLOG_BEGINS*/ \n\ + .section .init, \"ax\", @progbits \n\ + .globl _init \n\ + .type _init,@function \n\ + .usepv _init,std \n\ +_init: \n\ + ldgp $29, 0($27) \n\ + subq $30, 16, $30 \n\ + stq $26, 0($30) \n\ + stq $29, 8($30) \n\ + bsr $26, __pthread_initialize_minimal_internal !samegp \n\ + .align 3 \n\ +/*@_init_PROLOG_ENDS*/ \n\ + \n\ +/*@_init_EPILOG_BEGINS*/ \n\ + .section .init, \"ax\", @progbits \n\ + ldq $26, 0($30) \n\ + ldq $29, 8($30) \n\ + addq $30, 16, $30 \n\ + ret \n\ +/*@_init_EPILOG_ENDS*/ \n\ + \n\ +/*@_fini_PROLOG_BEGINS*/ \n\ + .section .fini, \"ax\", @progbits \n\ + .globl _fini \n\ + .type _fini,@function \n\ + .usepv _fini,std \n\ +_fini: \n\ + ldgp $29, 0($27) \n\ + subq $30, 16, $30 \n\ + stq $26, 0($30) \n\ + stq $29, 8($30) \n\ + .align 3 \n\ +/*@_fini_PROLOG_ENDS*/ \n\ + \n\ +/*@_fini_EPILOG_BEGINS*/ \n\ + .section .fini, \"ax\", @progbits \n\ + ldq $26, 0($30) \n\ + ldq $29, 8($30) \n\ + addq $30, 16, $30 \n\ + ret \n\ +/*@_fini_EPILOG_ENDS*/ \n\ + \n\ +/*@TRAILER_BEGINS*/ \n\ +"); diff --git a/libpthread/nptl/sysdeps/alpha/jmpbuf-unwind.h b/libpthread/nptl/sysdeps/alpha/jmpbuf-unwind.h new file mode 100644 index 000000000..5cef8b1cf --- /dev/null +++ b/libpthread/nptl/sysdeps/alpha/jmpbuf-unwind.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 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 <setjmp.h> +#include <stdint.h> +#include <unwind.h> + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ + _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ + ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_SP] - (_adj)) + +/* We use the normal lobngjmp for unwinding. */ +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/libpthread/nptl/sysdeps/alpha/libc-tls.c b/libpthread/nptl/sysdeps/alpha/libc-tls.c new file mode 100644 index 000000000..a3b68e928 --- /dev/null +++ b/libpthread/nptl/sysdeps/alpha/libc-tls.c @@ -0,0 +1,37 @@ +/* Thread-local storage handling in the ELF dynamic linker. Alpha version. + Copyright (C) 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdeps/generic/libc-tls.c> +#include <dl-tls.h> + +#if USE_TLS + +/* On Alpha, linker optimizations are not required, so __tls_get_addr + can be called even in statically linked binaries. In this case module + must be always 1 and PT_TLS segment exist in the binary, otherwise it + would not link. */ + +void * +__tls_get_addr (tls_index *ti) +{ + dtv_t *dtv = THREAD_DTV (); + return (char *) dtv[1].pointer.val + ti->ti_offset; +} + +#endif diff --git a/libpthread/nptl/sysdeps/alpha/pthread_spin_lock.S b/libpthread/nptl/sysdeps/alpha/pthread_spin_lock.S new file mode 100644 index 000000000..ce6cd41a4 --- /dev/null +++ b/libpthread/nptl/sysdeps/alpha/pthread_spin_lock.S @@ -0,0 +1,45 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson <rth@twiddle.net>, 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. */ + + + .text + .align 4 + + .globl pthread_spin_lock + .ent pthread_spin_lock +pthread_spin_lock: + .frame $sp, 0, $26, 0 + .prologue 0 + +0: ldl_l $1, 0($16) + lda $2, 1 + lda $0, 0 + bne $1, 1f + + stl_c $2, 0($16) + beq $2, 1f + mb + ret + +1: ldl $1, 0($16) + bne $1, 1b + unop + br 0b + + .end pthread_spin_lock diff --git a/libpthread/nptl/sysdeps/alpha/pthread_spin_trylock.S b/libpthread/nptl/sysdeps/alpha/pthread_spin_trylock.S new file mode 100644 index 000000000..0948da698 --- /dev/null +++ b/libpthread/nptl/sysdeps/alpha/pthread_spin_trylock.S @@ -0,0 +1,46 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson <rth@twiddle.net>, 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. */ + + +#define _ERRNO_H 1 +#include <bits/errno.h> + + .text + .align 4 + + .globl pthread_spin_trylock + .ent pthread_spin_trylock +pthread_spin_trylock: + .frame $sp, 0, $26, 0 + .prologue 0 + +0: ldl_l $1, 0($16) + lda $2, 1 + lda $0, EBUSY + bne $1, 1f + + stl_c $2, 0($16) + beq $2, 2f + mb + lda $0, 0 + +1: ret +2: br 0b + + .end pthread_spin_trylock diff --git a/libpthread/nptl/sysdeps/alpha/pthreaddef.h b/libpthread/nptl/sysdeps/alpha/pthreaddef.h new file mode 100644 index 000000000..26c4daf7b --- /dev/null +++ b/libpthread/nptl/sysdeps/alpha/pthreaddef.h @@ -0,0 +1,38 @@ +/* Copyright (C) 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (4 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. The ABI requires 16. */ +#define STACK_ALIGN 16 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 4096 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 16 + +/* Location of current stack frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + +/* XXX Until we have a better place keep the definitions here. */ + +/* While there is no such syscall. */ +#define __exit_thread_inline(val) \ + INLINE_SYSCALL (exit, 1, (val)) diff --git a/libpthread/nptl/sysdeps/alpha/tcb-offsets.sym b/libpthread/nptl/sysdeps/alpha/tcb-offsets.sym new file mode 100644 index 000000000..c21a79104 --- /dev/null +++ b/libpthread/nptl/sysdeps/alpha/tcb-offsets.sym @@ -0,0 +1,14 @@ +#include <sysdep.h> +#include <tls.h> + +-- + +-- Abuse tls.h macros to derive offsets relative to the thread register. +-- # define __builtin_thread_pointer() ((void *) 0) +-- # define thread_offsetof(mem) ((void *) &THREAD_SELF->mem - (void *) 0) +-- Ho hum, this doesn't work in gcc4, so Know Things about THREAD_SELF +#define thread_offsetof(mem) (long)(offsetof(struct pthread, mem) - sizeof(struct pthread)) + +MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads) +PID_OFFSET thread_offsetof (pid) +TID_OFFSET thread_offsetof (tid) diff --git a/libpthread/nptl/sysdeps/alpha/tls.h b/libpthread/nptl/sysdeps/alpha/tls.h new file mode 100644 index 000000000..99cd27a03 --- /dev/null +++ b/libpthread/nptl/sysdeps/alpha/tls.h @@ -0,0 +1,127 @@ +/* Definition for thread-local data handling. NPTL/Alpha version. + Copyright (C) 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H 1 + +#ifndef __ASSEMBLER__ +# include <stdbool.h> +# include <stddef.h> +# include <stdint.h> + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif /* __ASSEMBLER__ */ + + +/* We require TLS support in the tools. */ +#ifndef HAVE_TLS_SUPPORT +# error "TLS support is required." +#endif + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +#ifndef __ASSEMBLER__ + +/* Get system call information. */ +# include <sysdep.h> + +/* The TP points to the start of the thread blocks. */ +# define TLS_DTV_AT_TP 1 + +/* Get the thread descriptor definition. */ +# include <nptl/descr.h> + +typedef struct +{ + dtv_t *dtv; + void *private; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN 16 + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN 16 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + (((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1) + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + (THREAD_DTV() = (dtv)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) \ + (((tcbhead_t *) (tcbp))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + (__builtin_set_thread_pointer ((void *)(tcbp)), NULL) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) __builtin_thread_pointer ())->dtv) + +/* Return the thread descriptor for the current thread. */ +# define THREAD_SELF \ + ((struct pthread *)__builtin_thread_pointer () - 1) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF \ + REGISTER (64, 64, 32 * 8, -sizeof (struct pthread)) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + descr->member +#define THREAD_GETMEM_NC(descr, member, idx) \ + descr->member[idx] +#define THREAD_SETMEM(descr, member, value) \ + descr->member = (value) +#define THREAD_SETMEM_NC(descr, member, idx, value) \ + descr->member[idx] = (value) + +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/libpthread/nptl/sysdeps/arm/Makefile.arch b/libpthread/nptl/sysdeps/arm/Makefile.arch new file mode 100644 index 000000000..8b4ce70e4 --- /dev/null +++ b/libpthread/nptl/sysdeps/arm/Makefile.arch @@ -0,0 +1,71 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill <sjhill@uclibc.org> +# Portions Copyright (C) 2006 CodeSourcery +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_SSRC = pthread_spin_lock.S pthread_spin_trylock.S aeabi_read_tp.S \ + thumb_atomics.S +libpthread_CSRC = aeabi_unwind_cpp_pr1.c + +librt_SSRC = aeabi_read_tp.S thumb_atomics.S +librt_CSRC = aeabi_unwind_cpp_pr1.c + +libc_a_CSRC = + +CFLAGS-pt-raise.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + +ASFLAGS-pthread_spin_lock.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +ASFLAGS-pthread_spin_trylock.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +ASFLAGS-aeabi_read_tp.S = -DNOT_IN_libc=1 + +CFLAGS-arm = $(SSP_ALL_CFLAGS) + +PTHREAD_ARCH_DIR := $(top_srcdir)libpthread/nptl/sysdeps/arm +PTHREAD_ARCH_OUT := $(top_builddir)libpthread/nptl/sysdeps/arm +PTHREAD_ARCH_OBJ := $(patsubst %.S,$(PTHREAD_ARCH_OUT)/%.o,$(libpthread_SSRC)) +PTHREAD_ARCH_OBJ += $(patsubst %.c,$(PTHREAD_ARCH_OUT)/%.o,$(libpthread_CSRC)) +LIBRT_ARCH_OBJ := $(patsubst %.S,$(PTHREAD_ARCH_OUT)/%.o,$(librt_SSRC)) +LIBRT_ARCH_OBJ += $(patsubst %.c,$(PTHREAD_ARCH_OUT)/%.o,$(librt_CSRC)) + + +ifeq ($(DOPIC),y) +libpthread-a-y += $(PTHREAD_ARCH_OBJ:.o=.os) +else +libpthread-a-y += $(PTHREAD_ARCH_OBJ) +endif +libpthread-so-y += $(PTHREAD_ARCH_OBJ:.o=.oS) + +librt-a-y += $(LIBRT_ARCH_OBJ) +librt-so-y += $(LIBRT_ARCH_OBJ:.o=.oS) + +libpthread-nomulti-y += $(PTHREAD_ARCH_OBJ) + +objclean-y += nptl_arch_objclean +headers_clean-y += nptl_arch_headers_clean + +# +# Create 'tcb-offsets.h' header file. +# +CFLAGS-tcb-offsets.c = -S + +$(PTHREAD_ARCH_OUT)/tcb-offsets.c: $(PTHREAD_ARCH_DIR)/tcb-offsets.sym + $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ + +$(PTHREAD_ARCH_OUT)/tcb-offsets.s: $(PTHREAD_ARCH_OUT)/tcb-offsets.c + $(compile.c) + +$(PTHREAD_ARCH_OUT)/tcb-offsets.h: $(PTHREAD_ARCH_OUT)/tcb-offsets.s + $(do_sed) -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $@ + +pregen-headers-$(UCLIBC_HAS_THREADS_NATIVE) += $(PTHREAD_ARCH_OUT)/tcb-offsets.h + +nptl_arch_headers_clean: + $(RM) $(PTHREAD_ARCH_OUT)/tcb-offsets.c \ + $(PTHREAD_ARCH_OUT)/tcb-offsets.s \ + $(PTHREAD_ARCH_OUT)/tcb-offsets.h + +nptl_arch_objclean: + $(RM) $(PTHREAD_ARCH_OUT)/*.{o,os,oS} diff --git a/libpthread/nptl/sysdeps/arm/aeabi_read_tp.S b/libpthread/nptl/sysdeps/arm/aeabi_read_tp.S new file mode 100644 index 000000000..af640d625 --- /dev/null +++ b/libpthread/nptl/sysdeps/arm/aeabi_read_tp.S @@ -0,0 +1 @@ +#include <../../../../ldso/ldso/arm/aeabi_read_tp.S> diff --git a/libpthread/nptl/sysdeps/arm/aeabi_unwind_cpp_pr1.c b/libpthread/nptl/sysdeps/arm/aeabi_unwind_cpp_pr1.c new file mode 100644 index 000000000..84683627b --- /dev/null +++ b/libpthread/nptl/sysdeps/arm/aeabi_unwind_cpp_pr1.c @@ -0,0 +1 @@ +#include <../../../../libc/sysdeps/linux/arm/aeabi_unwind_cpp_pr1.c> diff --git a/libpthread/nptl/sysdeps/arm/dl-tls.h b/libpthread/nptl/sysdeps/arm/dl-tls.h new file mode 100644 index 000000000..e0324a7b6 --- /dev/null +++ b/libpthread/nptl/sysdeps/arm/dl-tls.h @@ -0,0 +1,29 @@ +/* Thread-local storage handling in the ELF dynamic linker. ARM version. + Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + + +extern void *__tls_get_addr (tls_index *ti); diff --git a/libpthread/nptl/sysdeps/arm/jmpbuf-unwind.h b/libpthread/nptl/sysdeps/arm/jmpbuf-unwind.h new file mode 100644 index 000000000..6e8f01d10 --- /dev/null +++ b/libpthread/nptl/sysdeps/arm/jmpbuf-unwind.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2005,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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <setjmp.h> +#include <stdint.h> +#include <unwind.h> + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#undef _JMPBUF_UNWINDS +#define _JMPBUF_UNWINDS(jmpbuf, address, demangle) \ + ((void *) (address) < (void *) demangle (jmpbuf[__JMP_BUF_SP])) + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ + _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ + ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[__JMP_BUF_SP] - (_adj)) + +/* We use the normal longjmp for unwinding. */ +#define __libc_unwind_longjmp(buf, val) longjmp (buf, val) diff --git a/libpthread/nptl/sysdeps/arm/pthread_spin_lock.S b/libpthread/nptl/sysdeps/arm/pthread_spin_lock.S new file mode 100644 index 000000000..bd6adf794 --- /dev/null +++ b/libpthread/nptl/sysdeps/arm/pthread_spin_lock.S @@ -0,0 +1,31 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> + + .text + .align 4 + +ENTRY (pthread_spin_lock) + mov r1, #1 +1: swp r2, r1, [r0] + teq r2, #0 + bne 1b + mov r0, #0 + PSEUDO_RET_NOERRNO +END (pthread_spin_lock) diff --git a/libpthread/nptl/sysdeps/arm/pthread_spin_trylock.S b/libpthread/nptl/sysdeps/arm/pthread_spin_trylock.S new file mode 100644 index 000000000..85931507a --- /dev/null +++ b/libpthread/nptl/sysdeps/arm/pthread_spin_trylock.S @@ -0,0 +1,34 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define _ERRNO_H 1 +#include <bits/errno.h> + +#include <sysdep.h> + + .text + .align 4 + +ENTRY (pthread_spin_trylock) + mov r1, #1 + swp r2, r1, [r0] + teq r2, #0 + moveq r0, #0 + movne r0, #EBUSY + PSEUDO_RET_NOERRNO +END (pthread_spin_trylock) diff --git a/libpthread/nptl/sysdeps/arm/pthreaddef.h b/libpthread/nptl/sysdeps/arm/pthreaddef.h new file mode 100644 index 000000000..783828a40 --- /dev/null +++ b/libpthread/nptl/sysdeps/arm/pthreaddef.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. SSE requires 16 + bytes. */ +#define STACK_ALIGN 16 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 2048 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 16 + + +/* Location of current stack frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + + +/* XXX Until we have a better place keep the definitions here. */ +#define __exit_thread_inline(val) \ + INLINE_SYSCALL (exit, 1, (val)) diff --git a/libpthread/nptl/sysdeps/arm/tcb-offsets.sym b/libpthread/nptl/sysdeps/arm/tcb-offsets.sym new file mode 100644 index 000000000..92cc441d3 --- /dev/null +++ b/libpthread/nptl/sysdeps/arm/tcb-offsets.sym @@ -0,0 +1,11 @@ +#include <sysdep.h> +#include <tls.h> + +-- + +-- Derive offsets relative to the thread register. +#define thread_offsetof(mem) (long)(offsetof(struct pthread, mem) - sizeof(struct pthread)) + +MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads) +PID_OFFSET thread_offsetof (pid) +TID_OFFSET thread_offsetof (tid) diff --git a/libpthread/nptl/sysdeps/arm/thumb_atomics.S b/libpthread/nptl/sysdeps/arm/thumb_atomics.S new file mode 100644 index 000000000..aaa7a3d8f --- /dev/null +++ b/libpthread/nptl/sysdeps/arm/thumb_atomics.S @@ -0,0 +1 @@ +#include <../../../../ldso/ldso/arm/thumb_atomics.S> diff --git a/libpthread/nptl/sysdeps/arm/tls.h b/libpthread/nptl/sysdeps/arm/tls.h new file mode 100644 index 000000000..0ca597ac8 --- /dev/null +++ b/libpthread/nptl/sysdeps/arm/tls.h @@ -0,0 +1,159 @@ +/* Definition for thread-local data handling. NPTL/ARM version. + Copyright (C) 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 + 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. */ + +#ifndef _TLS_H +#define _TLS_H 1 + +#ifndef __ASSEMBLER__ + +# include <stdbool.h> +# include <stddef.h> +# include <stdint.h> + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif /* __ASSEMBLER__ */ + + +/* We require TLS support in the tools. */ +#define HAVE_TLS_SUPPORT 1 +#define HAVE_TLS_MODEL_ATTRIBUTE 1 +#define HAVE___THREAD 1 + +/* Signal that TLS support is available. */ +#define USE_TLS 1 + +#ifndef __ASSEMBLER__ + +/* Get system call information. */ +# include <sysdep.h> + +/* The TP points to the start of the thread blocks. */ +# define TLS_DTV_AT_TP 1 + +/* Get the thread descriptor definition. */ +# include <../../descr.h> + +typedef struct +{ + dtv_t *dtv; + void *private; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN 16 + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN 16 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + (((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1) + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + (THREAD_DTV() = (dtv)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) \ + (((tcbhead_t *) (tcbp))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + ({ INTERNAL_SYSCALL_DECL (err); \ + long result_var; \ + result_var = INTERNAL_SYSCALL_ARM (set_tls, err, 1, (tcbp)); \ + INTERNAL_SYSCALL_ERROR_P (result_var, err) \ + ? "unknown error" : NULL; }) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) __builtin_thread_pointer ())->dtv) + +/* Return the thread descriptor for the current thread. */ +# define THREAD_SELF \ + ((struct pthread *)__builtin_thread_pointer () - 1) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF \ + CONST_THREAD_AREA (32, sizeof (struct pthread)) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + descr->member +#define THREAD_GETMEM_NC(descr, member, idx) \ + descr->member[idx] +#define THREAD_SETMEM(descr, member, value) \ + descr->member = (value) +#define THREAD_SETMEM_NC(descr, member, idx, value) \ + descr->member[idx] = (value) + +/* Initializing the thread pointer will generate a SIGILL if the syscall + is not available. */ +#define TLS_INIT_TP_EXPENSIVE 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, LLL_PRIVATE); \ + } \ + 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/libpthread/nptl/sysdeps/generic/Makefile b/libpthread/nptl/sysdeps/generic/Makefile new file mode 100644 index 000000000..582661fde --- /dev/null +++ b/libpthread/nptl/sysdeps/generic/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libpthread/nptl/sysdeps/generic/Makefile.in b/libpthread/nptl/sysdeps/generic/Makefile.in new file mode 100644 index 000000000..1079a5fd9 --- /dev/null +++ b/libpthread/nptl/sysdeps/generic/Makefile.in @@ -0,0 +1,30 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +# +# NOTE: Alpha and MIPS have their own versions of 'libc-tls.c' in +# their architecture specific directory which will override +# the one here. +# +libc_a_CSRC = dl-tls.c libc-tls.c + + +CFLAGS-generic = $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +PTHREAD_GENERIC_OUT:=$(top_builddir)libpthread/nptl/sysdeps/generic + +LIBC_GENERIC_OBJ:=$(patsubst %.c,$(PTHREAD_GENERIC_OUT)/%.o,$(libc_a_CSRC)) + +libc-static-y+=$(LIBC_GENERIC_OBJ) + +libc-nomulti-y+=$(LIBC_GENERIC_OBJ) + +objclean-y+=nptl_pthread_generic_clean + +nptl_pthread_generic_clean: + $(do_rm) $(addprefix $(PTHREAD_GENERIC_OUT)/*., o os oS) diff --git a/libpthread/nptl/sysdeps/generic/dl-tls.c b/libpthread/nptl/sysdeps/generic/dl-tls.c new file mode 100644 index 000000000..da6ebbddb --- /dev/null +++ b/libpthread/nptl/sysdeps/generic/dl-tls.c @@ -0,0 +1,895 @@ +/* Thread-local storage handling in the ELF dynamic linker. Generic version. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <libintl.h> +#include <signal.h> +#include <stdlib.h> +#include <sys/param.h> +#include <tls.h> +#include <dl-tls.h> +#include <ldsodefs.h> +#include <dl-elf.h> +#include <dl-hash.h> + +#include <assert.h> +#include <link.h> +#include <string.h> +#include <unistd.h> +#include <stdio.h> + +#define _dl_malloc malloc +#define _dl_memset memset +#define _dl_mempcpy mempcpy +#define _dl_dprintf fprintf +#define _dl_debug_file stderr +#define _dl_exit exit + +/* Amount of excess space to allocate in the static TLS area + to allow dynamic loading of modules defining IE-model TLS data. */ +# define TLS_STATIC_SURPLUS 64 + DL_NNS * 100 + +/* Value used for dtv entries for which the allocation is delayed. */ +# define TLS_DTV_UNALLOCATED ((void *) -1l) + + +/* Out-of-memory handler. */ +# ifdef SHARED +static void +__attribute__ ((__noreturn__)) +oom (void) +{ + do { + _dl_dprintf (_dl_debug_file, + "cannot allocate thread-local memory: ABORT\n"); + _dl_exit (127); + } while (1); +} +# endif + + +void *_dl_memalign(size_t alignment, size_t bytes) +{ + return _dl_malloc(bytes); +} + + +/* + * We are trying to perform a static TLS relocation in MAP, but it was + * dynamically loaded. This can only work if there is enough surplus in + * the static TLS area already allocated for each running thread. If this + * object's TLS segment is too big to fit, we fail. If it fits, + * we set MAP->l_tls_offset and return. + * This function intentionally does not return any value but signals error + * directly, as static TLS should be rare and code handling it should + * not be inlined as much as possible. + */ + + +void +internal_function __attribute_noinline__ +_dl_allocate_static_tls (struct link_map *map) +{ + /* If the alignment requirements are too high fail. */ + if (map->l_tls_align > _dl_tls_static_align) + { +fail: + _dl_dprintf(_dl_debug_file, "cannot allocate memory in static TLS block"); + _dl_exit(30); + } + +# if defined(TLS_TCB_AT_TP) + size_t freebytes; + size_t n; + size_t blsize; + + freebytes = _dl_tls_static_size - _dl_tls_static_used - TLS_TCB_SIZE; + + blsize = map->l_tls_blocksize + map->l_tls_firstbyte_offset; + if (freebytes < blsize) + goto fail; + + n = (freebytes - blsize) / map->l_tls_align; + + size_t offset = _dl_tls_static_used + (freebytes - n * map->l_tls_align + - map->l_tls_firstbyte_offset); + + map->l_tls_offset = _dl_tls_static_used = offset; +# elif defined(TLS_DTV_AT_TP) + size_t used; + size_t check; + + size_t offset = roundup (_dl_tls_static_used, map->l_tls_align); + used = offset + map->l_tls_blocksize; + check = used; + + /* dl_tls_static_used includes the TCB at the beginning. */ + if (check > _dl_tls_static_size) + goto fail; + + map->l_tls_offset = offset; + _dl_tls_static_used = used; +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* + * If the object is not yet relocated we cannot initialize the + * static TLS region. Delay it. + */ + if (((struct elf_resolve *) map)->init_flag & RELOCS_DONE) + { +#ifdef SHARED + /* + * Update the slot information data for at least the generation of + * the DSO we are allocating data for. + */ + if (__builtin_expect (THREAD_DTV()[0].counter != _dl_tls_generation, 0)) + (void) _dl_update_slotinfo (map->l_tls_modid); +#endif + _dl_init_static_tls (map); + } + else + map->l_need_tls_init = 1; +} + +size_t +internal_function +_dl_next_tls_modid (void) +{ + size_t result; + + if (__builtin_expect (GL(dl_tls_dtv_gaps), false)) + { + size_t disp = 0; + struct dtv_slotinfo_list *runp = GL(dl_tls_dtv_slotinfo_list); + + /* Note that this branch will never be executed during program + start since there are no gaps at that time. Therefore it + does not matter that the dl_tls_dtv_slotinfo is not allocated + yet when the function is called for the first times. + + NB: the offset +1 is due to the fact that DTV[0] is used + for something else. */ + result = GL(dl_tls_static_nelem) + 1; + if (result <= GL(dl_tls_max_dtv_idx)) + do + { + while (result - disp < runp->len) + { + if (runp->slotinfo[result - disp].map == NULL) + break; + + ++result; + assert (result <= GL(dl_tls_max_dtv_idx) + 1); + } + + if (result - disp < runp->len) + break; + + disp += runp->len; + } + while ((runp = runp->next) != NULL); + + if (result > GL(dl_tls_max_dtv_idx)) + { + /* The new index must indeed be exactly one higher than the + previous high. */ + assert (result == GL(dl_tls_max_dtv_idx) + 1); + /* There is no gap anymore. */ + GL(dl_tls_dtv_gaps) = false; + + goto nogaps; + } + } + else + { + /* No gaps, allocate a new entry. */ + nogaps: + + result = ++GL(dl_tls_max_dtv_idx); + } + + return result; +} + + +# ifdef SHARED +void +internal_function +_dl_determine_tlsoffset (void) +{ + size_t max_align = TLS_TCB_ALIGN; + size_t freetop = 0; + size_t freebottom = 0; + + /* The first element of the dtv slot info list is allocated. */ + assert (GL(dl_tls_dtv_slotinfo_list) != NULL); + /* There is at this point only one element in the + dl_tls_dtv_slotinfo_list list. */ + assert (GL(dl_tls_dtv_slotinfo_list)->next == NULL); + + struct dtv_slotinfo *slotinfo = GL(dl_tls_dtv_slotinfo_list)->slotinfo; + + /* Determining the offset of the various parts of the static TLS + block has several dependencies. In addition we have to work + around bugs in some toolchains. + + Each TLS block from the objects available at link time has a size + and an alignment requirement. The GNU ld computes the alignment + requirements for the data at the positions *in the file*, though. + I.e, it is not simply possible to allocate a block with the size + of the TLS program header entry. The data is layed out assuming + that the first byte of the TLS block fulfills + + p_vaddr mod p_align == &TLS_BLOCK mod p_align + + This means we have to add artificial padding at the beginning of + the TLS block. These bytes are never used for the TLS data in + this module but the first byte allocated must be aligned + according to mod p_align == 0 so that the first byte of the TLS + block is aligned according to p_vaddr mod p_align. This is ugly + and the linker can help by computing the offsets in the TLS block + assuming the first byte of the TLS block is aligned according to + p_align. + + The extra space which might be allocated before the first byte of + the TLS block need not go unused. The code below tries to use + that memory for the next TLS block. This can work if the total + memory requirement for the next TLS block is smaller than the + gap. */ + +# if defined(TLS_TCB_AT_TP) + /* We simply start with zero. */ + size_t offset = 0; + + for (size_t cnt = 0; slotinfo[cnt].map != NULL; ++cnt) + { + assert (cnt < GL(dl_tls_dtv_slotinfo_list)->len); + + size_t firstbyte = (-slotinfo[cnt].map->l_tls_firstbyte_offset + & (slotinfo[cnt].map->l_tls_align - 1)); + size_t off; + max_align = MAX (max_align, slotinfo[cnt].map->l_tls_align); + + if (freebottom - freetop >= slotinfo[cnt].map->l_tls_blocksize) + { + off = roundup (freetop + slotinfo[cnt].map->l_tls_blocksize + - firstbyte, slotinfo[cnt].map->l_tls_align) + + firstbyte; + if (off <= freebottom) + { + freetop = off; + + /* XXX For some architectures we perhaps should store the + negative offset. */ + slotinfo[cnt].map->l_tls_offset = off; + continue; + } + } + + off = roundup (offset + slotinfo[cnt].map->l_tls_blocksize - firstbyte, + slotinfo[cnt].map->l_tls_align) + firstbyte; + if (off > offset + slotinfo[cnt].map->l_tls_blocksize + + (freebottom - freetop)) + { + freetop = offset; + freebottom = off - slotinfo[cnt].map->l_tls_blocksize; + } + offset = off; + + /* XXX For some architectures we perhaps should store the + negative offset. */ + slotinfo[cnt].map->l_tls_offset = off; + } + + GL(dl_tls_static_used) = offset; + GL(dl_tls_static_size) = (roundup (offset + TLS_STATIC_SURPLUS, max_align) + + TLS_TCB_SIZE); +# elif defined(TLS_DTV_AT_TP) + /* The TLS blocks start right after the TCB. */ + size_t offset = TLS_TCB_SIZE; + size_t cnt; + + for (cnt = 0; slotinfo[cnt].map != NULL; ++cnt) + { + assert (cnt < GL(dl_tls_dtv_slotinfo_list)->len); + + size_t firstbyte = (-slotinfo[cnt].map->l_tls_firstbyte_offset + & (slotinfo[cnt].map->l_tls_align - 1)); + size_t off; + max_align = MAX (max_align, slotinfo[cnt].map->l_tls_align); + + if (slotinfo[cnt].map->l_tls_blocksize <= freetop - freebottom) + { + off = roundup (freebottom, slotinfo[cnt].map->l_tls_align); + if (off - freebottom < firstbyte) + off += slotinfo[cnt].map->l_tls_align; + if (off + slotinfo[cnt].map->l_tls_blocksize - firstbyte <= freetop) + { + slotinfo[cnt].map->l_tls_offset = off - firstbyte; + freebottom = (off + slotinfo[cnt].map->l_tls_blocksize + - firstbyte); + continue; + } + } + + off = roundup (offset, slotinfo[cnt].map->l_tls_align); + if (off - offset < firstbyte) + off += slotinfo[cnt].map->l_tls_align; + + slotinfo[cnt].map->l_tls_offset = off - firstbyte; + if (off - firstbyte - offset > freetop - freebottom) + { + freebottom = offset; + freetop = off - firstbyte; + } + + offset = off + slotinfo[cnt].map->l_tls_blocksize - firstbyte; + } + + GL(dl_tls_static_used) = offset; + GL(dl_tls_static_size) = roundup (offset + TLS_STATIC_SURPLUS, + TLS_TCB_ALIGN); +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* The alignment requirement for the static TLS block. */ + GL(dl_tls_static_align) = max_align; +} + + +/* This is called only when the data structure setup was skipped at startup, + when there was no need for it then. Now we have dynamically loaded + something needing TLS, or libpthread needs it. */ +int +internal_function +_dl_tls_setup (void) +{ + assert (GL(dl_tls_dtv_slotinfo_list) == NULL); + assert (GL(dl_tls_max_dtv_idx) == 0); + + const size_t nelem = 2 + TLS_SLOTINFO_SURPLUS; + + GL(dl_tls_dtv_slotinfo_list) + = calloc (1, (sizeof (struct dtv_slotinfo_list) + + nelem * sizeof (struct dtv_slotinfo))); + if (GL(dl_tls_dtv_slotinfo_list) == NULL) + return -1; + + GL(dl_tls_dtv_slotinfo_list)->len = nelem; + + /* Number of elements in the static TLS block. It can't be zero + because of various assumptions. The one element is null. */ + GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx) = 1; + + /* This initializes more variables for us. */ + _dl_determine_tlsoffset (); + + return 0; +} +# endif + +static void * +internal_function +allocate_dtv (void *result) +{ + dtv_t *dtv; + size_t dtv_length; + + /* We allocate a few more elements in the dtv than are needed for the + initial set of modules. This should avoid in most cases expansions + of the dtv. */ + dtv_length = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS; + dtv = calloc (dtv_length + 2, sizeof (dtv_t)); + if (dtv != NULL) + { + /* This is the initial length of the dtv. */ + dtv[0].counter = dtv_length; + + /* The rest of the dtv (including the generation counter) is + Initialize with zero to indicate nothing there. */ + + /* Add the dtv to the thread data structures. */ + INSTALL_DTV (result, dtv); + } + else + result = NULL; + + return result; +} + + +/* Get size and alignment requirements of the static TLS block. */ +void +internal_function +_dl_get_tls_static_info (size_t *sizep, size_t *alignp) +{ + *sizep = GL(dl_tls_static_size); + *alignp = GL(dl_tls_static_align); +} + + +void * +internal_function +_dl_allocate_tls_storage (void) +{ + void *result; + size_t size = GL(dl_tls_static_size); + +# if defined(TLS_DTV_AT_TP) + /* Memory layout is: + [ TLS_PRE_TCB_SIZE ] [ TLS_TCB_SIZE ] [ TLS blocks ] + ^ This should be returned. */ + size += (TLS_PRE_TCB_SIZE + GL(dl_tls_static_align) - 1) + & ~(GL(dl_tls_static_align) - 1); +# endif + + /* Allocate a correctly aligned chunk of memory. */ + result = _dl_memalign (GL(dl_tls_static_align), size); + if (__builtin_expect (result != NULL, 1)) + { + /* Allocate the DTV. */ + void *allocated = result; + +# if defined(TLS_TCB_AT_TP) + /* The TCB follows the TLS blocks. */ + result = (char *) result + size - TLS_TCB_SIZE; + + /* Clear the TCB data structure. We can't ask the caller (i.e. + libpthread) to do it, because we will initialize the DTV et al. */ + _dl_memset (result, '\0', TLS_TCB_SIZE); +# elif defined(TLS_DTV_AT_TP) + result = (char *) result + size - GL(dl_tls_static_size); + + /* Clear the TCB data structure and TLS_PRE_TCB_SIZE bytes before it. + We can't ask the caller (i.e. libpthread) to do it, because we will + initialize the DTV et al. */ + _dl_memset ((char *) result - TLS_PRE_TCB_SIZE, '\0', + TLS_PRE_TCB_SIZE + TLS_TCB_SIZE); +# endif + + result = allocate_dtv (result); + if (result == NULL) + free (allocated); + } + + return result; +} + + +void * +internal_function +_dl_allocate_tls_init (void *result) +{ + if (result == NULL) + /* The memory allocation failed. */ + return NULL; + + dtv_t *dtv = GET_DTV (result); + struct dtv_slotinfo_list *listp; + size_t total = 0; + size_t maxgen = 0; + + /* We have to prepare the dtv for all currently loaded modules using + TLS. For those which are dynamically loaded we add the values + indicating deferred allocation. */ + listp = GL(dl_tls_dtv_slotinfo_list); + while (1) + { + size_t cnt; + + for (cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt) + { + struct link_map *map; + void *dest; + + /* Check for the total number of used slots. */ + if (total + cnt > GL(dl_tls_max_dtv_idx)) + break; + + map = listp->slotinfo[cnt].map; + if (map == NULL) + /* Unused entry. */ + continue; + + /* Keep track of the maximum generation number. This might + not be the generation counter. */ + maxgen = MAX (maxgen, listp->slotinfo[cnt].gen); + + if (map->l_tls_offset == NO_TLS_OFFSET) + { + /* For dynamically loaded modules we simply store + the value indicating deferred allocation. */ + dtv[map->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED; + dtv[map->l_tls_modid].pointer.is_static = false; + continue; + } + + assert (map->l_tls_modid == cnt); + assert (map->l_tls_blocksize >= map->l_tls_initimage_size); +# if defined(TLS_TCB_AT_TP) + assert ((size_t) map->l_tls_offset >= map->l_tls_blocksize); + dest = (char *) result - map->l_tls_offset; +# elif defined(TLS_DTV_AT_TP) + dest = (char *) result + map->l_tls_offset; +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* Copy the initialization image and clear the BSS part. */ + dtv[map->l_tls_modid].pointer.val = dest; + dtv[map->l_tls_modid].pointer.is_static = true; + _dl_memset (_dl_mempcpy (dest, map->l_tls_initimage, + map->l_tls_initimage_size), '\0', + map->l_tls_blocksize - map->l_tls_initimage_size); + } + + total += cnt; + if (total >= GL(dl_tls_max_dtv_idx)) + break; + + listp = listp->next; + assert (listp != NULL); + } + + /* The DTV version is up-to-date now. */ + dtv[0].counter = maxgen; + + return result; +} + +void * +internal_function +_dl_allocate_tls (void *mem) +{ + return _dl_allocate_tls_init (mem == NULL + ? _dl_allocate_tls_storage () + : allocate_dtv (mem)); +} + + +void +internal_function +_dl_deallocate_tls (void *tcb, bool dealloc_tcb) +{ + dtv_t *dtv = GET_DTV (tcb); + size_t cnt; + + /* We need to free the memory allocated for non-static TLS. */ + for (cnt = 0; cnt < dtv[-1].counter; ++cnt) + if (! dtv[1 + cnt].pointer.is_static + && dtv[1 + cnt].pointer.val != TLS_DTV_UNALLOCATED) + free (dtv[1 + cnt].pointer.val); + + /* The array starts with dtv[-1]. */ +#ifdef SHARED + if (dtv != GL(dl_initial_dtv)) +#endif + free (dtv - 1); + + if (dealloc_tcb) + { +# if defined(TLS_TCB_AT_TP) + /* The TCB follows the TLS blocks. Back up to free the whole block. */ + tcb -= GL(dl_tls_static_size) - TLS_TCB_SIZE; +# elif defined(TLS_DTV_AT_TP) + /* Back up the TLS_PRE_TCB_SIZE bytes. */ + tcb -= (TLS_PRE_TCB_SIZE + GL(dl_tls_static_align) - 1) + & ~(GL(dl_tls_static_align) - 1); +# endif + free (tcb); + } +} + + +# ifdef SHARED +/* The __tls_get_addr function has two basic forms which differ in the + arguments. The IA-64 form takes two parameters, the module ID and + offset. The form used, among others, on IA-32 takes a reference to + a special structure which contain the same information. The second + form seems to be more often used (in the moment) so we default to + it. Users of the IA-64 form have to provide adequate definitions + of the following macros. */ +# ifndef GET_ADDR_ARGS +# define GET_ADDR_ARGS tls_index *ti +# endif +# ifndef GET_ADDR_MODULE +# define GET_ADDR_MODULE ti->ti_module +# endif +# ifndef GET_ADDR_OFFSET +# define GET_ADDR_OFFSET ti->ti_offset +# endif + + +static void * +allocate_and_init (struct link_map *map) +{ + void *newp; + + newp = _dl_memalign (map->l_tls_align, map->l_tls_blocksize); + if (newp == NULL) + oom (); + + /* Initialize the memory. */ + _dl_memset (_dl_mempcpy (newp, map->l_tls_initimage, map->l_tls_initimage_size), + '\0', map->l_tls_blocksize - map->l_tls_initimage_size); + + return newp; +} + + +struct link_map * +_dl_update_slotinfo (unsigned long int req_modid) +{ + struct link_map *the_map = NULL; + dtv_t *dtv = THREAD_DTV (); + + /* The global dl_tls_dtv_slotinfo array contains for each module + index the generation counter current when the entry was created. + This array never shrinks so that all module indices which were + valid at some time can be used to access it. Before the first + use of a new module index in this function the array was extended + appropriately. Access also does not have to be guarded against + modifications of the array. It is assumed that pointer-size + values can be read atomically even in SMP environments. It is + possible that other threads at the same time dynamically load + code and therefore add to the slotinfo list. This is a problem + since we must not pick up any information about incomplete work. + The solution to this is to ignore all dtv slots which were + created after the one we are currently interested. We know that + dynamic loading for this module is completed and this is the last + load operation we know finished. */ + unsigned long int idx = req_modid; + struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list); + + while (idx >= listp->len) + { + idx -= listp->len; + listp = listp->next; + } + + if (dtv[0].counter < listp->slotinfo[idx].gen) + { + /* The generation counter for the slot is higher than what the + current dtv implements. We have to update the whole dtv but + only those entries with a generation counter <= the one for + the entry we need. */ + size_t new_gen = listp->slotinfo[idx].gen; + size_t total = 0; + + /* We have to look through the entire dtv slotinfo list. */ + listp = GL(dl_tls_dtv_slotinfo_list); + do + { + size_t cnt; + + for (cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt) + { + size_t gen = listp->slotinfo[cnt].gen; + + if (gen > new_gen) + /* This is a slot for a generation younger than the + one we are handling now. It might be incompletely + set up so ignore it. */ + continue; + + /* If the entry is older than the current dtv layout we + know we don't have to handle it. */ + if (gen <= dtv[0].counter) + continue; + + /* If there is no map this means the entry is empty. */ + struct link_map *map = listp->slotinfo[cnt].map; + if (map == NULL) + { + /* If this modid was used at some point the memory + might still be allocated. */ + if (! dtv[total + cnt].pointer.is_static + && dtv[total + cnt].pointer.val != TLS_DTV_UNALLOCATED) + { + free (dtv[total + cnt].pointer.val); + dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED; + } + + continue; + } + + /* Check whether the current dtv array is large enough. */ + size_t modid = map->l_tls_modid; + assert (total + cnt == modid); + if (dtv[-1].counter < modid) + { + /* Reallocate the dtv. */ + dtv_t *newp; + size_t newsize = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS; + size_t oldsize = dtv[-1].counter; + + assert (map->l_tls_modid <= newsize); + + if (dtv == GL(dl_initial_dtv)) + { + /* This is the initial dtv that was allocated + during rtld startup using the dl-minimal.c + malloc instead of the real malloc. We can't + free it, we have to abandon the old storage. */ + + newp = malloc ((2 + newsize) * sizeof (dtv_t)); + if (newp == NULL) + oom (); + _dl_memcpy (newp, &dtv[-1], oldsize * sizeof (dtv_t)); + } + else + { + newp = realloc (&dtv[-1], + (2 + newsize) * sizeof (dtv_t)); + if (newp == NULL) + oom (); + } + + newp[0].counter = newsize; + + /* Clear the newly allocated part. */ + _dl_memset (newp + 2 + oldsize, '\0', + (newsize - oldsize) * sizeof (dtv_t)); + + /* Point dtv to the generation counter. */ + dtv = &newp[1]; + + /* Install this new dtv in the thread data + structures. */ + INSTALL_NEW_DTV (dtv); + } + + /* If there is currently memory allocate for this + dtv entry free it. */ + /* XXX Ideally we will at some point create a memory + pool. */ + if (! dtv[modid].pointer.is_static + && dtv[modid].pointer.val != TLS_DTV_UNALLOCATED) + /* Note that free is called for NULL is well. We + deallocate even if it is this dtv entry we are + supposed to load. The reason is that we call + memalign and not malloc. */ + free (dtv[modid].pointer.val); + + /* This module is loaded dynamically- We defer memory + allocation. */ + dtv[modid].pointer.is_static = false; + dtv[modid].pointer.val = TLS_DTV_UNALLOCATED; + + if (modid == req_modid) + the_map = map; + } + + total += listp->len; + } + while ((listp = listp->next) != NULL); + + /* This will be the new maximum generation counter. */ + dtv[0].counter = new_gen; + } + + return the_map; +} + + +/* The generic dynamic and local dynamic model cannot be used in + statically linked applications. */ +void * +__tls_get_addr (GET_ADDR_ARGS) +{ + dtv_t *dtv = THREAD_DTV (); + struct link_map *the_map = NULL; + void *p; + + if (__builtin_expect (dtv[0].counter != GL(dl_tls_generation), 0)) + the_map = _dl_update_slotinfo (GET_ADDR_MODULE); + + p = dtv[GET_ADDR_MODULE].pointer.val; + + if (__builtin_expect (p == TLS_DTV_UNALLOCATED, 0)) + { + /* The allocation was deferred. Do it now. */ + if (the_map == NULL) + { + /* Find the link map for this module. */ + size_t idx = GET_ADDR_MODULE; + struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list); + + while (idx >= listp->len) + { + idx -= listp->len; + listp = listp->next; + } + + the_map = listp->slotinfo[idx].map; + } + + p = dtv[GET_ADDR_MODULE].pointer.val = allocate_and_init (the_map); + dtv[GET_ADDR_MODULE].pointer.is_static = false; + } + + return (char *) p + GET_ADDR_OFFSET; +} +# endif + + + +void +_dl_add_to_slotinfo (struct link_map *l) +{ + /* Now that we know the object is loaded successfully add + modules containing TLS data to the dtv info table. We + might have to increase its size. */ + struct dtv_slotinfo_list *listp; + struct dtv_slotinfo_list *prevp; + size_t idx = l->l_tls_modid; + + /* Find the place in the dtv slotinfo list. */ + listp = GL(dl_tls_dtv_slotinfo_list); + prevp = NULL; /* Needed to shut up gcc. */ + do + { + /* Does it fit in the array of this list element? */ + if (idx < listp->len) + break; + idx -= listp->len; + prevp = listp; + listp = listp->next; + } + while (listp != NULL); + + if (listp == NULL) + { + /* When we come here it means we have to add a new element + to the slotinfo list. And the new module must be in + the first slot. */ + assert (idx == 0); + + listp = prevp->next = (struct dtv_slotinfo_list *) + malloc (sizeof (struct dtv_slotinfo_list) + + TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo)); + if (listp == NULL) + { + /* We ran out of memory. We will simply fail this + call but don't undo anything we did so far. The + application will crash or be terminated anyway very + soon. */ + + /* We have to do this since some entries in the dtv + slotinfo array might already point to this + generation. */ + ++GL(dl_tls_generation); + + _dl_dprintf (_dl_debug_file, + "cannot create TLS data structures: ABORT\n"); + _dl_exit (127); + } + + listp->len = TLS_SLOTINFO_SURPLUS; + listp->next = NULL; + _dl_memset (listp->slotinfo, '\0', + TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo)); + } + + /* Add the information into the slotinfo data structure. */ + listp->slotinfo[idx].map = l; + listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1; +} diff --git a/libpthread/nptl/sysdeps/generic/dl-tls.h b/libpthread/nptl/sysdeps/generic/dl-tls.h new file mode 100644 index 000000000..7703a9752 --- /dev/null +++ b/libpthread/nptl/sysdeps/generic/dl-tls.h @@ -0,0 +1,2 @@ +/* There has to be an architecture specific version of this file. */ +#error "architecture-specific version of <dl-tls.h> missing" diff --git a/libpthread/nptl/sysdeps/generic/libc-tls.c b/libpthread/nptl/sysdeps/generic/libc-tls.c new file mode 100644 index 000000000..b78d96483 --- /dev/null +++ b/libpthread/nptl/sysdeps/generic/libc-tls.c @@ -0,0 +1,265 @@ +/* Initialization code for TLS in statically linked application. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <ldsodefs.h> +#include <tls.h> +#include <unistd.h> +#include <stdio.h> +#include <sys/param.h> +#include <elf.h> +#include <link.h> +#include <string.h> +#include <stdlib.h> + + +#ifdef SHARED + #error makefile bug, this file is for static only +#endif + +#if USE_TLS +extern ElfW(Phdr) *_dl_phdr; +extern size_t _dl_phnum; + + +static dtv_t static_dtv[2 + TLS_SLOTINFO_SURPLUS]; + + +static struct +{ + struct dtv_slotinfo_list si; + /* The dtv_slotinfo_list data structure does not include the actual + information since it is defined as an array of size zero. We define + here the necessary entries. Note that it is not important whether + there is padding or not since we will always access the information + through the 'si' element. */ + struct dtv_slotinfo info[2 + TLS_SLOTINFO_SURPLUS]; +} static_slotinfo; + +/* Fake link map for the application. */ +static struct link_map static_map; + + +/* Highest dtv index currently needed. */ +size_t _dl_tls_max_dtv_idx; +/* Flag signalling whether there are gaps in the module ID allocation. */ +bool _dl_tls_dtv_gaps; +/* Information about the dtv slots. */ +struct dtv_slotinfo_list *_dl_tls_dtv_slotinfo_list; +/* Number of modules in the static TLS block. */ +size_t _dl_tls_static_nelem; +/* Size of the static TLS block. */ +size_t _dl_tls_static_size; +/* Size actually allocated in the static TLS block. */ +size_t _dl_tls_static_used; +/* Alignment requirement of the static TLS block. */ +size_t _dl_tls_static_align; + +/* Generation counter for the dtv. */ +size_t _dl_tls_generation; + + +/* Additional definitions needed by TLS initialization. */ +#ifdef TLS_INIT_HELPER +TLS_INIT_HELPER +#endif + +static inline void +init_slotinfo (void) +{ + /* Create the slotinfo list. */ + static_slotinfo.si.len = (((char *) (&static_slotinfo + 1) + - (char *) &static_slotinfo.si.slotinfo[0]) + / sizeof static_slotinfo.si.slotinfo[0]); + // static_slotinfo.si.next = NULL; already zero + + /* The slotinfo list. Will be extended by the code doing dynamic + linking. */ + GL(dl_tls_max_dtv_idx) = 1; + GL(dl_tls_dtv_slotinfo_list) = &static_slotinfo.si; +} + +static inline void +init_static_tls (size_t memsz, size_t align) +{ + /* That is the size of the TLS memory for this object. The initialized + value of _dl_tls_static_size is provided by dl-open.c to request some + surplus that permits dynamic loading of modules with IE-model TLS. */ + GL(dl_tls_static_size) = roundup (memsz + GL(dl_tls_static_size), + TLS_TCB_ALIGN); + GL(dl_tls_static_used) = memsz; + /* The alignment requirement for the static TLS block. */ + GL(dl_tls_static_align) = align; + /* Number of elements in the static TLS block. */ + GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx); +} + +void +__libc_setup_tls (size_t tcbsize, size_t tcbalign) +{ + void *tlsblock; + size_t memsz = 0; + size_t filesz = 0; + void *initimage = NULL; + size_t align = 0; + size_t max_align = tcbalign; + size_t tcb_offset; + ElfW(Phdr) *phdr; + + /* Look through the TLS segment if there is any. */ + if (_dl_phdr != NULL) + for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr) + if (phdr->p_type == PT_TLS) + { + /* Remember the values we need. */ + memsz = phdr->p_memsz; + filesz = phdr->p_filesz; + initimage = (void *) phdr->p_vaddr; + align = phdr->p_align; + if (phdr->p_align > max_align) + max_align = phdr->p_align; + break; + } + + /* We have to set up the TCB block which also (possibly) contains + 'errno'. Therefore we avoid 'malloc' which might touch 'errno'. + Instead we use 'sbrk' which would only uses 'errno' if it fails. + In this case we are right away out of memory and the user gets + what she/he deserves. + + The initialized value of _dl_tls_static_size is provided by dl-open.c + to request some surplus that permits dynamic loading of modules with + IE-model TLS. */ +# if defined(TLS_TCB_AT_TP) + tcb_offset = roundup (memsz + GL(dl_tls_static_size), tcbalign); + tlsblock = sbrk (tcb_offset + tcbsize + max_align); +# elif defined(TLS_DTV_AT_TP) + tcb_offset = roundup (tcbsize, align ?: 1); + tlsblock = sbrk (tcb_offset + memsz + max_align + + TLS_PRE_TCB_SIZE + GL(dl_tls_static_size)); + tlsblock += TLS_PRE_TCB_SIZE; +# else + /* In case a model with a different layout for the TCB and DTV + is defined add another #elif here and in the following #ifs. */ +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* Align the TLS block. */ + tlsblock = (void *) (((uintptr_t) tlsblock + max_align - 1) + & ~(max_align - 1)); + + /* Initialize the dtv. [0] is the length, [1] the generation counter. */ + static_dtv[0].counter = (sizeof (static_dtv) / sizeof (static_dtv[0])) - 2; + // static_dtv[1].counter = 0; would be needed if not already done + + /* Initialize the TLS block. */ +# if defined(TLS_TCB_AT_TP) + static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset + - roundup (memsz, align ?: 1)); + static_map.l_tls_offset = roundup (memsz, align ?: 1); +# elif defined(TLS_DTV_AT_TP) + static_dtv[2].pointer.val = (char *) tlsblock + tcb_offset; + static_map.l_tls_offset = tcb_offset; +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + static_dtv[2].pointer.is_static = true; + /* sbrk gives us zero'd memory, so we don't need to clear the remainder. */ + memcpy (static_dtv[2].pointer.val, initimage, filesz); + + /* Install the pointer to the dtv. */ + + /* Initialize the thread pointer. */ +# if defined(TLS_TCB_AT_TP) + INSTALL_DTV ((char *) tlsblock + tcb_offset, static_dtv); + + const char *lossage = TLS_INIT_TP ((char *) tlsblock + tcb_offset, 0); +# elif defined(TLS_DTV_AT_TP) + INSTALL_DTV (tlsblock, static_dtv); + const char *lossage = (char *)TLS_INIT_TP (tlsblock, 0); +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + if (__builtin_expect (lossage != NULL, 0)) + abort(); + + /* We have to create a fake link map which normally would be created + by the dynamic linker. It just has to have enough information to + make the TLS routines happy. */ + static_map.l_tls_align = align; + static_map.l_tls_blocksize = memsz; + static_map.l_tls_initimage = initimage; + static_map.l_tls_initimage_size = filesz; + static_map.l_tls_modid = 1; + + init_slotinfo (); + // static_slotinfo.si.slotinfo[1].gen = 0; already zero + static_slotinfo.si.slotinfo[1].map = &static_map; + + memsz = roundup (memsz, align ?: 1); + +# if defined(TLS_TCB_AT_TP) + memsz += tcbsize; +# elif defined(TLS_DTV_AT_TP) + memsz += tcb_offset; +# endif + + init_static_tls (memsz, MAX (TLS_TCB_ALIGN, max_align)); +} + +/* This is called only when the data structure setup was skipped at startup, + when there was no need for it then. Now we have dynamically loaded + something needing TLS, or libpthread needs it. */ +int +internal_function +_dl_tls_setup (void) +{ + init_slotinfo (); + init_static_tls ( +# if defined(TLS_TCB_AT_TP) + TLS_TCB_SIZE, +# else + 0, +# endif + TLS_TCB_ALIGN); + return 0; +} + + +/* This is the minimal initialization function used when libpthread is + not used. */ +void +__attribute__ ((weak)) +__pthread_initialize_minimal (void) +{ + __libc_setup_tls (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN); +} + +#elif defined NONTLS_INIT_TP + +/* This is the minimal initialization function used when libpthread is + not used. */ +void +__attribute__ ((weak)) +__pthread_initialize_minimal (void) +{ + NONTLS_INIT_TP; +} + +#endif diff --git a/libpthread/nptl/sysdeps/generic/lowlevellock.h b/libpthread/nptl/sysdeps/generic/lowlevellock.h new file mode 100644 index 000000000..0600e1794 --- /dev/null +++ b/libpthread/nptl/sysdeps/generic/lowlevellock.h @@ -0,0 +1,84 @@ +/* Low level locking macros used in NPTL implementation. Stub version. + Copyright (C) 2002, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <atomic.h> + + +/* Mutex lock counter: + bit 31 clear means unlocked; + bit 31 set means locked. + + All code that looks at bit 31 first increases the 'number of + interested threads' usage counter, which is in bits 0-30. + + All negative mutex values indicate that the mutex is still locked. */ + + +static inline void +__generic_mutex_lock (int *mutex) +{ + unsigned int v; + + /* Bit 31 was clear, we got the mutex. (this is the fastpath). */ + if (atomic_bit_test_set (mutex, 31) == 0) + return; + + atomic_increment (mutex); + + while (1) + { + if (atomic_bit_test_set (mutex, 31) == 0) + { + atomic_decrement (mutex); + return; + } + + /* We have to wait now. First make sure the futex value we are + monitoring is truly negative (i.e. locked). */ + v = *mutex; + if (v >= 0) + continue; + + lll_futex_wait (mutex, v, + // XYZ check mutex flag + LLL_SHARED); + } +} + + +static inline void +__generic_mutex_unlock (int *mutex) +{ + /* Adding 0x80000000 to the counter results in 0 if and only if + there are not other interested threads - we can return (this is + the fastpath). */ + if (atomic_add_zero (mutex, 0x80000000)) + return; + + /* There are other threads waiting for this mutex, wake one of them + up. */ + lll_futex_wake (mutex, 1, + // XYZ check mutex flag + LLL_SHARED); +} + + +#define lll_mutex_lock(futex) __generic_mutex_lock (&(futex)) +#define lll_mutex_unlock(futex) __generic_mutex_unlock (&(futex)) diff --git a/libpthread/nptl/sysdeps/i386/Makefile b/libpthread/nptl/sysdeps/i386/Makefile new file mode 100644 index 000000000..2f0d88f30 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/Makefile @@ -0,0 +1,27 @@ +# Copyright (C) 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; if not, write to the Free +# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +# 02111-1307 USA. + +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif + +ifeq ($(subdir),nptl) +CFLAGS-pthread_create.c += -mpreferred-stack-boundary=4 +CFLAGS-tst-align.c += -mpreferred-stack-boundary=4 +CFLAGS-tst-align2.c += -mpreferred-stack-boundary=4 +endif diff --git a/libpthread/nptl/sysdeps/i386/Makefile.arch b/libpthread/nptl/sysdeps/i386/Makefile.arch new file mode 100644 index 000000000..e2bb2efd8 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/Makefile.arch @@ -0,0 +1,53 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_CSRC = pthread_spin_lock.c +libpthread_SSRC = i486/pthread_spin_trylock.S + +CFLAGS-pthread_spin_lock.c += -D_GNU_SOURCE + +CFLAGS-i386 = $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +PTHREAD_ARCH_DIR := $(top_srcdir)libpthread/nptl/sysdeps/i386 +PTHREAD_ARCH_OUT := $(top_builddir)libpthread/nptl/sysdeps/i386 +PTHREAD_ARCH_OBJ := $(patsubst %.S,$(PTHREAD_ARCH_OUT)/%.o,$(libpthread_SSRC)) +PTHREAD_ARCH_OBJ += $(patsubst %.c,$(PTHREAD_ARCH_OUT)/%.o,$(libpthread_CSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(PTHREAD_ARCH_OBJ:.o=.os) +else +libpthread-a-y += $(PTHREAD_ARCH_OBJ) +endif +libpthread-so-y += $(PTHREAD_ARCH_OBJ:.o=.oS) + +libpthread-nomulti-y += $(PTHREAD_ARCH_OBJ) + +objclean-y += nptl_arch_clean +headers_clean-y += nptl_arch_headers_clean + +# +# Create 'tcb-offsets.h' header file. +# +CFLAGS-tcb-offsets.c = -S + +$(PTHREAD_ARCH_OUT)/tcb-offsets.c: $(PTHREAD_ARCH_DIR)/tcb-offsets.sym + $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ + +$(PTHREAD_ARCH_OUT)/tcb-offsets.s: $(PTHREAD_ARCH_OUT)/tcb-offsets.c + $(compile.c) + +$(PTHREAD_ARCH_OUT)/tcb-offsets.h: $(PTHREAD_ARCH_OUT)/tcb-offsets.s + $(do_sed) -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $@ + +pregen-headers-$(UCLIBC_HAS_THREADS_NATIVE) += $(PTHREAD_ARCH_OUT)/tcb-offsets.h + +nptl_arch_headers_clean: + $(do_rm) $(addprefix $(PTHREAD_ARCH_OUT)/tcb-offsets., c s h) + +nptl_arch_clean: + $(do_rm) $(addprefix $(PTHREAD_ARCH_OUT)/*., o os oS) diff --git a/libpthread/nptl/sysdeps/i386/dl-tls.h b/libpthread/nptl/sysdeps/i386/dl-tls.h new file mode 100644 index 000000000..e94f9654e --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/dl-tls.h @@ -0,0 +1,62 @@ +/* Thread-local storage handling in the ELF dynamic linker. i386 version. + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + + +extern void *__tls_get_addr (tls_index *ti); + +#ifdef SHARED +/* This is the prototype for the GNU version. */ +extern void *___tls_get_addr (tls_index *ti) + __attribute__ ((__regparm__ (1))); +extern void *___tls_get_addr_internal (tls_index *ti) + __attribute__ ((__regparm__ (1))) attribute_hidden; + +# ifdef IS_IN_rtld +/* The special thing about the x86 TLS ABI is that we have two + variants of the __tls_get_addr function with different calling + conventions. The GNU version, which we are mostly concerned here, + takes the parameter in a register. The name is changed by adding + an additional underscore at the beginning. The Sun version uses + the normal calling convention. */ +void * +__tls_get_addr (tls_index *ti) +{ + return ___tls_get_addr_internal (ti); +} + + +/* Prepare using the definition of __tls_get_addr in the generic + version of this file. */ +# define __tls_get_addr __attribute__ ((__regparm__ (1))) ___tls_get_addr +strong_alias (___tls_get_addr, ___tls_get_addr_internal) +#else + +/* Users should get the better interface. */ +# define __tls_get_addr ___tls_get_addr + +# endif +#endif diff --git a/libpthread/nptl/sysdeps/i386/i486/pthread_spin_trylock.S b/libpthread/nptl/sysdeps/i386/i486/pthread_spin_trylock.S new file mode 100644 index 000000000..e30072c3d --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/i486/pthread_spin_trylock.S @@ -0,0 +1,47 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthread-errnos.h> + + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + + .globl pthread_spin_trylock + .type pthread_spin_trylock,@function + .align 16 +pthread_spin_trylock: + movl 4(%esp), %edx + movl $1, %eax + xorl %ecx, %ecx + LOCK + cmpxchgl %ecx, (%edx) + movl $EBUSY, %eax +#ifdef HAVE_CMOV + cmovel %ecx, %eax +#else + jne 0f + movl %ecx, %eax +0: +#endif + ret + .size pthread_spin_trylock,.-pthread_spin_trylock diff --git a/libpthread/nptl/sysdeps/i386/i586/pthread_spin_trylock.S b/libpthread/nptl/sysdeps/i386/i586/pthread_spin_trylock.S new file mode 100644 index 000000000..ffe3d456b --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/i586/pthread_spin_trylock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/pthread_spin_trylock.S" diff --git a/libpthread/nptl/sysdeps/i386/i686/Makefile b/libpthread/nptl/sysdeps/i386/i686/Makefile new file mode 100644 index 000000000..137c0a2f0 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/i686/Makefile @@ -0,0 +1,32 @@ +# Copyright (C) 2003 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, write to the Free +# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +# 02111-1307 USA. + +ifeq ($(subdir),nptl) +# It turns out that stack coloring is in general not good on P4s. Some +# applications will benefit. We will probably have a configuration option +# at some point. Enabling coloring can be done with +# +# -DCOLORING_INCREMENT=128 +# +# What is useful is to avoid the 64k aliasing problem which reliably +# happens if all stacks use sizes which are a multiple of 64k. Tell +# the stack allocator to disturb this by allocation one more page if +# necessary. +CFLAGS-pthread_create.c += -DMULTI_PAGE_ALIASING=65536 +endif diff --git a/libpthread/nptl/sysdeps/i386/i686/pthread_spin_trylock.S b/libpthread/nptl/sysdeps/i386/i686/pthread_spin_trylock.S new file mode 100644 index 000000000..a5d861f92 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/i686/pthread_spin_trylock.S @@ -0,0 +1,21 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define HAVE_CMOV 1 +#include "../i486/pthread_spin_trylock.S" diff --git a/libpthread/nptl/sysdeps/i386/i686/tls.h b/libpthread/nptl/sysdeps/i386/i686/tls.h new file mode 100644 index 000000000..4025ed8d2 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/i686/tls.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H + +/* Additional definitions for <tls.h> on i686 and up. */ + + +/* Macros to load from and store into segment registers. We can use + the 32-bit instructions. */ +#define TLS_GET_GS() \ + ({ int __seg; __asm ("movl %%gs, %0" : "=q" (__seg)); __seg; }) +#define TLS_SET_GS(val) \ + __asm ("movl %0, %%gs" :: "q" (val)) + + +/* Get the full set of definitions. */ +#include "../tls.h" + +#endif /* tls.h */ diff --git a/libpthread/nptl/sysdeps/i386/jmpbuf-unwind.h b/libpthread/nptl/sysdeps/i386/jmpbuf-unwind.h new file mode 100644 index 000000000..b9528f363 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/jmpbuf-unwind.h @@ -0,0 +1,32 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 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 <setjmp.h> +#include <stdint.h> +#include <unwind.h> + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ + _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ + ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_SP] - (_adj)) + +/* We use the normal lobngjmp for unwinding. */ +extern __typeof(longjmp) __libc_longjmp attribute_noreturn; +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/libpthread/nptl/sysdeps/i386/pthread_spin_init.c b/libpthread/nptl/sysdeps/i386/pthread_spin_init.c new file mode 100644 index 000000000..0a47981aa --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/pthread_spin_init.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Not needed. pthread_spin_init is an alias for pthread_spin_unlock. */ diff --git a/libpthread/nptl/sysdeps/i386/pthread_spin_lock.c b/libpthread/nptl/sysdeps/i386/pthread_spin_lock.c new file mode 100644 index 000000000..34cd525dc --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/pthread_spin_lock.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2002,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + +#ifndef LOCK_PREFIX +# ifdef UP +# define LOCK_PREFIX /* nothing */ +# else +# define LOCK_PREFIX "lock;" +# endif +#endif + + +int +pthread_spin_lock ( + pthread_spinlock_t *lock) +{ + __asm__ ("\n" + "1:\t" LOCK_PREFIX "decl %0\n\t" + "jne 2f\n\t" + ".subsection 1\n\t" + ".align 16\n" + "2:\trep; nop\n\t" + "cmpl $0, %0\n\t" + "jg 1b\n\t" + "jmp 2b\n\t" + ".previous" + : "=m" (*lock) + : "m" (*lock)); + + return 0; +} diff --git a/libpthread/nptl/sysdeps/i386/pthread_spin_unlock.S b/libpthread/nptl/sysdeps/i386/pthread_spin_unlock.S new file mode 100644 index 000000000..d94f1e7b8 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/pthread_spin_unlock.S @@ -0,0 +1,32 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + .globl pthread_spin_unlock + .type pthread_spin_unlock,@function + .align 16 +pthread_spin_unlock: + movl 4(%esp), %eax + movl $1, (%eax) + xorl %eax, %eax + ret + .size pthread_spin_unlock,.-pthread_spin_unlock + + /* The implementation of pthread_spin_init is identical. */ + .globl pthread_spin_init +pthread_spin_init = pthread_spin_unlock diff --git a/libpthread/nptl/sysdeps/i386/pthreaddef.h b/libpthread/nptl/sysdeps/i386/pthreaddef.h new file mode 100644 index 000000000..81456a4fc --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/pthreaddef.h @@ -0,0 +1,48 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. SSE requires 16 + bytes. */ +#define STACK_ALIGN 16 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 2048 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 16 + + +/* Location of current stack frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + + +/* XXX Until we have a better place keep the definitions here. */ + +/* While there is no such syscall. */ +#define __exit_thread_inline(val) \ + while (1) { \ + if (__builtin_constant_p (val) && (val) == 0) \ + __asm__ volatile ("xorl %%ebx, %%ebx; int $0x80" :: "a" (__NR_exit)); \ + else \ + __asm__ volatile ("movl %1, %%ebx; int $0x80" \ + :: "a" (__NR_exit), "r" (val)); \ + } diff --git a/libpthread/nptl/sysdeps/i386/tcb-offsets.sym b/libpthread/nptl/sysdeps/i386/tcb-offsets.sym new file mode 100644 index 000000000..69f9deb36 --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/tcb-offsets.sym @@ -0,0 +1,17 @@ +#include <sysdep.h> +#include <tls.h> + +RESULT offsetof (struct pthread, result) +TID offsetof (struct pthread, tid) +PID offsetof (struct pthread, pid) +CANCELHANDLING offsetof (struct pthread, cancelhandling) +CLEANUP_JMP_BUF offsetof (struct pthread, cleanup_jmp_buf) +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) +SYSINFO_OFFSET offsetof (tcbhead_t, sysinfo) +CLEANUP offsetof (struct pthread, cleanup) +CLEANUP_PREV offsetof (struct _pthread_cleanup_buffer, __prev) +MUTEX_FUTEX offsetof (pthread_mutex_t, __data.__lock) +POINTER_GUARD offsetof (tcbhead_t, pointer_guard) +#ifndef __ASSUME_PRIVATE_FUTEX +PRIVATE_FUTEX offsetof (tcbhead_t, private_futex) +#endif diff --git a/libpthread/nptl/sysdeps/i386/tls.h b/libpthread/nptl/sysdeps/i386/tls.h new file mode 100644 index 000000000..5f27d8fec --- /dev/null +++ b/libpthread/nptl/sysdeps/i386/tls.h @@ -0,0 +1,480 @@ +/* Definition for thread-local data handling. nptl/i386 version. + Copyright (C) 2002-2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H 1 + +#ifndef __ASSEMBLER__ +# include <stdbool.h> +# include <stddef.h> +# include <stdint.h> +# include <stdlib.h> +# include <list.h> +# include <sysdep.h> +# include <bits/kernel-features.h> + + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessarily the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ + int multiple_threads; + uintptr_t sysinfo; + uintptr_t stack_guard; + uintptr_t pointer_guard; + int gscope_flag; +#ifndef __ASSUME_PRIVATE_FUTEX + int private_futex; +#else + int __unused1; +#endif + /* Reservation of some values for the TM ABI. */ + void *__private_tm[5]; +} tcbhead_t; + +# define TLS_MULTIPLE_THREADS_IN_TCB 1 + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif + + +/* We require TLS support in the tools. */ +#define HAVE_TLS_SUPPORT +#define HAVE___THREAD 1 +#define HAVE_TLS_MODEL_ATTRIBUTE 1 + +/* 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 + +#ifndef __ASSEMBLER__ +/* Get system call information. */ +# include <sysdep.h> + +/* The old way: using LDT. */ + +/* Structure passed to `modify_ldt', 'set_thread_area', and 'clone' calls. */ +struct user_desc +{ + unsigned int entry_number; + unsigned long int base_addr; + unsigned int limit; + unsigned int seg_32bit:1; + unsigned int contents:2; + unsigned int read_exec_only:1; + unsigned int limit_in_pages:1; + unsigned int seg_not_present:1; + unsigned int useable:1; + unsigned int empty:25; +}; + +/* Initializing bit fields is slow. We speed it up by using a union. */ +union user_desc_init +{ + struct user_desc desc; + unsigned int vals[4]; +}; + + +/* Get the thread descriptor definition. */ +# include <descr.h> + +/* This is the size of the initial TCB. Can't be just sizeof (tcbhead_t), + because NPTL getpid, __libc_alloca_cutoff etc. need (almost) the whole + struct pthread even when not linked with -lpthread. */ +# define TLS_INIT_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtvp) \ + ({ struct pthread *__pd; \ + THREAD_SETMEM (__pd, header.dtv, (dtvp)); }) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +#define THREAD_SELF_SYSINFO THREAD_GETMEM (THREAD_SELF, header.sysinfo) +#define THREAD_SYSINFO(pd) ((pd)->header.sysinfo) + +/* Macros to load from and store into segment registers. */ +# ifndef TLS_GET_GS +# define TLS_GET_GS() \ + ({ int __seg; __asm__ ("movw %%gs, %w0" : "=q" (__seg)); __seg & 0xffff; }) +# endif +# ifndef TLS_SET_GS +# define TLS_SET_GS(val) \ + __asm__ ("movw %w0, %%gs" :: "q" (val)) +# endif + + +# ifndef __NR_set_thread_area +# define __NR_set_thread_area 243 +# endif +# ifndef TLS_FLAG_WRITABLE +# define TLS_FLAG_WRITABLE 0x00000001 +# endif + +// XXX Enable for the real world. +#if 0 +# ifndef __ASSUME_SET_THREAD_AREA +# error "we need set_thread_area" +# endif +#endif + +# ifdef __PIC__ +# define TLS_EBX_ARG "r" +# define TLS_LOAD_EBX "xchgl %3, %%ebx\n\t" +# else +# define TLS_EBX_ARG "b" +# define TLS_LOAD_EBX +# endif + +#if defined NEED_DL_SYSINFO +# define INIT_SYSINFO \ + _head->sysinfo = GLRO(dl_sysinfo) +#else +# define INIT_SYSINFO +#endif + +#ifndef LOCK_PREFIX +# ifdef UP +# define LOCK_PREFIX /* nothing */ +# else +# define LOCK_PREFIX "lock;" +# endif +#endif + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(thrdescr, secondcall) \ + ({ void *_thrdescr = (thrdescr); \ + tcbhead_t *_head = _thrdescr; \ + union user_desc_init _segdescr; \ + int _result; \ + \ + _head->tcb = _thrdescr; \ + /* For now the thread descriptor is at the same address. */ \ + _head->self = _thrdescr; \ + /* New syscall handling support. */ \ + INIT_SYSINFO; \ + \ + /* The 'entry_number' field. Let the kernel pick a value. */ \ + if (secondcall) \ + _segdescr.vals[0] = TLS_GET_GS () >> 3; \ + else \ + _segdescr.vals[0] = -1; \ + /* The 'base_addr' field. Pointer to the TCB. */ \ + _segdescr.vals[1] = (unsigned long int) _thrdescr; \ + /* The 'limit' field. We use 4GB which is 0xfffff pages. */ \ + _segdescr.vals[2] = 0xfffff; \ + /* Collapsed value of the bitfield: \ + .seg_32bit = 1 \ + .contents = 0 \ + .read_exec_only = 0 \ + .limit_in_pages = 1 \ + .seg_not_present = 0 \ + .useable = 1 */ \ + _segdescr.vals[3] = 0x51; \ + \ + /* Install the TLS. */ \ + __asm__ volatile (TLS_LOAD_EBX \ + "int $0x80\n\t" \ + TLS_LOAD_EBX \ + : "=a" (_result), "=m" (_segdescr.desc.entry_number) \ + : "0" (__NR_set_thread_area), \ + TLS_EBX_ARG (&_segdescr.desc), "m" (_segdescr.desc)); \ + \ + if (_result == 0) \ + /* We know the index in the GDT, now load the segment register. \ + The use of the GDT is described by the value 3 in the lower \ + three bits of the segment descriptor value. \ + \ + Note that we have to do this even if the numeric value of \ + the descriptor does not change. Loading the segment register \ + causes the segment information from the GDT to be loaded \ + which is necessary since we have changed it. */ \ + TLS_SET_GS (_segdescr.desc.entry_number * 8 + 3); \ + \ + _result == 0 ? NULL \ + : "set_thread_area failed when setting up thread-local storage\n"; }) + + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ struct pthread *__pd; \ + THREAD_GETMEM (__pd, header.dtv); }) + + +/* Return the thread descriptor for the current thread. + + The contained asm must *not* be marked volatile since otherwise + assignments like + pthread_descr self = thread_self(); + do not get optimized away. */ +# define THREAD_SELF \ + ({ struct pthread *__self; \ + __asm__ ("movl %%gs:%c1,%0" : "=r" (__self) \ + : "i" (offsetof (struct pthread, header.self))); \ + __self;}) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF \ + REGISTER_THREAD_AREA (32, offsetof (struct user_regs_struct, xgs), 3) \ + REGISTER_THREAD_AREA (64, 26 * 8, 3) /* x86-64's user_regs_struct->gs */ + + +/* Read member of the thread descriptor directly. */ +# define THREAD_GETMEM(descr, member) \ + ({ __typeof (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ volatile ("movb %%gs:%P2,%b0" \ + : "=q" (__value) \ + : "0" (0), "i" (offsetof (struct pthread, member))); \ + else if (sizeof (__value) == 4) \ + __asm__ volatile ("movl %%gs:%P1,%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct pthread, member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ volatile ("movl %%gs:%P1,%%eax\n\t" \ + "movl %%gs:%P2,%%edx" \ + : "=A" (__value) \ + : "i" (offsetof (struct pthread, member)), \ + "i" (offsetof (struct pthread, member) + 4)); \ + } \ + __value; }) + + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +# define THREAD_GETMEM_NC(descr, member, idx) \ + ({ __typeof (descr->member[0]) __value; \ + if (sizeof (__value) == 1) \ + __asm__ volatile ("movb %%gs:%P2(%3),%b0" \ + : "=q" (__value) \ + : "0" (0), "i" (offsetof (struct pthread, member[0])), \ + "r" (idx)); \ + else if (sizeof (__value) == 4) \ + __asm__ volatile ("movl %%gs:%P1(,%2,4),%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct pthread, member[0])), \ + "r" (idx)); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ volatile ("movl %%gs:%P1(,%2,8),%%eax\n\t" \ + "movl %%gs:4+%P1(,%2,8),%%edx" \ + : "=&A" (__value) \ + : "i" (offsetof (struct pthread, member[0])), \ + "r" (idx)); \ + } \ + __value; }) + + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +# define THREAD_SETMEM(descr, member, value) \ + ({ if (sizeof (descr->member) == 1) \ + __asm__ volatile ("movb %b0,%%gs:%P1" : \ + : "iq" (value), \ + "i" (offsetof (struct pthread, member))); \ + else if (sizeof (descr->member) == 4) \ + __asm__ volatile ("movl %0,%%gs:%P1" : \ + : "ir" (value), \ + "i" (offsetof (struct pthread, member))); \ + else \ + { \ + if (sizeof (descr->member) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ volatile ("movl %%eax,%%gs:%P1\n\t" \ + "movl %%edx,%%gs:%P2" : \ + : "A" (value), \ + "i" (offsetof (struct pthread, member)), \ + "i" (offsetof (struct pthread, member) + 4)); \ + }}) + + +/* Set member of the thread descriptor directly. */ +# define THREAD_SETMEM_NC(descr, member, idx, value) \ + ({ if (sizeof (descr->member[0]) == 1) \ + __asm__ volatile ("movb %b0,%%gs:%P1(%2)" : \ + : "iq" (value), \ + "i" (offsetof (struct pthread, member)), \ + "r" (idx)); \ + else if (sizeof (descr->member[0]) == 4) \ + __asm__ volatile ("movl %0,%%gs:%P1(,%2,4)" : \ + : "ir" (value), \ + "i" (offsetof (struct pthread, member)), \ + "r" (idx)); \ + else \ + { \ + if (sizeof (descr->member[0]) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ volatile ("movl %%eax,%%gs:%P1(,%2,8)\n\t" \ + "movl %%edx,%%gs:4+%P1(,%2,8)" : \ + : "A" (value), \ + "i" (offsetof (struct pthread, member)), \ + "r" (idx)); \ + }}) + + +/* Atomic compare and exchange on TLS, returning old value. */ +#define THREAD_ATOMIC_CMPXCHG_VAL(descr, member, newval, oldval) \ + ({ __typeof (descr->member) __ret; \ + __typeof (oldval) __old = (oldval); \ + if (sizeof (descr->member) == 4) \ + __asm__ volatile (LOCK_PREFIX "cmpxchgl %2, %%gs:%P3" \ + : "=a" (__ret) \ + : "0" (__old), "r" (newval), \ + "i" (offsetof (struct pthread, member))); \ + else \ + /* Not necessary for other sizes in the moment. */ \ + abort (); \ + __ret; }) + + +/* Atomic logical and. */ +#define THREAD_ATOMIC_AND(descr, member, val) \ + (void) ({ if (sizeof ((descr)->member) == 4) \ + __asm__ volatile (LOCK_PREFIX "andl %1, %%gs:%P0" \ + :: "i" (offsetof (struct pthread, member)), \ + "ir" (val)); \ + else \ + /* Not necessary for other sizes in the moment. */ \ + abort (); }) + + +/* Atomic set bit. */ +#define THREAD_ATOMIC_BIT_SET(descr, member, bit) \ + (void) ({ if (sizeof ((descr)->member) == 4) \ + __asm__ volatile (LOCK_PREFIX "orl %1, %%gs:%P0" \ + :: "i" (offsetof (struct pthread, member)), \ + "ir" (1 << (bit))); \ + else \ + /* Not necessary for other sizes in the moment. */ \ + abort (); }) + + +/* Call the user-provided thread function. */ +#define CALL_THREAD_FCT(descr) \ + ({ void *__res; \ + int __ignore1, __ignore2; \ + __asm__ volatile ("pushl %%eax\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%gs:%P4\n\t" \ + "call *%%gs:%P3\n\t" \ + "addl $16, %%esp" \ + : "=a" (__res), "=c" (__ignore1), "=d" (__ignore2) \ + : "i" (offsetof (struct pthread, start_routine)), \ + "i" (offsetof (struct pthread, arg))); \ + __res; }) + + +/* Set the stack guard field in TCB head. */ +#define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.stack_guard, value) +#define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->header.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, header.stack_guard)) + + +/* Set the pointer guard field in the TCB head. */ +#define THREAD_SET_POINTER_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.pointer_guard, value) +#define THREAD_COPY_POINTER_GUARD(descr) \ + ((descr)->header.pointer_guard \ + = 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, LLL_PRIVATE); \ + } \ + 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/libpthread/nptl/sysdeps/mips/Makefile b/libpthread/nptl/sysdeps/mips/Makefile new file mode 100644 index 000000000..6371d2871 --- /dev/null +++ b/libpthread/nptl/sysdeps/mips/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libpthread/nptl/sysdeps/mips/Makefile.arch b/libpthread/nptl/sysdeps/mips/Makefile.arch new file mode 100644 index 000000000..2b17aeed1 --- /dev/null +++ b/libpthread/nptl/sysdeps/mips/Makefile.arch @@ -0,0 +1,67 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_SSRC = pthread_spin_lock.S pthread_spin_trylock.S \ + nptl-sysdep.S + +libc_a_CSRC = libc-tls.c + +CFLAGS-pt-raise.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + +ASFLAGS-pthread_spin_lock.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +ASFLAGS-pthread_spin_trylock.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +ASFLAGS-nptl-sysdep.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 \ + -I$(top_srcdir)libc/sysdeps/linux/mips + +CFLAGS-mips = $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +PTHREAD_ARCH_DIR := $(top_srcdir)libpthread/nptl/sysdeps/mips +PTHREAD_ARCH_OUT := $(top_builddir)libpthread/nptl/sysdeps/mips +PTHREAD_ARCH_OBJ := $(patsubst %.S,$(PTHREAD_ARCH_OUT)/%.o,$(libpthread_SSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(PTHREAD_ARCH_OBJ:.o=.os) +else +libpthread-a-y += $(PTHREAD_ARCH_OBJ) +endif +libpthread-so-y += $(PTHREAD_ARCH_OBJ:.o=.oS) + +libpthread-nomulti-y += $(PTHREAD_ARCH_OBJ) + +LIBC_ARCH_OBJ := $(patsubst %.c,$(PTHREAD_ARCH_OUT)/%.o,$(libc_a_CSRC)) + +libc-static-y += $(LIBC_ARCH_OBJ) + +libc-nomulti-y += $(LIBC_ARCH_OBJ) + +objclean-y += nptl_arch_objclean +headers_clean-y += nptl_arch_headers_clean + +# +# Create 'tcb-offsets.h' header file. +# +CFLAGS-tcb-offsets.c = -S + +$(PTHREAD_ARCH_OUT)/tcb-offsets.c: $(PTHREAD_ARCH_DIR)/tcb-offsets.sym + $(do_awk) -f $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ + +$(PTHREAD_ARCH_OUT)/tcb-offsets.s: $(PTHREAD_ARCH_OUT)/tcb-offsets.c + $(compile.c) + +$(PTHREAD_ARCH_OUT)/tcb-offsets.h: $(PTHREAD_ARCH_OUT)/tcb-offsets.s + $(do_sed) -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $@ + +pregen-headers-$(UCLIBC_HAS_THREADS_NATIVE) += $(PTHREAD_ARCH_OUT)/tcb-offsets.h + +nptl_arch_headers_clean: + $(RM) $(PTHREAD_ARCH_OUT)/tcb-offsets.c \ + $(PTHREAD_ARCH_OUT)/tcb-offsets.s \ + $(PTHREAD_ARCH_OUT)/tcb-offsets.h + +nptl_arch_objclean: + $(RM) $(PTHREAD_ARCH_OUT)/*.{o,os,oS} diff --git a/libpthread/nptl/sysdeps/mips/dl-tls.h b/libpthread/nptl/sysdeps/mips/dl-tls.h new file mode 100644 index 000000000..3ad3b2bc0 --- /dev/null +++ b/libpthread/nptl/sysdeps/mips/dl-tls.h @@ -0,0 +1,46 @@ +/* Thread-local storage handling in the ELF dynamic linker. MIPS version. + Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + +/* The thread pointer points 0x7000 past the first static TLS block. */ +#define TLS_TP_OFFSET 0x7000 + +/* Dynamic thread vector pointers point 0x8000 past the start of each + TLS block. */ +#define TLS_DTV_OFFSET 0x8000 + +/* Compute the value for a GOTTPREL reloc. */ +#define TLS_TPREL_VALUE(sym_map, sym_val) \ + ((sym_map)->l_tls_offset + sym_val - TLS_TP_OFFSET) + +/* Compute the value for a DTPREL reloc. */ +#define TLS_DTPREL_VALUE(sym_val) \ + (sym_val - TLS_DTV_OFFSET) + +extern void *__tls_get_addr (tls_index *ti); + +# define GET_ADDR_OFFSET (ti->ti_offset + TLS_DTV_OFFSET) +# define __TLS_GET_ADDR(__ti) (__tls_get_addr (__ti) - TLS_DTV_OFFSET) diff --git a/libpthread/nptl/sysdeps/mips/jmpbuf-unwind.h b/libpthread/nptl/sysdeps/mips/jmpbuf-unwind.h new file mode 100644 index 000000000..a9cfe43b3 --- /dev/null +++ b/libpthread/nptl/sysdeps/mips/jmpbuf-unwind.h @@ -0,0 +1,30 @@ +/* Copyright (C) 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <setjmp.h> +#include <stdint.h> +#include <unwind.h> + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ + _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ + ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[0].__sp - (_adj)) + +/* We use the normal longjmp for unwinding. */ +#define __libc_unwind_longjmp(buf, val) longjmp (buf, val) diff --git a/libpthread/nptl/sysdeps/mips/libc-tls.c b/libpthread/nptl/sysdeps/mips/libc-tls.c new file mode 100644 index 000000000..fdedc9f5a --- /dev/null +++ b/libpthread/nptl/sysdeps/mips/libc-tls.c @@ -0,0 +1,37 @@ +/* Thread-local storage handling in the ELF dynamic linker. MIPS version. + Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <../generic/libc-tls.c> +#include <dl-tls.h> + +#if USE_TLS + +/* On MIPS, linker optimizations are not required, so __tls_get_addr + can be called even in statically linked binaries. In this case module + must be always 1 and PT_TLS segment exist in the binary, otherwise it + would not link. */ + +void * +__tls_get_addr (tls_index *ti) +{ + dtv_t *dtv = THREAD_DTV (); + return (char *) dtv[1].pointer.val + GET_ADDR_OFFSET; +} + +#endif diff --git a/libpthread/nptl/sysdeps/mips/nptl-sysdep.S b/libpthread/nptl/sysdeps/mips/nptl-sysdep.S new file mode 100644 index 000000000..7a4a8d311 --- /dev/null +++ b/libpthread/nptl/sysdeps/mips/nptl-sysdep.S @@ -0,0 +1,2 @@ +/* Pull in __syscall_error. */ +#include <syscall_error.S> diff --git a/libpthread/nptl/sysdeps/mips/pthread_spin_lock.S b/libpthread/nptl/sysdeps/mips/pthread_spin_lock.S new file mode 100644 index 000000000..e35c381ed --- /dev/null +++ b/libpthread/nptl/sysdeps/mips/pthread_spin_lock.S @@ -0,0 +1,38 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sys/asm.h> +#include <sysdep.h> +#include <sgidefs.h> + +ENTRY (pthread_spin_lock) + .set push +#if _MIPS_SIM == _ABIO32 + .set mips2 +#endif +1: ll a2, 0(a0) + li a1, 1 + bnez a2, 1b + sc a1, 0(a0) + beqz a1, 1b + MIPS_SYNC + .set pop + li v0, 0 + j ra + nop +END (pthread_spin_lock) diff --git a/libpthread/nptl/sysdeps/mips/pthread_spin_trylock.S b/libpthread/nptl/sysdeps/mips/pthread_spin_trylock.S new file mode 100644 index 000000000..b54732869 --- /dev/null +++ b/libpthread/nptl/sysdeps/mips/pthread_spin_trylock.S @@ -0,0 +1,43 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sys/asm.h> +#include <sysdep.h> +#define _ERRNO_H 1 +#include <bits/errno.h> +#include <sgidefs.h> + +ENTRY (pthread_spin_trylock) + .set push +#if _MIPS_SIM == _ABIO32 + .set mips2 +#endif + ll a2, 0(a0) + li a1, 1 + bnez a2, 1f + sc a1, 0(a0) + beqz a1, 1f + MIPS_SYNC + .set pop + li v0, 0 + j ra + nop +1: li v0, EBUSY + j ra + nop +END (pthread_spin_trylock) diff --git a/libpthread/nptl/sysdeps/mips/pthreaddef.h b/libpthread/nptl/sysdeps/mips/pthreaddef.h new file mode 100644 index 000000000..e72b4bc58 --- /dev/null +++ b/libpthread/nptl/sysdeps/mips/pthreaddef.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. */ +#define STACK_ALIGN 16 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 2048 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 16 + + +/* Location of current stack frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + + +/* XXX Until we have a better place keep the definitions here. */ + +#define __exit_thread_inline(val) \ + INLINE_SYSCALL (exit, 1, (val)) diff --git a/libpthread/nptl/sysdeps/mips/regdef.h b/libpthread/nptl/sysdeps/mips/regdef.h new file mode 100644 index 000000000..a462d512a --- /dev/null +++ b/libpthread/nptl/sysdeps/mips/regdef.h @@ -0,0 +1,26 @@ +/* Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ralf Baechle <ralf@gnu.org>. + + 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. */ + +#ifndef _REGDEF_H +#define _REGDEF_H + +#include <sys/regdef.h> +#include <sys/fpregdef.h> + +#endif /* _REGDEF_H */ diff --git a/libpthread/nptl/sysdeps/mips/tcb-offsets.sym b/libpthread/nptl/sysdeps/mips/tcb-offsets.sym new file mode 100644 index 000000000..e0e71dc43 --- /dev/null +++ b/libpthread/nptl/sysdeps/mips/tcb-offsets.sym @@ -0,0 +1,11 @@ +#include <sysdep.h> +#include <tls.h> + +-- + +-- Abuse tls.h macros to derive offsets relative to the thread register. +#define thread_offsetof(mem) (long)(offsetof(struct pthread, mem) - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) + +MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads) +PID_OFFSET thread_offsetof (pid) +TID_OFFSET thread_offsetof (tid) diff --git a/libpthread/nptl/sysdeps/mips/tls.h b/libpthread/nptl/sysdeps/mips/tls.h new file mode 100644 index 000000000..27b1c15df --- /dev/null +++ b/libpthread/nptl/sysdeps/mips/tls.h @@ -0,0 +1,181 @@ +/* Definition for thread-local data handling. NPTL/MIPS version. + Copyright (C) 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 + 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. */ + +#ifndef _TLS_H +#define _TLS_H 1 + +#ifndef __ASSEMBLER__ +# include <stdbool.h> +# include <stddef.h> +# include <stdint.h> + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +/* Note: rd must be $v1 to be ABI-conformant. */ +# define READ_THREAD_POINTER() \ + ({ void *__result; \ + __asm__ __volatile__ (".set\tpush\n\t.set\tmips32r2\n\t" \ + "rdhwr\t%0, $29\n\t.set\tpop" : "=v" (__result)); \ + __result; }) + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> + +# define READ_THREAD_POINTER(rd) \ + .set push; \ + .set mips32r2; \ + rdhwr rd, $29; \ + .set pop +#endif /* __ASSEMBLER__ */ + + +/* We require TLS support in the tools. */ +#define HAVE_TLS_SUPPORT 1 +#define HAVE_TLS_MODEL_ATTRIBUTE 1 +#define HAVE___THREAD 1 + +/* Signal that TLS support is available. */ +#define USE_TLS 1 + +#ifndef __ASSEMBLER__ + +/* Get system call information. */ +# include <sysdep.h> + +/* The TP points to the start of the thread blocks. */ +# define TLS_DTV_AT_TP 1 + +/* Get the thread descriptor definition. */ +#include <../../descr.h> + +typedef struct +{ + dtv_t *dtv; + void *private; +} tcbhead_t; + +/* This is the size of the initial TCB. Because our TCB is before the thread + pointer, we don't need this. */ +# define TLS_INIT_TCB_SIZE 0 + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size of the TCB. Because our TCB is before the thread + pointer, we don't need this. */ +# define TLS_TCB_SIZE 0 + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size we need before TCB - actually, it includes the TCB. */ +# define TLS_PRE_TCB_SIZE \ + (sizeof (struct pthread) \ + + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1))) + +/* The thread pointer (in hardware register $29) points to the end of + the TCB + 0x7000, as for PowerPC. The pthread_descr structure is + immediately in front of the TCB. */ +# define TLS_TCB_OFFSET 0x7000 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + (((tcbhead_t *) (tcbp))[-1].dtv = (dtvp) + 1) + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + (THREAD_DTV() = (dtv)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) \ + (((tcbhead_t *) (tcbp))[-1].dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + ({ INTERNAL_SYSCALL_DECL (err); \ + long result_var; \ + result_var = INTERNAL_SYSCALL (set_thread_area, err, 1, \ + (char *) (tcbp) + TLS_TCB_OFFSET); \ + INTERNAL_SYSCALL_ERROR_P (result_var, err) \ + ? "unknown error" : NULL; }) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) (READ_THREAD_POINTER () - TLS_TCB_OFFSET))[-1].dtv) + +/* Return the thread descriptor for the current thread. */ +# define THREAD_SELF \ + ((struct pthread *) (READ_THREAD_POINTER () \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF \ + CONST_THREAD_AREA (32, TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE) + +/* Access to data in the thread descriptor is easy. */ +# define THREAD_GETMEM(descr, member) \ + descr->member +# define THREAD_GETMEM_NC(descr, member, idx) \ + descr->member[idx] +# define THREAD_SETMEM(descr, member, value) \ + descr->member = (value) +# define THREAD_SETMEM_NC(descr, member, idx, value) \ + descr->member[idx] = (value) + +/* l_tls_offset == 0 is perfectly valid on MIPS, so we have to use some + 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, LLL_PRIVATE); \ + } \ + 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/libpthread/nptl/sysdeps/powerpc/Makefile b/libpthread/nptl/sysdeps/powerpc/Makefile new file mode 100644 index 000000000..3af245600 --- /dev/null +++ b/libpthread/nptl/sysdeps/powerpc/Makefile @@ -0,0 +1,21 @@ +# Copyright (C) 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; if not, write to the Free +# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +# 02111-1307 USA. + +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif diff --git a/libpthread/nptl/sysdeps/powerpc/dl-tls.h b/libpthread/nptl/sysdeps/powerpc/dl-tls.h new file mode 100644 index 000000000..957d4b4b9 --- /dev/null +++ b/libpthread/nptl/sysdeps/powerpc/dl-tls.h @@ -0,0 +1,49 @@ +/* Thread-local storage handling in the ELF dynamic linker. PowerPC version. + Copyright (C) 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the TOC. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + +/* The thread pointer points 0x7000 past the first static TLS block. */ +#define TLS_TP_OFFSET 0x7000 + +/* Dynamic thread vector pointers point 0x8000 past the start of each + TLS block. */ +#define TLS_DTV_OFFSET 0x8000 + +/* Compute the value for a @tprel reloc. */ +#define TLS_TPREL_VALUE(sym_map, sym, reloc) \ + ((sym_map)->l_tls_offset + (sym)->st_value + (reloc)->r_addend \ + - TLS_TP_OFFSET) + +/* Compute the value for a @dtprel reloc. */ +#define TLS_DTPREL_VALUE(sym, reloc) \ + ((sym)->st_value + (reloc)->r_addend - TLS_DTV_OFFSET) + +#ifdef SHARED +extern void *__tls_get_addr (tls_index *ti); + +# define GET_ADDR_OFFSET (ti->ti_offset + TLS_DTV_OFFSET) +# define __TLS_GET_ADDR(__ti) (__tls_get_addr (__ti) - TLS_DTV_OFFSET) +#endif diff --git a/libpthread/nptl/sysdeps/powerpc/jmpbuf-unwind.h b/libpthread/nptl/sysdeps/powerpc/jmpbuf-unwind.h new file mode 100644 index 000000000..0b817160d --- /dev/null +++ b/libpthread/nptl/sysdeps/powerpc/jmpbuf-unwind.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 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 <setjmp.h> +#include <stdint.h> +#include <unwind.h> + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ + _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ + ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_GPR1] - (_adj)) + +/* We use the normal lobngjmp for unwinding. */ +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/libpthread/nptl/sysdeps/powerpc/pthread_spin_lock.c b/libpthread/nptl/sysdeps/powerpc/pthread_spin_lock.c new file mode 100644 index 000000000..e2293fda1 --- /dev/null +++ b/libpthread/nptl/sysdeps/powerpc/pthread_spin_lock.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras <paulus@au.ibm.com>, 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_lock (lock) + pthread_spinlock_t *lock; +{ + unsigned int __tmp; + + asm volatile ( + "1: lwarx %0,0,%1\n" + " cmpwi 0,%0,0\n" + " bne- 2f\n" + " stwcx. %2,0,%1\n" + " bne- 2f\n" + " isync\n" + " .subsection 1\n" + "2: lwzx %0,0,%1\n" + " cmpwi 0,%0,0\n" + " bne 2b\n" + " b 1b\n" + " .previous" + : "=&r" (__tmp) + : "r" (lock), "r" (1) + : "cr0", "memory"); + return 0; +} diff --git a/libpthread/nptl/sysdeps/powerpc/pthread_spin_trylock.c b/libpthread/nptl/sysdeps/powerpc/pthread_spin_trylock.c new file mode 100644 index 000000000..d8e1dbcc8 --- /dev/null +++ b/libpthread/nptl/sysdeps/powerpc/pthread_spin_trylock.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras <paulus@au.ibm.com>, 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 <errno.h> +#include "pthreadP.h" + +int +pthread_spin_trylock (lock) + pthread_spinlock_t *lock; +{ + unsigned int old; + int err = EBUSY; + + asm ("1: lwarx %0,0,%2\n" + " cmpwi 0,%0,0\n" + " bne 2f\n" + " stwcx. %3,0,%2\n" + " bne- 1b\n" + " li %1,0\n" + " isync\n" + "2: " + : "=&r" (old), "=&r" (err) + : "r" (lock), "r" (1), "1" (err) + : "cr0", "memory"); + + return err; +} diff --git a/libpthread/nptl/sysdeps/powerpc/pthreaddef.h b/libpthread/nptl/sysdeps/powerpc/pthreaddef.h new file mode 100644 index 000000000..342c15c67 --- /dev/null +++ b/libpthread/nptl/sysdeps/powerpc/pthreaddef.h @@ -0,0 +1,41 @@ +/* Copyright (C) 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (4 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. The ABI requires 16 + bytes (for both 32-bit and 64-bit PowerPC). */ +#define STACK_ALIGN 16 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 4096 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 16 + + +/* Location of current stack frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + + +/* XXX Until we have a better place keep the definitions here. */ + +/* While there is no such syscall. */ +#define __exit_thread_inline(val) \ + INLINE_SYSCALL (exit, 1, (val)) diff --git a/libpthread/nptl/sysdeps/powerpc/tcb-offsets.sym b/libpthread/nptl/sysdeps/powerpc/tcb-offsets.sym new file mode 100644 index 000000000..8ac133dfd --- /dev/null +++ b/libpthread/nptl/sysdeps/powerpc/tcb-offsets.sym @@ -0,0 +1,20 @@ +#include <sysdep.h> +#include <tls.h> + +-- + +-- Abuse tls.h macros to derive offsets relative to the thread register. +# undef __thread_register +# define __thread_register ((void *) 0) +# define thread_offsetof(mem) ((ptrdiff_t) THREAD_SELF + offsetof (struct pthread, mem)) + + +#if TLS_MULTIPLE_THREADS_IN_TCB +MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads) +#endif +PID thread_offsetof (pid) +TID thread_offsetof (tid) +POINTER_GUARD (offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (tcbhead_t)) +#ifndef __ASSUME_PRIVATE_FUTEX +PRIVATE_FUTEX_OFFSET thread_offsetof (header.private_futex) +#endif diff --git a/libpthread/nptl/sysdeps/powerpc/tls.h b/libpthread/nptl/sysdeps/powerpc/tls.h new file mode 100644 index 000000000..ce5559eef --- /dev/null +++ b/libpthread/nptl/sysdeps/powerpc/tls.h @@ -0,0 +1,209 @@ +/* Definition for thread-local data handling. NPTL/PowerPC version. + 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 + 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. */ + +#ifndef _TLS_H +#define _TLS_H 1 + +#ifndef __ASSEMBLER__ +# include <stdbool.h> +# include <stddef.h> +# include <stdint.h> + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif /* __ASSEMBLER__ */ + + +/* We require TLS support in the tools. */ +#ifndef HAVE_TLS_SUPPORT +# error "TLS support is required." +#endif + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +#ifndef __ASSEMBLER__ + +/* Get system call information. */ +# include <sysdep.h> + +/* The TP points to the start of the thread blocks. */ +# define TLS_DTV_AT_TP 1 + +/* We use the multiple_threads field in the pthread struct */ +#define TLS_MULTIPLE_THREADS_IN_TCB 1 + +/* Get the thread descriptor definition. */ +# include <nptl/descr.h> + +/* The stack_guard is accessed directly by GCC -fstack-protector code, + so it is a part of public ABI. The dtv and pointer_guard fields + are private. */ +typedef struct +{ + uintptr_t pointer_guard; + uintptr_t stack_guard; + dtv_t *dtv; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE 0 + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE 0 + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE \ + (sizeof (struct pthread) \ + + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1))) + +# ifndef __powerpc64__ +/* Register r2 (tp) is reserved by the ABI as "thread pointer". */ +register void *__thread_register __asm__ ("r2"); +# define PT_THREAD_POINTER PT_R2 +# else +/* Register r13 (tp) is reserved by the ABI as "thread pointer". */ +register void *__thread_register __asm__ ("r13"); +# define PT_THREAD_POINTER PT_R13 +# endif + +/* The following assumes that TP (R2 or R13) points to the end of the + TCB + 0x7000 (per the ABI). This implies that TCB address is + TP - 0x7000. As we define TLS_DTV_AT_TP we can + assume that the pthread struct is allocated immediately ahead of the + TCB. This implies that the pthread_descr address is + TP - (TLS_PRE_TCB_SIZE + 0x7000). */ +# define TLS_TCB_OFFSET 0x7000 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + ((tcbhead_t *) (tcbp))[-1].dtv = dtvp + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) (THREAD_DTV() = (dtv)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) (((tcbhead_t *) (tcbp))[-1].dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + (__thread_register = (void *) (tcbp) + TLS_TCB_OFFSET, NULL) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) (__thread_register - TLS_TCB_OFFSET))[-1].dtv) + +/* Return the thread descriptor for the current thread. */ +# define THREAD_SELF \ + ((struct pthread *) (__thread_register \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF \ + REGISTER (32, 32, PT_THREAD_POINTER * 4, \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) \ + REGISTER (64, 64, PT_THREAD_POINTER * 8, \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) + +/* Read member of the thread descriptor directly. */ +# define THREAD_GETMEM(descr, member) ((void)(descr), (THREAD_SELF)->member) + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +# define THREAD_GETMEM_NC(descr, member, idx) \ + ((void)(descr), (THREAD_SELF)->member[idx]) + +/* Set member of the thread descriptor directly. */ +# define THREAD_SETMEM(descr, member, value) \ + ((void)(descr), (THREAD_SELF)->member = (value)) + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +# define THREAD_SETMEM_NC(descr, member, idx, value) \ + ((void)(descr), (THREAD_SELF)->member[idx] = (value)) + +/* Set the stack guard field in TCB head. */ +# define THREAD_SET_STACK_GUARD(value) \ + (((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].stack_guard = (value)) +# define THREAD_COPY_STACK_GUARD(descr) \ + (((tcbhead_t *) ((char *) (descr) \ + + TLS_PRE_TCB_SIZE))[-1].stack_guard \ + = ((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].stack_guard) + +/* Set the stack guard field in TCB head. */ +# define THREAD_GET_POINTER_GUARD() \ + (((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].pointer_guard) +# define THREAD_SET_POINTER_GUARD(value) \ + (THREAD_GET_POINTER_GUARD () = (value)) +# define THREAD_COPY_POINTER_GUARD(descr) \ + (((tcbhead_t *) ((char *) (descr) \ + + TLS_PRE_TCB_SIZE))[-1].pointer_guard \ + = THREAD_GET_POINTER_GUARD()) + +/* l_tls_offset == 0 is perfectly valid on PPC, so we have to use some + 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, LLL_PRIVATE); \ + } \ + 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/libpthread/nptl/sysdeps/pthread/Makefile b/libpthread/nptl/sysdeps/pthread/Makefile new file mode 100644 index 000000000..a30ded527 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libpthread/nptl/sysdeps/pthread/Makefile.in b/libpthread/nptl/sysdeps/pthread/Makefile.in new file mode 100644 index 000000000..2a94e4315 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/Makefile.in @@ -0,0 +1,163 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005-2006 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +# +# NOTE: glibc puts flockfile.c, ftrylockfile.c, funlockfile.c, and +# pt-longjmp.c in libc and libpthread. For uClibc, they are +# in libc only. +# +libpthread_CSRC = pthread_barrier_init.c pthread_barrier_destroy.c \ + pthread_barrier_wait.c pthread_cond_broadcast.c \ + pthread_cond_signal.c pthread_cond_timedwait.c \ + pthread_cond_wait.c pthread_rwlock_rdlock.c \ + pthread_rwlock_timedrdlock.c \ + pthread_rwlock_timedwrlock.c pthread_rwlock_unlock.c \ + pthread_rwlock_wrlock.c pthread_sigmask.c \ + pthread_spin_destroy.c pthread_spin_init.c \ + pthread_spin_unlock.c pt-sigfillset.c \ + pt-longjmp.c tpp.c + + +ifeq ($(TARGET_ARCH),i386) +X86_PTHREAD_EXCLUDE_LIST = pthread_spin_unlock.c pthread_spin_init.c \ + pthread_barrier_wait.c pthread_cond_broadcast.c \ + pthread_cond_signal.c pthread_rwlock_timedrdlock.c \ + pthread_rwlock_timedwrlock.c pthread_rwlock_unlock.c pthread_rwlock_wrlock.c \ + pthread_rwlock_rdlock.c + +libpthread_CSRC := $(filter-out $(X86_PTHREAD_EXCLUDE_LIST),$(libpthread_CSRC)) +endif + +ifeq ($(TARGET_ARCH),sh) +SH_PTHREAD_EXCLUDE_LIST = pthread_spin_unlock.c pthread_spin_init.c \ + pthread_rwlock_wrlock.c pthread_rwlock_rdlock.c \ + pthread_rwlock_unlock.c pt-longjmp.c \ + pthread_barrier_wait.c pthread_cond_broadcast.c \ + pthread_cond_signal.c \ + pthread_rwlock_timedrdlock.c \ + pthread_rwlock_timedwrlock.c + +libpthread_CSRC := $(filter-out $(SH_PTHREAD_EXCLUDE_LIST),$(libpthread_CSRC)) +endif + +ifeq ($(TARGET_ARCH),sparc) +SPARC_PTHREAD_EXCLUDE_LIST = pthread_barrier_init.c pthread_barrier_wait.c \ + pthread_barrier_destroy.c + +libpthread_CSRC := $(filter-out $(SPARC_PTHREAD_EXCLUDE_LIST),$(libpthread_CSRC)) +endif + +ifeq ($(TARGET_ARCH),x86_64) +X64_PTHREAD_EXCLUDE_LIST = pthread_spin_unlock.c pthread_spin_init.c \ + pthread_barrier_wait.c pthread_cond_broadcast.c \ + pthread_cond_signal.c pthread_rwlock_timedrdlock.c \ + pthread_rwlock_timedwrlock.c pthread_rwlock_unlock.c pthread_rwlock_wrlock.c \ + pthread_rwlock_rdlock.c pthread_cond_timedwait.c pthread_cond_wait.c + +libpthread_CSRC := $(filter-out $(X64_PTHREAD_EXCLUDE_LIST),$(libpthread_CSRC)) +endif + + + +CFLAGS-pt-common = -DNOT_IN_libc=1 $(SSP_ALL_CFLAGS) +CFLAGS-pthread_barrier_init.c = $(CFLAGS-pt-common) -DIS_IN_libpthread=1 +CFLAGS-pthread_barrier_destroy.c = $(CFLAGS-pt-common) -DIS_IN_libpthread=1 +CFLAGS-pthread_barrier_wait.c = -D_GNU_SOURCE $(CFLAGS-pt-common) \ + -DIS_IN_libpthread=1 +CFLAGS-pthread_cond_broadcast.c = $(CFLAGS-pt-common) -DIS_IN_libpthread=1 +CFLAGS-pthread_cond_signal.c = $(CFLAGS-pt-common) -DIS_IN_libpthread=1 +CFLAGS-pthread_cond_timedwait.c = $(CFLAGS-pt-common) -DIS_IN_libpthread=1 +CFLAGS-pthread_cond_wait.c = $(CFLAGS-pt-common) -DIS_IN_libpthread=1 +CFLAGS-pthread_rwlock_rdlock.c = $(CFLAGS-pt-common) -DIS_IN_libpthread=1 +CFLAGS-pthread_rwlock_timedrdlock.c = $(CFLAGS-pt-common) -DIS_IN_libpthread=1 +CFLAGS-pthread_rwlock_timedwrlock.c = $(CFLAGS-pt-common) -DIS_IN_libpthread=1 +CFLAGS-pthread_rwlock_unlock.c = $(CFLAGS-pt-common) -DIS_IN_libpthread=1 +CFLAGS-pthread_rwlock_wrlock.c = $(CFLAGS-pt-common) -DIS_IN_libpthread=1 +CFLAGS-pthread_sigmask.c = $(CFLAGS-pt-common) -DIS_IN_libpthread=1 +CFLAGS-pthread_spin_destroy.c = -D_GNU_SOURCE $(CFLAGS-pt-common) \ + -DIS_IN_libpthread=1 +CFLAGS-pthread_spin_init.c = -D_GNU_SOURCE $(CFLAGS-pt-common) \ + -DIS_IN_libpthread=1 +CFLAGS-pthread_spin_unlock.c = -D_GNU_SOURCE $(CFLAGS-pt-common) \ + -DIS_IN_libpthread=1 +CFLAGS-pt-sigaction.c = $(CFLAGS-pt-common) -DIS_IN_libpthread=1 \ + -I$(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH) \ + -I$(top_srcdir)libc/signal +CFLAGS-pt-sigfillset.c = $(CFLAGS-pt-common) -DIS_IN_libpthread=1 \ + -I$(top_srcdir)libc/signal +CFLAGS-pt-sigprocmask.c = $(CFLAGS-pt-common) -DIS_IN_libpthread=1 \ + -I$(top_srcdir)libc/sysdeps/linux/common +CFLAGS-unwind-forcedunwind.c = $(CFLAGS-pt-common) -DIS_IN_libpthread=1 -fexceptions -fasynchronous-unwind-tables +CFLAGS-librt-cancellation.c = -DIS_IN_librt=1 $(CFLAGS-pt-common) \ + -fexceptions -fasynchronous-unwind-tables +CFLAGS-rt-unwind-resume.c = -DIS_IN_librt=1 $(CFLAGS-pt-common) \ + -fexceptions -fasynchronous-unwind-tables +CFLAGS-tpp.c = $(CFLAGS-pt-common) -DIS_IN_libpthread=1 + +#CFLAGS:=$(CFLAGS:-O1=-O2) + +pthread_DIR := $(top_srcdir)libpthread/nptl/sysdeps/pthread +pthread_OUT := $(top_builddir)libpthread/nptl/sysdeps/pthread + +pthread_SRC = $(patsubst %.c, $(pthread_DIR)/%.c, $(libpthread_CSRC)) +pthread_OBJ = $(patsubst %.c, $(pthread_OUT)/%.o, $(libpthread_CSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(pthread_OBJ:.o=.os) +else +libpthread-a-y += $(pthread_OBJ) +endif +libpthread-so-y += $(pthread_OBJ:.o=.oS) +libpthread-so-y += $(pthread_OUT)/pt-sigaction.oS $(pthread_OUT)/pt-sigprocmask.oS \ + $(pthread_OUT)/unwind-forcedunwind.oS + +CFLAGS-sigaction.c = -I$(top_srcdir)libc/signal +libc-y += $(pthread_OUT)/sigaction.o + +librt-a-y += $(pthread_OUT)/librt-cancellation.o +librt-so-y += $(pthread_OUT)/librt-cancellation.oS \ + $(pthread_OUT)/rt-unwind-resume.oS + +ifeq ($(UCLIBC_CTOR_DTOR),y) +CFLAGS-pt-initfini.c = -S -g0 -fPIC -fno-inline-functions \ + $(call check_gcc,-fno-unit-at-a-time,) \ + -finhibit-size-directive \ + $(patsubst -f%,-fno-%,$(call check_gcc,-fexceptions,)) +ASFLAGS-crti.S = -g0 +ASFLAGS-crtn.S = -g0 + +$(pthread_OUT)/pt-initfini.s: $(pthread_DIR)/pt-initfini.c + $(compile.c) + $(do_sed) '/@TESTS_BEGIN/,/@TESTS_END/p' $< | \ + $(AWK) -f $(pthread_DIR)/defs.awk > $(pthread_OUT)/defs.h + +$(pthread_OUT)/crti.S: $(pthread_OUT)/pt-initfini.s + $(do_sed) -e '1,/@HEADER_ENDS/p' \ + -e '/@_.*_PROLOG_BEGINS/,/@_.*_PROLOG_ENDS/p' \ + -e '/@TRAILER_BEGINS/,$$p' $< > $@ + +$(pthread_OUT)/crtn.S: $(pthread_OUT)/pt-initfini.s + $(do_sed) -e '1,/@HEADER_ENDS/p' \ + -e '/@_.*_EPILOG_BEGINS/,/@_.*_EPILOG_ENDS/p' \ + -e '/@TRAILER_BEGINS/,$$p' $< > $@ +endif + +$(pthread_DIR)/pt-sigaction.c: + $(LN) -s sigaction.c $@ + +$(pthread_DIR)/pt-sigfillset.c: + $(LN) -s sigfillset.c $@ + +$(pthread_DIR)/pt-sigprocmask.c: + $(LN) -s sigprocmask.c $@ + +objclean-y += nptl_pthread_clean + +nptl_pthread_clean: + $(do_rm) $(addprefix $(pthread_OUT)/*., o os oS s S) $(pthread_OUT)/defs.h \ + $(pthread_DIR)/pt-sigaction.c $(pthread_DIR)/pt-sigfillset.c \ + $(pthread_DIR)/pt-sigprocmask.c diff --git a/libpthread/nptl/sysdeps/pthread/allocalim.h b/libpthread/nptl/sysdeps/pthread/allocalim.h new file mode 100644 index 000000000..f13c3a330 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/allocalim.h @@ -0,0 +1,30 @@ +/* Determine whether block of given size can be allocated on the stack or not. + Copyright (C) 2002, 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. */ + +#include <alloca.h> +#include <limits.h> + + +extern int +__always_inline +__libc_use_alloca (size_t size) +{ + return (__builtin_expect (size <= PTHREAD_STACK_MIN / 4, 1) + || __libc_alloca_cutoff (size)); +} diff --git a/libpthread/nptl/sysdeps/pthread/bits/libc-lock.h b/libpthread/nptl/sysdeps/pthread/bits/libc-lock.h new file mode 100644 index 000000000..3268aa5f6 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/bits/libc-lock.h @@ -0,0 +1,586 @@ +/* libc-internal interface for mutex locks. NPTL version. + Copyright (C) 1996-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 + 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. */ + +#ifndef _BITS_LIBC_LOCK_H +#define _BITS_LIBC_LOCK_H 1 + +#include <pthread.h> +#define __need_NULL +#include <stddef.h> + + +/* Fortunately Linux now has a mean to do locking which is realtime + safe without the aid of the thread library. We also need no fancy + options like error checking mutexes etc. We only need simple + locks, maybe recursive. This can be easily and cheaply implemented + using futexes. We will use them everywhere except in ld.so since + ld.so might be used on old kernels with a different libc.so. */ +#ifdef _LIBC +# include <lowlevellock.h> +# include <tls.h> +# include <pthread-functions.h> +#endif + +/* Mutex type. */ +#if defined _LIBC || defined _IO_MTSAFE_IO +# if (defined NOT_IN_libc && !defined IS_IN_libpthread) || !defined _LIBC +typedef pthread_mutex_t __libc_lock_t; +typedef struct { pthread_mutex_t mutex; } __libc_lock_recursive_t; +# else +typedef int __libc_lock_t; +typedef struct { int lock; int cnt; void *owner; } __libc_lock_recursive_t; +# endif +typedef struct { pthread_mutex_t mutex; } __rtld_lock_recursive_t; +# ifdef __USE_UNIX98 +typedef pthread_rwlock_t __libc_rwlock_t; +# else +typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; +# endif +#else +typedef struct __libc_lock_opaque__ __libc_lock_t; +typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; +typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; +#endif + +/* Type for key to thread-specific data. */ +typedef pthread_key_t __libc_key_t; + +# define __libc_freeres_fn_section \ + __attribute__ ((section ("__libc_freeres_fn"))) + + +/* Define a lock variable NAME with storage class CLASS. The lock must be + initialized with __libc_lock_init before it can be used (or define it + with __libc_lock_define_initialized, below). Use `extern' for CLASS to + declare a lock defined in another module. In public structure + definitions you must use a pointer to the lock structure (i.e., NAME + begins with a `*'), because its storage size will not be known outside + of libc. */ +#define __libc_lock_define(CLASS,NAME) \ + CLASS __libc_lock_t NAME; +#define __libc_rwlock_define(CLASS,NAME) \ + CLASS __libc_rwlock_t NAME; +#define __libc_lock_define_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME; +#define __rtld_lock_define_recursive(CLASS,NAME) \ + CLASS __rtld_lock_recursive_t NAME; + +/* Define an initialized lock variable NAME with storage class CLASS. + + For the C library we take a deeper look at the initializer. For + this implementation all fields are initialized to zero. Therefore + we don't initialize the variable which allows putting it into the + BSS section. (Except on PA-RISC and other odd architectures, where + initialized locks must be set to one due to the lack of normal + atomic operations.) */ + +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# if LLL_LOCK_INITIALIZER == 0 +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME; +# else +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME = LLL_LOCK_INITIALIZER; +# endif +#else +# if __LT_SPINLOCK_INIT == 0 +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME; +# else +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER; +# endif +#endif + +#define __libc_rwlock_define_initialized(CLASS,NAME) \ + CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER; + +/* Define an initialized recursive lock variable NAME with storage + class CLASS. */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# if LLL_LOCK_INITIALIZER == 0 +# define __libc_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME; +# else +# define __libc_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER; +# endif +# define _LIBC_LOCK_RECURSIVE_INITIALIZER \ + { LLL_LOCK_INITIALIZER, 0, NULL } +#else +# define __libc_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER; +# define _LIBC_LOCK_RECURSIVE_INITIALIZER \ + {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} +#endif + +#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER; +#define _RTLD_LOCK_RECURSIVE_INITIALIZER \ + {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} + +#define __rtld_lock_initialize(NAME) \ + (void) ((NAME) = (__rtld_lock_recursive_t) _RTLD_LOCK_RECURSIVE_INITIALIZER) + +/* If we check for a weakly referenced symbol and then perform a + normal jump to it te code generated for some platforms in case of + PIC is unnecessarily slow. What would happen is that the function + is first referenced as data and then it is called indirectly + through the PLT. We can make this a direct jump. */ +#ifdef __PIC__ +# define __libc_maybe_call(FUNC, ARGS, ELSE) \ + (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \ + _fn != NULL ? (*_fn) ARGS : ELSE; })) +#else +# define __libc_maybe_call(FUNC, ARGS, ELSE) \ + (FUNC != NULL ? FUNC ARGS : ELSE) +#endif + +/* Call thread functions through the function pointer table. */ +#if defined SHARED && !defined NOT_IN_libc +# define PTFAVAIL(NAME) __libc_pthread_functions_init +# define __libc_ptf_call(FUNC, ARGS, ELSE) \ + (__libc_pthread_functions_init ? PTHFCT_CALL (ptr_##FUNC, ARGS) : ELSE) +# define __libc_ptf_call_always(FUNC, ARGS) \ + PTHFCT_CALL (ptr_##FUNC, ARGS) +#else +# define PTFAVAIL(NAME) (NAME != NULL) +# define __libc_ptf_call(FUNC, ARGS, ELSE) \ + __libc_maybe_call (FUNC, ARGS, ELSE) +# define __libc_ptf_call_always(FUNC, ARGS) \ + FUNC ARGS +#endif + + +/* Initialize the named lock variable, leaving it in a consistent, unlocked + state. */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_init(NAME) ((NAME) = LLL_LOCK_INITIALIZER, 0) +#else +# define __libc_lock_init(NAME) \ + __libc_maybe_call (__pthread_mutex_init, (&(NAME), NULL), 0) +#endif +#if defined SHARED && !defined NOT_IN_libc +/* ((NAME) = (__libc_rwlock_t) PTHREAD_RWLOCK_INITIALIZER, 0) is + inefficient. */ +# define __libc_rwlock_init(NAME) \ + (__builtin_memset (&(NAME), '\0', sizeof (NAME)), 0) +#else +# define __libc_rwlock_init(NAME) \ + __libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0) +#endif + +/* Same as last but this time we initialize a recursive mutex. */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_init_recursive(NAME) \ + ((NAME) = (__libc_lock_recursive_t) _LIBC_LOCK_RECURSIVE_INITIALIZER, 0) +#else +# define __libc_lock_init_recursive(NAME) \ + do { \ + if (__pthread_mutex_init != NULL) \ + { \ + pthread_mutexattr_t __attr; \ + __pthread_mutexattr_init (&__attr); \ + __pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \ + __pthread_mutex_init (&(NAME).mutex, &__attr); \ + __pthread_mutexattr_destroy (&__attr); \ + } \ + } while (0) +#endif + +#define __rtld_lock_init_recursive(NAME) \ + do { \ + if (__pthread_mutex_init != NULL) \ + { \ + pthread_mutexattr_t __attr; \ + __pthread_mutexattr_init (&__attr); \ + __pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \ + __pthread_mutex_init (&(NAME).mutex, &__attr); \ + __pthread_mutexattr_destroy (&__attr); \ + } \ + } while (0) + +/* Finalize the named lock variable, which must be locked. It cannot be + used again until __libc_lock_init is called again on it. This must be + called on a lock variable before the containing storage is reused. */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_fini(NAME) ((void) 0) +#else +# define __libc_lock_fini(NAME) \ + __libc_maybe_call (__pthread_mutex_destroy, (&(NAME)), 0) +#endif +#if defined SHARED && !defined NOT_IN_libc +# define __libc_rwlock_fini(NAME) ((void) 0) +#else +# define __libc_rwlock_fini(NAME) \ + __libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0) +#endif + +/* Finalize recursive named lock. */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_fini_recursive(NAME) ((void) 0) +#else +# define __libc_lock_fini_recursive(NAME) \ + __libc_maybe_call (__pthread_mutex_destroy, (&(NAME)), 0) +#endif + +/* Lock the named lock variable. */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_lock(NAME) \ + ({ lll_lock (NAME, LLL_PRIVATE); 0; }) +#else +# define __libc_lock_lock(NAME) \ + __libc_maybe_call (__pthread_mutex_lock, (&(NAME)), 0) +#endif +#define __libc_rwlock_rdlock(NAME) \ + __libc_ptf_call (__pthread_rwlock_rdlock, (&(NAME)), 0) +#define __libc_rwlock_wrlock(NAME) \ + __libc_ptf_call (__pthread_rwlock_wrlock, (&(NAME)), 0) + +/* Lock the recursive named lock variable. */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_lock_recursive(NAME) \ + do { \ + void *self = THREAD_SELF; \ + if ((NAME).owner != self) \ + { \ + lll_lock ((NAME).lock, LLL_PRIVATE); \ + (NAME).owner = self; \ + } \ + ++(NAME).cnt; \ + } while (0) +#else +# define __libc_lock_lock_recursive(NAME) \ + __libc_maybe_call (__pthread_mutex_lock, (&(NAME).mutex), 0) +#endif + +/* Try to lock the named lock variable. */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_trylock(NAME) \ + lll_trylock (NAME) +#else +# define __libc_lock_trylock(NAME) \ + __libc_maybe_call (__pthread_mutex_trylock, (&(NAME)), 0) +#endif +#define __libc_rwlock_tryrdlock(NAME) \ + __libc_maybe_call (__pthread_rwlock_tryrdlock, (&(NAME)), 0) +#define __libc_rwlock_trywrlock(NAME) \ + __libc_maybe_call (__pthread_rwlock_trywrlock, (&(NAME)), 0) + +/* Try to lock the recursive named lock variable. */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_trylock_recursive(NAME) \ + ({ \ + int result = 0; \ + void *self = THREAD_SELF; \ + if ((NAME).owner != self) \ + { \ + if (lll_trylock ((NAME).lock) == 0) \ + { \ + (NAME).owner = self; \ + (NAME).cnt = 1; \ + } \ + else \ + result = EBUSY; \ + } \ + else \ + ++(NAME).cnt; \ + result; \ + }) +#else +# define __libc_lock_trylock_recursive(NAME) \ + __libc_maybe_call (__pthread_mutex_trylock, (&(NAME)), 0) +#endif + +#define __rtld_lock_trylock_recursive(NAME) \ + __libc_maybe_call (__pthread_mutex_trylock, (&(NAME).mutex), 0) + +/* Unlock the named lock variable. */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_unlock(NAME) \ + lll_unlock (NAME, LLL_PRIVATE) +#else +# define __libc_lock_unlock(NAME) \ + __libc_maybe_call (__pthread_mutex_unlock, (&(NAME)), 0) +#endif +#define __libc_rwlock_unlock(NAME) \ + __libc_ptf_call (__pthread_rwlock_unlock, (&(NAME)), 0) + +/* Unlock the recursive named lock variable. */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +/* We do no error checking here. */ +# define __libc_lock_unlock_recursive(NAME) \ + do { \ + if (--(NAME).cnt == 0) \ + { \ + (NAME).owner = NULL; \ + lll_unlock ((NAME).lock, LLL_PRIVATE); \ + } \ + } while (0) +#else +# define __libc_lock_unlock_recursive(NAME) \ + __libc_maybe_call (__pthread_mutex_unlock, (&(NAME)), 0) +#endif + +#if defined _LIBC && defined SHARED +# define __rtld_lock_default_lock_recursive(lock) \ + ++((pthread_mutex_t *)(lock))->__data.__count; + +# define __rtld_lock_default_unlock_recursive(lock) \ + --((pthread_mutex_t *)(lock))->__data.__count; + +# define __rtld_lock_lock_recursive(NAME) \ + GL(dl_rtld_lock_recursive) (&(NAME).mutex) + +# define __rtld_lock_unlock_recursive(NAME) \ + GL(dl_rtld_unlock_recursive) (&(NAME).mutex) +#else +# define __rtld_lock_lock_recursive(NAME) \ + __libc_maybe_call (__pthread_mutex_lock, (&(NAME).mutex), 0) + +# define __rtld_lock_unlock_recursive(NAME) \ + __libc_maybe_call (__pthread_mutex_unlock, (&(NAME).mutex), 0) +#endif + +/* Define once control variable. */ +#if PTHREAD_ONCE_INIT == 0 +/* Special case for static variables where we can avoid the initialization + if it is zero. */ +# define __libc_once_define(CLASS, NAME) \ + CLASS pthread_once_t NAME +#else +# define __libc_once_define(CLASS, NAME) \ + CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT +#endif + +/* Call handler iff the first call. */ +#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \ + do { \ + if (PTFAVAIL (__pthread_once)) \ + __libc_ptf_call_always (__pthread_once, (&(ONCE_CONTROL), \ + INIT_FUNCTION)); \ + else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \ + INIT_FUNCTION (); \ + (ONCE_CONTROL) |= 2; \ + } \ + } while (0) + + +/* Note that for I/O cleanup handling we are using the old-style + cancel handling. It does not have to be integrated with C++ snce + no C++ code is called in the middle. The old-style handling is + faster and the support is not going away. */ +extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer, + void (*routine) (void *), void *arg); +extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer, + int execute); +extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer, + void (*routine) (void *), void *arg); +extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer, + int execute); + +/* Start critical region with cleanup. */ +#define __libc_cleanup_region_start(DOIT, FCT, ARG) \ + { struct _pthread_cleanup_buffer _buffer; \ + int _avail; \ + if (DOIT) { \ + _avail = PTFAVAIL (_pthread_cleanup_push_defer); \ + if (_avail) { \ + __libc_ptf_call_always (_pthread_cleanup_push_defer, (&_buffer, FCT, \ + ARG)); \ + } else { \ + _buffer.__routine = (FCT); \ + _buffer.__arg = (ARG); \ + } \ + } else { \ + _avail = 0; \ + } + +/* End critical region with cleanup. */ +#define __libc_cleanup_region_end(DOIT) \ + if (_avail) { \ + __libc_ptf_call_always (_pthread_cleanup_pop_restore, (&_buffer, DOIT));\ + } else if (DOIT) \ + _buffer.__routine (_buffer.__arg); \ + } + +/* Sometimes we have to exit the block in the middle. */ +#define __libc_cleanup_end(DOIT) \ + if (_avail) { \ + __libc_ptf_call_always (_pthread_cleanup_pop_restore, (&_buffer, DOIT));\ + } else if (DOIT) \ + _buffer.__routine (_buffer.__arg) + + +/* Normal cleanup handling, based on C cleanup attribute. */ +__extern_inline void +__libc_cleanup_routine (struct __pthread_cleanup_frame *f) +{ + if (f->__do_it) + f->__cancel_routine (f->__cancel_arg); +} + +#define __libc_cleanup_push(fct, arg) \ + do { \ + struct __pthread_cleanup_frame __clframe \ + __attribute__ ((__cleanup__ (__libc_cleanup_routine))) \ + = { .__cancel_routine = (fct), .__cancel_arg = (arg), \ + .__do_it = 1 }; + +#define __libc_cleanup_pop(execute) \ + __clframe.__do_it = (execute); \ + } while (0) + + +/* Create thread-specific key. */ +#define __libc_key_create(KEY, DESTRUCTOR) \ + __libc_ptf_call (__pthread_key_create, (KEY, DESTRUCTOR), 1) + +/* Get thread-specific data. */ +#define __libc_getspecific(KEY) \ + __libc_ptf_call (__pthread_getspecific, (KEY), NULL) + +/* Set thread-specific data. */ +#define __libc_setspecific(KEY, VALUE) \ + __libc_ptf_call (__pthread_setspecific, (KEY, VALUE), 0) + + +/* Register handlers to execute before and after `fork'. Note that the + last parameter is NULL. The handlers registered by the libc are + never removed so this is OK. */ +#define __libc_atfork(PREPARE, PARENT, CHILD) \ + __register_atfork (PREPARE, PARENT, CHILD, NULL) +extern int __register_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void), + void *__dso_handle); + +/* Functions that are used by this file and are internal to the GNU C + library. */ + +extern int __pthread_mutex_init (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutex_attr); + +extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); + +extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr); + +extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr); + +extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr, + int __kind); + +#ifdef __USE_UNIX98 +extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock, + __const pthread_rwlockattr_t *__attr); + +extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock); +#endif + +extern int __pthread_key_create (pthread_key_t *__key, + void (*__destr_function) (void *)); + +extern int __pthread_setspecific (pthread_key_t __key, + __const void *__pointer); + +extern void *__pthread_getspecific (pthread_key_t __key); + +extern int __pthread_once (pthread_once_t *__once_control, + void (*__init_routine) (void)); + +extern int __pthread_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void)); + + + +/* Make the pthread functions weak so that we can elide them from + single-threaded processes. */ +#ifndef __NO_WEAK_PTHREAD_ALIASES +# ifdef weak_extern +weak_extern (__pthread_mutex_init) +weak_extern (__pthread_mutex_destroy) +weak_extern (__pthread_mutex_lock) +weak_extern (__pthread_mutex_trylock) +weak_extern (__pthread_mutex_unlock) +weak_extern (__pthread_mutexattr_init) +weak_extern (__pthread_mutexattr_destroy) +weak_extern (__pthread_mutexattr_settype) +weak_extern (__pthread_rwlock_init) +weak_extern (__pthread_rwlock_destroy) +weak_extern (__pthread_rwlock_rdlock) +weak_extern (__pthread_rwlock_tryrdlock) +weak_extern (__pthread_rwlock_wrlock) +weak_extern (__pthread_rwlock_trywrlock) +weak_extern (__pthread_rwlock_unlock) +weak_extern (__pthread_key_create) +weak_extern (__pthread_setspecific) +weak_extern (__pthread_getspecific) +weak_extern (__pthread_once) +//weak_extern (__pthread_initialize) +weak_extern (__pthread_atfork) +#ifdef SHARED +weak_extern (_pthread_cleanup_push_defer) +weak_extern (_pthread_cleanup_pop_restore) +#endif +weak_extern (pthread_setcancelstate) +# else +# pragma weak __pthread_mutex_init +# pragma weak __pthread_mutex_destroy +# pragma weak __pthread_mutex_lock +# pragma weak __pthread_mutex_trylock +# pragma weak __pthread_mutex_unlock +# pragma weak __pthread_mutexattr_init +# pragma weak __pthread_mutexattr_destroy +# pragma weak __pthread_mutexattr_settype +# pragma weak __pthread_rwlock_destroy +# pragma weak __pthread_rwlock_rdlock +# pragma weak __pthread_rwlock_tryrdlock +# pragma weak __pthread_rwlock_wrlock +# pragma weak __pthread_rwlock_trywrlock +# pragma weak __pthread_rwlock_unlock +# pragma weak __pthread_key_create +# pragma weak __pthread_setspecific +# pragma weak __pthread_getspecific +# pragma weak __pthread_once +//# pragma weak __pthread_initialize +# pragma weak __pthread_atfork +# pragma weak _pthread_cleanup_push_defer +# pragma weak _pthread_cleanup_pop_restore +# pragma weak pthread_setcancelstate +# endif +#endif + +#endif /* bits/libc-lock.h */ diff --git a/libpthread/nptl/sysdeps/pthread/bits/libc-tsd.h b/libpthread/nptl/sysdeps/pthread/bits/libc-tsd.h new file mode 100644 index 000000000..3f1676b3e --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/bits/libc-tsd.h @@ -0,0 +1,69 @@ +/* libc-internal interface for thread-specific data. Stub or TLS version. + Copyright (C) 1998,2001,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _GENERIC_BITS_LIBC_TSD_H +#define _GENERIC_BITS_LIBC_TSD_H 1 + +/* This file defines the following macros for accessing a small fixed + set of thread-specific `void *' data used only internally by libc. + + __libc_tsd_define(CLASS, KEY) -- Define or declare a `void *' datum + for KEY. CLASS can be `static' for + keys used in only one source file, + empty for global definitions, or + `extern' for global declarations. + __libc_tsd_address(KEY) -- Return the `void **' pointing to + the current thread's datum for KEY. + __libc_tsd_get(KEY) -- Return the `void *' datum for KEY. + __libc_tsd_set(KEY, VALUE) -- Set the datum for KEY to VALUE. + + The set of available KEY's will usually be provided as an enum, + and contains (at least): + _LIBC_TSD_KEY_MALLOC + _LIBC_TSD_KEY_DL_ERROR + _LIBC_TSD_KEY_RPC_VARS + All uses must be the literal _LIBC_TSD_* name in the __libc_tsd_* macros. + Some implementations may not provide any enum at all and instead + using string pasting in the macros. */ + +#include <tls.h> + +/* When full support for __thread variables is available, this interface is + just a trivial wrapper for it. Without TLS, this is the generic/stub + implementation for wholly single-threaded systems. + + We don't define an enum for the possible key values, because the KEYs + translate directly into variables by macro magic. */ + +#if USE___THREAD +# define __libc_tsd_define(CLASS, KEY) \ + CLASS __thread void *__libc_tsd_##KEY attribute_tls_model_ie; + +# define __libc_tsd_address(KEY) (&__libc_tsd_##KEY) +# define __libc_tsd_get(KEY) (__libc_tsd_##KEY) +# define __libc_tsd_set(KEY, VALUE) (__libc_tsd_##KEY = (VALUE)) +#else +# define __libc_tsd_define(CLASS, KEY) CLASS void *__libc_tsd_##KEY##_data; + +# define __libc_tsd_address(KEY) (&__libc_tsd_##KEY##_data) +# define __libc_tsd_get(KEY) (__libc_tsd_##KEY##_data) +# define __libc_tsd_set(KEY, VALUE) (__libc_tsd_##KEY##_data = (VALUE)) +#endif + +#endif /* bits/libc-tsd.h */ diff --git a/libpthread/nptl/sysdeps/pthread/bits/sigthread.h b/libpthread/nptl/sysdeps/pthread/bits/sigthread.h new file mode 100644 index 000000000..9a524e57d --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/bits/sigthread.h @@ -0,0 +1,44 @@ +/* Signal handling function for threaded programs. + Copyright (C) 1998, 1999, 2000, 2002, 2009 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. */ + +#ifndef _BITS_SIGTHREAD_H +#define _BITS_SIGTHREAD_H 1 + +#if !defined _SIGNAL_H && !defined _PTHREAD_H +# error "Never include this file directly. Use <pthread.h> instead" +#endif + +/* Functions for handling signals. */ + +/* Modify the signal mask for the calling thread. The arguments have + the same meaning as for sigprocmask(2). */ +extern int pthread_sigmask (int __how, + __const __sigset_t *__restrict __newmask, + __sigset_t *__restrict __oldmask)__THROW; + +/* Send signal SIGNO to the given thread. */ +extern int pthread_kill (pthread_t __threadid, int __signo) __THROW; + +#ifdef __USE_GNU +/* Queue signal and data to a thread. */ +extern int pthread_sigqueue (pthread_t __threadid, int __signo, + const union sigval __value) __THROW; +#endif + +#endif /* bits/sigthread.h */ diff --git a/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h b/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h new file mode 100644 index 000000000..b8efdd8d5 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h @@ -0,0 +1,111 @@ +/* Thread package specific definitions of stream lock type. NPTL version. + Copyright (C) 2000, 2001, 2002, 2003, 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 + 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. */ + +#ifndef _BITS_STDIO_LOCK_H +#define _BITS_STDIO_LOCK_H 1 + +#include <bits/libc-lock.h> +#include <lowlevellock.h> + + +/* The locking here is very inexpensive, even for inlining. */ +#define _IO_lock_inexpensive 1 + +typedef struct { int lock; int cnt; void *owner; } _IO_lock_t; + +#define _IO_lock_initializer { LLL_LOCK_INITIALIZER, 0, NULL } + +#define _IO_lock_init(_name) \ + ((_name) = (_IO_lock_t) _IO_lock_initializer , 0) + +#define _IO_lock_fini(_name) \ + ((void) 0) + +#define _IO_lock_lock(_name) \ + do { \ + void *__self = THREAD_SELF; \ + if ((_name).owner != __self) \ + { \ + lll_lock ((_name).lock, LLL_PRIVATE); \ + (_name).owner = __self; \ + } \ + ++(_name).cnt; \ + } while (0) + +#define _IO_lock_trylock(_name) \ + ({ \ + int __result = 0; \ + void *__self = THREAD_SELF; \ + if ((_name).owner != __self) \ + { \ + if (lll_trylock ((_name).lock) == 0) \ + { \ + (_name).owner = __self; \ + (_name).cnt = 1; \ + } \ + else \ + __result = EBUSY; \ + } \ + else \ + ++(_name).cnt; \ + __result; \ + }) + +#define _IO_lock_unlock(_name) \ + do { \ + if (--(_name).cnt == 0) \ + { \ + (_name).owner = NULL; \ + lll_unlock ((_name).lock, LLL_PRIVATE); \ + } \ + } while (0) + + + +#define _IO_cleanup_region_start(_fct, _fp) \ + __libc_cleanup_region_start (((_fp)->_flags & _IO_USER_LOCK) == 0, _fct, _fp) +#define _IO_cleanup_region_start_noarg(_fct) \ + __libc_cleanup_region_start (1, _fct, NULL) +#define _IO_cleanup_region_end(_doit) \ + __libc_cleanup_region_end (_doit) + +#if defined _LIBC && !defined NOT_IN_libc + +# ifdef __EXCEPTIONS +# define _IO_acquire_lock(_fp) \ + do { \ + _IO_FILE *_IO_acquire_lock_file \ + __attribute__((cleanup (_IO_acquire_lock_fct))) \ + = (_fp); \ + _IO_flockfile (_IO_acquire_lock_file); +# define _IO_acquire_lock_clear_flags2(_fp) \ + do { \ + _IO_FILE *_IO_acquire_lock_file \ + __attribute__((cleanup (_IO_acquire_lock_clear_flags2_fct))) \ + = (_fp); \ + _IO_flockfile (_IO_acquire_lock_file); +# else +# define _IO_acquire_lock(_fp) _IO_acquire_lock_needs_exceptions_enabled +# define _IO_acquire_lock_clear_flags2(_fp) _IO_acquire_lock (_fp) +# endif +# define _IO_release_lock(_fp) ; } while (0) + +#endif + +#endif /* bits/stdio-lock.h */ diff --git a/libpthread/nptl/sysdeps/pthread/createthread.c b/libpthread/nptl/sysdeps/pthread/createthread.c new file mode 100644 index 000000000..a676e277f --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/createthread.c @@ -0,0 +1,257 @@ +/* Copyright (C) 2002-2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sched.h> +#include <setjmp.h> +#include <signal.h> +#include <stdlib.h> +#include <atomic.h> +#include <ldsodefs.h> +#include <tls.h> + +#include <bits/kernel-features.h> + + +#define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD) + +/* Unless otherwise specified, the thread "register" is going to be + initialized with a pointer to the TCB. */ +#ifndef TLS_VALUE +# define TLS_VALUE pd +#endif + +#ifndef ARCH_CLONE +# define ARCH_CLONE __clone +#endif + + +#ifndef TLS_MULTIPLE_THREADS_IN_TCB +/* Pointer to the corresponding variable in libc. */ +int *__libc_multiple_threads_ptr attribute_hidden; +#endif + + +static int +do_clone (struct pthread *pd, const struct pthread_attr *attr, + int clone_flags, int (*fct) (void *), STACK_VARIABLES_PARMS, + int stopped) +{ +#ifdef PREPARE_CREATE + PREPARE_CREATE; +#endif + + if (__builtin_expect (stopped != 0, 0)) + /* We make sure the thread does not run far by forcing it to get a + lock. We lock it here too so that the new thread cannot continue + until we tell it to. */ + lll_lock (pd->lock, LLL_PRIVATE); + + /* One more thread. We cannot have the thread do this itself, since it + might exist but not have been scheduled yet by the time we've returned + and need to check the value to behave correctly. We must do it before + creating the thread, in case it does get scheduled first and then + might mistakenly think it was the only thread. In the failure case, + we momentarily store a false value; this doesn't matter because there + is no kosher thing a signal handler interrupting us right here can do + that cares whether the thread count is correct. */ + atomic_increment (&__nptl_nthreads); + + if (ARCH_CLONE (fct, STACK_VARIABLES_ARGS, clone_flags, + pd, &pd->tid, TLS_VALUE, &pd->tid) == -1) + { + atomic_decrement (&__nptl_nthreads); /* Oops, we lied for a second. */ + + /* Failed. If the thread is detached, remove the TCB here since + the caller cannot do this. The caller remembered the thread + as detached and cannot reverify that it is not since it must + not access the thread descriptor again. */ + if (IS_DETACHED (pd)) + __deallocate_stack (pd); + + /* We have to translate error codes. */ + return errno == ENOMEM ? EAGAIN : errno; + } + + /* Now we have the possibility to set scheduling parameters etc. */ + if (__builtin_expect (stopped != 0, 0)) + { + INTERNAL_SYSCALL_DECL (err); + int res = 0; + + /* Set the affinity mask if necessary. */ + if (attr->cpuset != NULL) + { + res = INTERNAL_SYSCALL (sched_setaffinity, err, 3, pd->tid, + attr->cpusetsize, attr->cpuset); + + if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0)) + { + /* The operation failed. We have to kill the thread. First + send it the cancellation signal. */ + INTERNAL_SYSCALL_DECL (err2); + err_out: +#if __ASSUME_TGKILL + (void) INTERNAL_SYSCALL (tgkill, err2, 3, + THREAD_GETMEM (THREAD_SELF, pid), + pd->tid, SIGCANCEL); +#else + (void) INTERNAL_SYSCALL (tkill, err2, 2, pd->tid, SIGCANCEL); +#endif + + return (INTERNAL_SYSCALL_ERROR_P (res, err) + ? INTERNAL_SYSCALL_ERRNO (res, err) + : 0); + } + } + + /* Set the scheduling parameters. */ + if ((attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0) + { + res = INTERNAL_SYSCALL (sched_setscheduler, err, 3, pd->tid, + pd->schedpolicy, &pd->schedparam); + + if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0)) + goto err_out; + } + } + + /* We now have for sure more than one thread. The main thread might + not yet have the flag set. No need to set the global variable + again if this is what we use. */ + THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1); + + return 0; +} + + +static int +create_thread (struct pthread *pd, const struct pthread_attr *attr, + STACK_VARIABLES_PARMS) +{ +#ifdef TLS_TCB_AT_TP + assert (pd->header.tcb != NULL); +#endif + + /* We rely heavily on various flags the CLONE function understands: + + CLONE_VM, CLONE_FS, CLONE_FILES + These flags select semantics with shared address space and + file descriptors according to what POSIX requires. + + CLONE_SIGNAL + This flag selects the POSIX signal semantics. + + CLONE_SETTLS + The sixth parameter to CLONE determines the TLS area for the + new thread. + + CLONE_PARENT_SETTID + The kernels writes the thread ID of the newly created thread + into the location pointed to by the fifth parameters to CLONE. + + Note that it would be semantically equivalent to use + CLONE_CHILD_SETTID but it is be more expensive in the kernel. + + CLONE_CHILD_CLEARTID + The kernels clears the thread ID of a thread that has called + sys_exit() in the location pointed to by the seventh parameter + to CLONE. + + CLONE_DETACHED + No signal is generated if the thread exists and it is + automatically reaped. + + The termination signal is chosen to be zero which means no signal + is sent. */ + int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL + | CLONE_SETTLS | CLONE_PARENT_SETTID + | CLONE_CHILD_CLEARTID | CLONE_SYSVSEM +#if __ASSUME_NO_CLONE_DETACHED == 0 + | CLONE_DETACHED +#endif + | 0); + + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, report_events), 0)) + { + /* The parent thread is supposed to report events. Check whether + the TD_CREATE event is needed, too. */ + const int _idx = __td_eventword (TD_CREATE); + const uint32_t _mask = __td_eventmask (TD_CREATE); + + if ((_mask & (__nptl_threads_events.event_bits[_idx] + | pd->eventbuf.eventmask.event_bits[_idx])) != 0) + { + /* We always must have the thread start stopped. */ + pd->stopped_start = true; + + /* Create the thread. We always create the thread stopped + so that it does not get far before we tell the debugger. */ + int res = do_clone (pd, attr, clone_flags, start_thread, + STACK_VARIABLES_ARGS, 1); + if (res == 0) + { + /* Now fill in the information about the new thread in + the newly created thread's data structure. We cannot let + the new thread do this since we don't know whether it was + already scheduled when we send the event. */ + pd->eventbuf.eventnum = TD_CREATE; + pd->eventbuf.eventdata = pd; + + /* Enqueue the descriptor. */ + do + pd->nextevent = __nptl_last_event; + while (atomic_compare_and_exchange_bool_acq (&__nptl_last_event, + pd, pd->nextevent) + != 0); + + /* Now call the function which signals the event. */ + __nptl_create_event (); + + /* And finally restart the new thread. */ + lll_unlock (pd->lock, LLL_PRIVATE); + } + + return res; + } + } + +#ifdef NEED_DL_SYSINFO + assert (THREAD_SELF_SYSINFO == THREAD_SYSINFO (pd)); +#endif + + /* Determine whether the newly created threads has to be started + stopped since we have to set the scheduling parameters or set the + affinity. */ + bool stopped = false; + if (attr != NULL && (attr->cpuset != NULL + || (attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0)) + stopped = true; + pd->stopped_start = stopped; + pd->parent_cancelhandling = THREAD_GETMEM (THREAD_SELF, cancelhandling); + + /* Actually create the thread. */ + int res = do_clone (pd, attr, clone_flags, start_thread, + STACK_VARIABLES_ARGS, stopped); + + if (res == 0 && stopped) + /* And finally restart the new thread. */ + lll_unlock (pd->lock, LLL_PRIVATE); + + return res; +} diff --git a/libpthread/nptl/sysdeps/pthread/defs.awk b/libpthread/nptl/sysdeps/pthread/defs.awk new file mode 100644 index 000000000..d41d57bd7 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/defs.awk @@ -0,0 +1,24 @@ +/^[ ]*\.endp/ { need_endp = 1 } +/^[ ]*\.end/ { need_end = 1 } +/^[ ]*\.align/ { if($2 > max) max = $2; } + +END { + if(need_endp) + { + print "#define END_INIT .endp _init"; + print "#define END_FINI .endp _fini"; + } else if(need_end) + { + print "#define END_INIT .end _init"; + print "#define END_FINI .end _fini"; + } + else + { + print "#define END_INIT"; + print "#define END_FINI"; + } + if(max) + print "#define ALIGN .align", max; + else + print "#define ALIGN"; +} diff --git a/libpthread/nptl/sysdeps/pthread/librt-cancellation.c b/libpthread/nptl/sysdeps/pthread/librt-cancellation.c new file mode 100644 index 000000000..ad189e81a --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/librt-cancellation.c @@ -0,0 +1,25 @@ +/* Copyright (C) 2002, 2003, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +#define __pthread_enable_asynccancel __librt_enable_asynccancel +#define __pthread_disable_asynccancel __librt_disable_asynccancel +#include "cancellation.c" diff --git a/libpthread/nptl/sysdeps/pthread/list.h b/libpthread/nptl/sysdeps/pthread/list.h new file mode 100644 index 000000000..6ddccb9fb --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/list.h @@ -0,0 +1,103 @@ +/* Copyright (C) 2002, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LIST_H +#define _LIST_H 1 + +/* The definitions of this file are adopted from those which can be + found in the Linux kernel headers to enable people familiar with + the latter find their way in these sources as well. */ + + +/* Basic type for the double-link list. */ +typedef struct list_head +{ + struct list_head *next; + struct list_head *prev; +} list_t; + + +/* Define a variable with the head and tail of the list. */ +#define LIST_HEAD(name) \ + list_t name = { &(name), &(name) } + +/* Initialize a new list head. */ +#define INIT_LIST_HEAD(ptr) \ + (ptr)->next = (ptr)->prev = (ptr) + + +/* Add new element at the head of the list. */ +static inline void +list_add (list_t *newp, list_t *head) +{ + newp->next = head->next; + newp->prev = head; + head->next->prev = newp; + head->next = newp; +} + + +/* Remove element from list. */ +static inline void +list_del (list_t *elem) +{ + elem->next->prev = elem->prev; + elem->prev->next = elem->next; +} + + +/* Join two lists. */ +static inline void +list_splice (list_t *add, list_t *head) +{ + /* Do nothing if the list which gets added is empty. */ + if (add != add->next) + { + add->next->prev = head; + add->prev->next = head->next; + head->next->prev = add->prev; + head->next = add->next; + } +} + + +/* Get typed element from list at a given position. */ +#define list_entry(ptr, type, member) \ + ((type *) ((char *) (ptr) - (unsigned long) (&((type *) 0)->member))) + + + +/* Iterate forward over the elements of the list. */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + + +/* Iterate forward over the elements of the list. */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); pos = pos->prev) + + +/* Iterate backwards over the elements list. The list elements can be + removed from the list while doing this. */ +#define list_for_each_prev_safe(pos, p, head) \ + for (pos = (head)->prev, p = pos->prev; \ + pos != (head); \ + pos = p, p = pos->prev) + +#endif /* list.h */ diff --git a/libpthread/nptl/sysdeps/pthread/malloc-machine.h b/libpthread/nptl/sysdeps/pthread/malloc-machine.h new file mode 100644 index 000000000..e99aaa781 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/malloc-machine.h @@ -0,0 +1,73 @@ +/* Basic platform-independent macro definitions for mutexes, + thread-specific data and parameters for malloc. + Copyright (C) 2003, 2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MALLOC_MACHINE_H +#define _MALLOC_MACHINE_H + +#undef thread_atfork_static + +#include <atomic.h> +#include <bits/libc-lock.h> + +__libc_lock_define (typedef, mutex_t) + +#define mutex_init(m) __libc_lock_init (*(m)) +#define mutex_lock(m) __libc_lock_lock (*(m)) +#define mutex_trylock(m) __libc_lock_trylock (*(m)) +#define mutex_unlock(m) __libc_lock_unlock (*(m)) + +/* This is defined by newer gcc version unique for each module. */ +extern void *__dso_handle __attribute__ ((__weak__)); + +#include <fork.h> + +#define ATFORK_MEM static struct fork_handler atfork_mem + +#ifdef SHARED +# define thread_atfork(prepare, parent, child) \ + atfork_mem.prepare_handler = prepare; \ + atfork_mem.parent_handler = parent; \ + atfork_mem.child_handler = child; \ + atfork_mem.dso_handle = __dso_handle; \ + atfork_mem.refcntr = 1; \ + __linkin_atfork (&atfork_mem) +#else +# define thread_atfork(prepare, parent, child) \ + atfork_mem.prepare_handler = prepare; \ + atfork_mem.parent_handler = parent; \ + atfork_mem.child_handler = child; \ + atfork_mem.dso_handle = &__dso_handle == NULL ? NULL : __dso_handle; \ + atfork_mem.refcntr = 1; \ + __linkin_atfork (&atfork_mem) +#endif + +/* thread specific data for glibc */ + +#include <bits/libc-tsd.h> + +typedef int tsd_key_t[1]; /* no key data structure, libc magic does it */ +__libc_tsd_define (static, void *, MALLOC) /* declaration/common definition */ +#define tsd_key_create(key, destr) ((void) (key)) +#define tsd_setspecific(key, data) __libc_tsd_set (void *, MALLOC, (data)) +#define tsd_getspecific(key, vptr) ((vptr) = __libc_tsd_get (void *, MALLOC)) + +#include <sysdeps/generic/malloc-machine.h> + +#endif /* !defined(_MALLOC_MACHINE_H) */ diff --git a/libpthread/nptl/sysdeps/pthread/posix-timer.h b/libpthread/nptl/sysdeps/pthread/posix-timer.h new file mode 100644 index 000000000..8b4cbc8cd --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/posix-timer.h @@ -0,0 +1,197 @@ +/* Definitions for POSIX timer implementation on top of NPTL. + Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku <kaz@ashi.footprints.net>. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <limits.h> +#include <signal.h> + +/* Double linked list. */ +struct list_links +{ + struct list_links *next; + struct list_links *prev; +}; + + +/* Forward declaration. */ +struct timer_node; + + +/* Definitions for an internal thread of the POSIX timer implementation. */ +struct thread_node +{ + struct list_links links; + pthread_attr_t attr; + pthread_t id; + unsigned int exists; + struct list_links timer_queue; + pthread_cond_t cond; + struct timer_node *current_timer; + pthread_t captured; + clockid_t clock_id; +}; + + +/* Internal representation of a timer. */ +struct timer_node +{ + struct list_links links; + struct sigevent event; + clockid_t clock; + struct itimerspec value; + struct timespec expirytime; + pthread_attr_t attr; + unsigned int abstime; + unsigned int armed; + enum { + TIMER_FREE, TIMER_INUSE, TIMER_DELETED + } inuse; + struct thread_node *thread; + pid_t creator_pid; + int refcount; + int overrun_count; +}; + + +/* The limit is not published if we are compiled with kernel timer support. + But we still compiled in this implementation with its limit unless built + to require the kernel support. */ +#ifndef TIMER_MAX +# define TIMER_MAX 256 +#endif + +/* Static array with the structures for all the timers. */ +extern struct timer_node __timer_array[TIMER_MAX]; + +/* Global lock to protect operation on the lists. */ +extern pthread_mutex_t __timer_mutex; + +/* Variable to protext initialization. */ +extern pthread_once_t __timer_init_once_control; + +/* Nonzero if initialization of timer implementation failed. */ +extern int __timer_init_failed; + +/* Node for the thread used to deliver signals. */ +extern struct thread_node __timer_signal_thread_rclk; + + +/* Return pointer to timer structure corresponding to ID. */ +#define timer_id2ptr(timerid) ((struct timer_node *) timerid) +#define timer_ptr2id(timerid) ((void *) timerid) + +/* Check whether timer is valid; global mutex must be held. */ +static inline int +timer_valid (struct timer_node *timer) +{ + return timer && timer->inuse == TIMER_INUSE; +} + +/* Timer refcount functions; need global mutex. */ +extern void __timer_dealloc (struct timer_node *timer); + +static inline void +timer_addref (struct timer_node *timer) +{ + timer->refcount++; +} + +static inline void +timer_delref (struct timer_node *timer) +{ + if (--timer->refcount == 0) + __timer_dealloc (timer); +} + +/* Timespec helper routines. */ +static inline int +__attribute ((always_inline)) +timespec_compare (const struct timespec *left, const struct timespec *right) +{ + if (left->tv_sec < right->tv_sec) + return -1; + if (left->tv_sec > right->tv_sec) + return 1; + + if (left->tv_nsec < right->tv_nsec) + return -1; + if (left->tv_nsec > right->tv_nsec) + return 1; + + return 0; +} + +static inline void +timespec_add (struct timespec *sum, const struct timespec *left, + const struct timespec *right) +{ + sum->tv_sec = left->tv_sec + right->tv_sec; + sum->tv_nsec = left->tv_nsec + right->tv_nsec; + + if (sum->tv_nsec >= 1000000000) + { + ++sum->tv_sec; + sum->tv_nsec -= 1000000000; + } +} + +static inline void +timespec_sub (struct timespec *diff, const struct timespec *left, + const struct timespec *right) +{ + diff->tv_sec = left->tv_sec - right->tv_sec; + diff->tv_nsec = left->tv_nsec - right->tv_nsec; + + if (diff->tv_nsec < 0) + { + --diff->tv_sec; + diff->tv_nsec += 1000000000; + } +} + + +/* We need one of the list functions in the other modules. */ +static inline void +list_unlink_ip (struct list_links *list) +{ + struct list_links *lnext = list->next, *lprev = list->prev; + + lnext->prev = lprev; + lprev->next = lnext; + + /* The suffix ip means idempotent; list_unlink_ip can be called + * two or more times on the same node. + */ + + list->next = list; + list->prev = list; +} + + +/* Functions in the helper file. */ +extern void __timer_mutex_cancel_handler (void *arg); +extern void __timer_init_once (void); +extern struct timer_node *__timer_alloc (void); +extern int __timer_thread_start (struct thread_node *thread); +extern struct thread_node *__timer_thread_find_matching (const pthread_attr_t *desired_attr, clockid_t); +extern struct thread_node *__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t); +extern void __timer_thread_dealloc (struct thread_node *thread); +extern int __timer_thread_queue_timer (struct thread_node *thread, + struct timer_node *insert); +extern void __timer_thread_wakeup (struct thread_node *thread); diff --git a/libpthread/nptl/sysdeps/pthread/pt-initfini.c b/libpthread/nptl/sysdeps/pthread/pt-initfini.c new file mode 100644 index 000000000..b26a50456 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pt-initfini.c @@ -0,0 +1,125 @@ +/* Special .init and .fini section support. Linuxthread version. + Copyright (C) 1995,1996,1997,2000,2001,2002 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 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Library General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + 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, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +#include <stdlib.h> + +/* We use embedded asm for .section unconditionally, as this makes it + easier to insert the necessary directives into crtn.S. */ +#define SECTION(x) __asm__ (".section " x ) + +/* Embed an #include to pull in the alignment and .end directives. */ +asm ("\n#include \"defs.h\""); + +/* The initial common code ends here. */ +asm ("\n/*@HEADER_ENDS*/"); + +/* To determine whether we need .end and .align: */ +asm ("\n/*@TESTS_BEGIN*/"); +extern void dummy (void (*foo) (void)); +void +dummy (void (*foo) (void)) +{ + if (foo) + (*foo) (); +} +asm ("\n/*@TESTS_END*/"); + +/* The beginning of _init: */ +asm ("\n/*@_init_PROLOG_BEGINS*/"); + +static void +call_initialize_minimal (void) +{ + extern void __pthread_initialize_minimal_internal (void) + __attribute ((visibility ("hidden"))); + + __pthread_initialize_minimal_internal (); +} + +SECTION (".init"); +extern void __attribute__ ((section (".init"))) _init (void); +void +_init (void) +{ + /* The very first thing we must do is to set up the registers. */ + call_initialize_minimal (); + + asm ("ALIGN"); + asm("END_INIT"); + /* Now the epilog. */ + asm ("\n/*@_init_PROLOG_ENDS*/"); + asm ("\n/*@_init_EPILOG_BEGINS*/"); + SECTION(".init"); +} +asm ("END_INIT"); + +/* End of the _init epilog, beginning of the _fini prolog. */ +asm ("\n/*@_init_EPILOG_ENDS*/"); +asm ("\n/*@_fini_PROLOG_BEGINS*/"); + +SECTION (".fini"); +extern void __attribute__ ((section (".fini"))) _fini (void); +void +_fini (void) +{ + + /* End of the _fini prolog. */ + asm ("ALIGN"); + asm ("END_FINI"); + asm ("\n/*@_fini_PROLOG_ENDS*/"); + + { + /* Let GCC know that _fini is not a leaf function by having a dummy + function call here. We arrange for this call to be omitted from + either crt file. */ + extern void i_am_not_a_leaf (void); + i_am_not_a_leaf (); + } + + /* Beginning of the _fini epilog. */ + asm ("\n/*@_fini_EPILOG_BEGINS*/"); + SECTION (".fini"); +} +asm ("END_FINI"); + +/* End of the _fini epilog. Any further generated assembly (e.g. .ident) + is shared between both crt files. */ +asm ("\n/*@_fini_EPILOG_ENDS*/"); +asm ("\n/*@TRAILER_BEGINS*/"); + +/* End of file. */ diff --git a/libpthread/nptl/sysdeps/pthread/pt-longjmp.c b/libpthread/nptl/sysdeps/pthread/pt-longjmp.c new file mode 100644 index 000000000..f161380ea --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pt-longjmp.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <setjmp.h> +#include <stdlib.h> +#include "pthreadP.h" + +void +longjmp (jmp_buf env, int val) +{ + __libc_longjmp (env, val); +} +weak_alias (longjmp, siglongjmp) diff --git a/libpthread/nptl/sysdeps/pthread/pthread-functions.h b/libpthread/nptl/sysdeps/pthread/pthread-functions.h new file mode 100644 index 000000000..3808e4cb9 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread-functions.h @@ -0,0 +1,117 @@ +/* Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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. */ + +#ifndef _PTHREAD_FUNCTIONS_H +#define _PTHREAD_FUNCTIONS_H 1 + +#include <pthread.h> +#include <setjmp.h> +#include <internaltypes.h> +#include <sysdep.h> + +struct xid_command; + +/* Data type shared with libc. The libc uses it to pass on calls to + the thread functions. */ +struct pthread_functions +{ + int (*ptr_pthread_attr_destroy) (pthread_attr_t *); + int (*ptr___pthread_attr_init_2_0) (pthread_attr_t *); + int (*ptr___pthread_attr_init_2_1) (pthread_attr_t *); + int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *, + struct sched_param *); + int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *, + const struct sched_param *); + int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int); + int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *); + int (*ptr_pthread_condattr_init) (pthread_condattr_t *); + int (*ptr___pthread_cond_broadcast) (pthread_cond_t *); + int (*ptr___pthread_cond_destroy) (pthread_cond_t *); + int (*ptr___pthread_cond_init) (pthread_cond_t *, + const pthread_condattr_t *); + int (*ptr___pthread_cond_signal) (pthread_cond_t *); + int (*ptr___pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *); + int (*ptr___pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *, + const struct timespec *); + int (*ptr___pthread_cond_broadcast_2_0) (pthread_cond_2_0_t *); + int (*ptr___pthread_cond_destroy_2_0) (pthread_cond_2_0_t *); + int (*ptr___pthread_cond_init_2_0) (pthread_cond_2_0_t *, + const pthread_condattr_t *); + int (*ptr___pthread_cond_signal_2_0) (pthread_cond_2_0_t *); + int (*ptr___pthread_cond_wait_2_0) (pthread_cond_2_0_t *, pthread_mutex_t *); + int (*ptr___pthread_cond_timedwait_2_0) (pthread_cond_2_0_t *, + pthread_mutex_t *, + const struct timespec *); + int (*ptr_pthread_equal) (pthread_t, pthread_t); + void (*ptr___pthread_exit) (void *); + int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *); + int (*ptr_pthread_setschedparam) (pthread_t, int, + const struct sched_param *); + int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *); + int (*ptr_pthread_mutex_init) (pthread_mutex_t *, + const pthread_mutexattr_t *); + int (*ptr_pthread_mutex_lock) (pthread_mutex_t *); + int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *); + pthread_t (*ptr_pthread_self) (void); + int (*ptr_pthread_setcancelstate) (int, int *); + int (*ptr_pthread_setcanceltype) (int, int *); + void (*ptr___pthread_cleanup_upto) (__jmp_buf, char *); + int (*ptr___pthread_once) (pthread_once_t *, void (*) (void)); + int (*ptr___pthread_rwlock_rdlock) (pthread_rwlock_t *); + int (*ptr___pthread_rwlock_wrlock) (pthread_rwlock_t *); + int (*ptr___pthread_rwlock_unlock) (pthread_rwlock_t *); + int (*ptr___pthread_key_create) (pthread_key_t *, void (*) (void *)); + void *(*ptr___pthread_getspecific) (pthread_key_t); + int (*ptr___pthread_setspecific) (pthread_key_t, const void *); + void (*ptr__pthread_cleanup_push_defer) (struct _pthread_cleanup_buffer *, + void (*) (void *), void *); + void (*ptr__pthread_cleanup_pop_restore) (struct _pthread_cleanup_buffer *, + int); +#define HAVE_PTR_NTHREADS + unsigned int *ptr_nthreads; + void (*ptr___pthread_unwind) (__pthread_unwind_buf_t *) + __attribute ((noreturn)) __cleanup_fct_attribute; + void (*ptr__nptl_deallocate_tsd) (void); + int (*ptr__nptl_setxid) (struct xid_command *); + void (*ptr_freeres) (void); +}; + +/* Variable in libc.so. */ +extern struct pthread_functions __libc_pthread_functions attribute_hidden; +extern int __libc_pthread_functions_init attribute_hidden; + +#if 0 +# define PTHFCT_CALL(fct, params) \ + ({ __typeof (__libc_pthread_functions.fct) __p; \ + __p = __libc_pthread_functions.fct; \ + PTR_DEMANGLE (__p); \ + __p params; }) +#else +# define PTHFCT_CALL(fct, params) \ + __libc_pthread_functions.fct params +#endif + +#endif /* pthread-functions.h */ diff --git a/libpthread/nptl/sysdeps/pthread/pthread.h b/libpthread/nptl/sysdeps/pthread/pthread.h new file mode 100644 index 000000000..deb74309a --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread.h @@ -0,0 +1,1138 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _PTHREAD_H +#define _PTHREAD_H 1 + +#include <features.h> +#include <endian.h> +#include <sched.h> +#include <time.h> + +#define __need_sigset_t +#include <signal.h> +#include <bits/pthreadtypes.h> +#include <bits/setjmp.h> +#include <bits/wordsize.h> +#if defined _LIBC && ( defined IS_IN_libc || defined NOT_IN_libc ) +#include <bits/uClibc_pthread.h> +#endif + + +/* Detach state. */ +enum +{ + PTHREAD_CREATE_JOINABLE, +#define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_JOINABLE + PTHREAD_CREATE_DETACHED +#define PTHREAD_CREATE_DETACHED PTHREAD_CREATE_DETACHED +}; + + +/* Mutex types. */ +enum +{ + PTHREAD_MUTEX_TIMED_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_ADAPTIVE_NP +#if defined __USE_UNIX98 || defined __USE_XOPEN2K8 + , + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +#endif +#ifdef __USE_GNU + /* For compatibility. */ + , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_TIMED_NP +#endif +}; + + +#ifdef __USE_XOPEN2K +/* Robust mutex or not flags. */ +enum +{ + PTHREAD_MUTEX_STALLED, + PTHREAD_MUTEX_STALLED_NP = PTHREAD_MUTEX_STALLED, + PTHREAD_MUTEX_ROBUST, + PTHREAD_MUTEX_ROBUST_NP = PTHREAD_MUTEX_ROBUST +}; +#endif + + +#ifdef __USE_UNIX98 +/* Mutex protocols. */ +enum +{ + PTHREAD_PRIO_NONE, + PTHREAD_PRIO_INHERIT, + PTHREAD_PRIO_PROTECT +}; +#endif + + +/* Mutex initializers. */ +#if __WORDSIZE == 64 +# define PTHREAD_MUTEX_INITIALIZER \ + { { 0, 0, 0, 0, 0, 0, { 0, 0 } } } +# ifdef __USE_GNU +# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ + { { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, { 0, 0 } } } +# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ + { { 0, 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, 0, { 0, 0 } } } +# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ + { { 0, 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, 0, { 0, 0 } } } +# endif +#else +# define PTHREAD_MUTEX_INITIALIZER \ + { { 0, 0, 0, 0, 0, { 0 } } } +# ifdef __USE_GNU +# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ + { { 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, { 0 } } } +# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ + { { 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, 0, { 0 } } } +# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ + { { 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, 0, { 0 } } } +# endif +#endif + + +/* Read-write lock types. */ +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +enum +{ + PTHREAD_RWLOCK_PREFER_READER_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, + PTHREAD_RWLOCK_DEFAULT_NP = PTHREAD_RWLOCK_PREFER_READER_NP +}; + +/* Read-write lock initializers. */ +# define PTHREAD_RWLOCK_INITIALIZER \ + { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } +# ifdef __USE_GNU +# if __WORDSIZE == 64 +# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ + { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP } } +# else +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ + { { 0, 0, 0, 0, 0, 0, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, \ + 0, 0, 0, 0 } } +# else +# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ + { { 0, 0, 0, 0, 0, 0, 0, 0, 0, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,\ + 0 } } +# endif +# endif +# endif +#endif /* Unix98 or XOpen2K */ + + +/* Scheduler inheritance. */ +enum +{ + PTHREAD_INHERIT_SCHED, +#define PTHREAD_INHERIT_SCHED PTHREAD_INHERIT_SCHED + PTHREAD_EXPLICIT_SCHED +#define PTHREAD_EXPLICIT_SCHED PTHREAD_EXPLICIT_SCHED +}; + + +/* Scope handling. */ +enum +{ + PTHREAD_SCOPE_SYSTEM, +#define PTHREAD_SCOPE_SYSTEM PTHREAD_SCOPE_SYSTEM + PTHREAD_SCOPE_PROCESS +#define PTHREAD_SCOPE_PROCESS PTHREAD_SCOPE_PROCESS +}; + + +/* Process shared or private flag. */ +enum +{ + PTHREAD_PROCESS_PRIVATE, +#define PTHREAD_PROCESS_PRIVATE PTHREAD_PROCESS_PRIVATE + PTHREAD_PROCESS_SHARED +#define PTHREAD_PROCESS_SHARED PTHREAD_PROCESS_SHARED +}; + + + +/* Conditional variable handling. */ +#define PTHREAD_COND_INITIALIZER { { 0, 0, 0, 0, 0, (void *) 0, 0, 0 } } + + +/* Cleanup buffers */ +struct _pthread_cleanup_buffer +{ + void (*__routine) (void *); /* Function to call. */ + void *__arg; /* Its argument. */ + int __canceltype; /* Saved cancellation type. */ + struct _pthread_cleanup_buffer *__prev; /* Chaining of cleanup functions. */ +}; + +/* Cancellation */ +enum +{ + PTHREAD_CANCEL_ENABLE, +#define PTHREAD_CANCEL_ENABLE PTHREAD_CANCEL_ENABLE + PTHREAD_CANCEL_DISABLE +#define PTHREAD_CANCEL_DISABLE PTHREAD_CANCEL_DISABLE +}; +enum +{ + PTHREAD_CANCEL_DEFERRED, +#define PTHREAD_CANCEL_DEFERRED PTHREAD_CANCEL_DEFERRED + PTHREAD_CANCEL_ASYNCHRONOUS +#define PTHREAD_CANCEL_ASYNCHRONOUS PTHREAD_CANCEL_ASYNCHRONOUS +}; +#define PTHREAD_CANCELED ((void *) -1) + + +/* Single execution handling. */ +#define PTHREAD_ONCE_INIT 0 + + +#ifdef __USE_XOPEN2K +/* Value returned by 'pthread_barrier_wait' for one of the threads after + the required number of threads have called this function. + -1 is distinct from 0 and all errno constants */ +# define PTHREAD_BARRIER_SERIAL_THREAD -1 +#endif + + +__BEGIN_DECLS + +/* Create a new thread, starting with execution of START-ROUTINE + getting passed ARG. Creation attributed come from ATTR. The new + handle is stored in *NEWTHREAD. */ +extern int pthread_create (pthread_t *__restrict __newthread, + __const pthread_attr_t *__restrict __attr, + void *(*__start_routine) (void *), + void *__restrict __arg) __THROW __nonnull ((1, 3)); + +/* Terminate calling thread. + + The registered cleanup handlers are called via exception handling + so we cannot mark this function with __THROW.*/ +extern void pthread_exit (void *__retval) __attribute__ ((__noreturn__)); + +/* Make calling thread wait for termination of the thread TH. The + exit status of the thread is stored in *THREAD_RETURN, if THREAD_RETURN + is not NULL. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int pthread_join (pthread_t __th, void **__thread_return); + +#ifdef __USE_GNU +/* Check whether thread TH has terminated. If yes return the status of + the thread in *THREAD_RETURN, if THREAD_RETURN is not NULL. */ +extern int pthread_tryjoin_np (pthread_t __th, void **__thread_return) __THROW; + +/* Make calling thread wait for termination of the thread TH, but only + until TIMEOUT. The exit status of the thread is stored in + *THREAD_RETURN, if THREAD_RETURN is not NULL. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int pthread_timedjoin_np (pthread_t __th, void **__thread_return, + __const struct timespec *__abstime); +#endif + +/* Indicate that the thread TH is never to be joined with PTHREAD_JOIN. + The resources of TH will therefore be freed immediately when it + terminates, instead of waiting for another thread to perform PTHREAD_JOIN + on it. */ +extern int pthread_detach (pthread_t __th) __THROW; + + +/* Obtain the identifier of the current thread. */ +extern pthread_t pthread_self (void) __THROW __attribute__ ((__const__)); + +/* Compare two thread identifiers. */ +extern int pthread_equal (pthread_t __thread1, pthread_t __thread2) __THROW; + + +/* Thread attribute handling. */ + +/* Initialize thread attribute *ATTR with default attributes + (detachstate is PTHREAD_JOINABLE, scheduling policy is SCHED_OTHER, + no user-provided stack). */ +extern int pthread_attr_init (pthread_attr_t *__attr) __THROW __nonnull ((1)); + +/* Destroy thread attribute *ATTR. */ +extern int pthread_attr_destroy (pthread_attr_t *__attr) + __THROW __nonnull ((1)); + +/* Get detach state attribute. */ +extern int pthread_attr_getdetachstate (__const pthread_attr_t *__attr, + int *__detachstate) + __THROW __nonnull ((1, 2)); + +/* Set detach state attribute. */ +extern int pthread_attr_setdetachstate (pthread_attr_t *__attr, + int __detachstate) + __THROW __nonnull ((1)); + + +/* Get the size of the guard area created for stack overflow protection. */ +extern int pthread_attr_getguardsize (__const pthread_attr_t *__attr, + size_t *__guardsize) + __THROW __nonnull ((1, 2)); + +/* Set the size of the guard area created for stack overflow protection. */ +extern int pthread_attr_setguardsize (pthread_attr_t *__attr, + size_t __guardsize) + __THROW __nonnull ((1)); + + +/* Return in *PARAM the scheduling parameters of *ATTR. */ +extern int pthread_attr_getschedparam (__const pthread_attr_t *__restrict + __attr, + struct sched_param *__restrict __param) + __THROW __nonnull ((1, 2)); + +/* Set scheduling parameters (priority, etc) in *ATTR according to PARAM. */ +extern int pthread_attr_setschedparam (pthread_attr_t *__restrict __attr, + __const struct sched_param *__restrict + __param) __THROW __nonnull ((1, 2)); + +/* Return in *POLICY the scheduling policy of *ATTR. */ +extern int pthread_attr_getschedpolicy (__const pthread_attr_t *__restrict + __attr, int *__restrict __policy) + __THROW __nonnull ((1, 2)); + +/* Set scheduling policy in *ATTR according to POLICY. */ +extern int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy) + __THROW __nonnull ((1)); + +/* Return in *INHERIT the scheduling inheritance mode of *ATTR. */ +extern int pthread_attr_getinheritsched (__const pthread_attr_t *__restrict + __attr, int *__restrict __inherit) + __THROW __nonnull ((1, 2)); + +/* Set scheduling inheritance mode in *ATTR according to INHERIT. */ +extern int pthread_attr_setinheritsched (pthread_attr_t *__attr, + int __inherit) + __THROW __nonnull ((1)); + + +/* Return in *SCOPE the scheduling contention scope of *ATTR. */ +extern int pthread_attr_getscope (__const pthread_attr_t *__restrict __attr, + int *__restrict __scope) + __THROW __nonnull ((1, 2)); + +/* Set scheduling contention scope in *ATTR according to SCOPE. */ +extern int pthread_attr_setscope (pthread_attr_t *__attr, int __scope) + __THROW __nonnull ((1)); + +/* Return the previously set address for the stack. */ +extern int pthread_attr_getstackaddr (__const pthread_attr_t *__restrict + __attr, void **__restrict __stackaddr) + __THROW __nonnull ((1, 2)) __attribute_deprecated__; + +/* Set the starting address of the stack of the thread to be created. + Depending on whether the stack grows up or down the value must either + be higher or lower than all the address in the memory block. The + minimal size of the block must be PTHREAD_STACK_MIN. */ +extern int pthread_attr_setstackaddr (pthread_attr_t *__attr, + void *__stackaddr) + __THROW __nonnull ((1)) __attribute_deprecated__; + +/* Return the currently used minimal stack size. */ +extern int pthread_attr_getstacksize (__const pthread_attr_t *__restrict + __attr, size_t *__restrict __stacksize) + __THROW __nonnull ((1, 2)); + +/* Add information about the minimum stack size needed for the thread + to be started. This size must never be less than PTHREAD_STACK_MIN + and must also not exceed the system limits. */ +extern int pthread_attr_setstacksize (pthread_attr_t *__attr, + size_t __stacksize) + __THROW __nonnull ((1)); + +#ifdef __USE_XOPEN2K +/* Return the previously set address for the stack. */ +extern int pthread_attr_getstack (__const pthread_attr_t *__restrict __attr, + void **__restrict __stackaddr, + size_t *__restrict __stacksize) + __THROW __nonnull ((1, 2, 3)); + +/* The following two interfaces are intended to replace the last two. They + require setting the address as well as the size since only setting the + address will make the implementation on some architectures impossible. */ +extern int pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr, + size_t __stacksize) __THROW __nonnull ((1)); +#endif + +#ifdef __USE_GNU +/* Thread created with attribute ATTR will be limited to run only on + the processors represented in CPUSET. */ +extern int pthread_attr_setaffinity_np (pthread_attr_t *__attr, + size_t __cpusetsize, + __const cpu_set_t *__cpuset) + __THROW __nonnull ((1, 3)); + +/* Get bit set in CPUSET representing the processors threads created with + ATTR can run on. */ +extern int pthread_attr_getaffinity_np (__const pthread_attr_t *__attr, + size_t __cpusetsize, + cpu_set_t *__cpuset) + __THROW __nonnull ((1, 3)); + + +/* Initialize thread attribute *ATTR with attributes corresponding to the + already running thread TH. It shall be called on uninitialized ATTR + and destroyed with pthread_attr_destroy when no longer needed. */ +extern int pthread_getattr_np (pthread_t __th, pthread_attr_t *__attr) + __THROW __nonnull ((2)); +#endif + + +/* Functions for scheduling control. */ + +/* Set the scheduling parameters for TARGET_THREAD according to POLICY + and *PARAM. */ +extern int pthread_setschedparam (pthread_t __target_thread, int __policy, + __const struct sched_param *__param) + __THROW __nonnull ((3)); + +/* Return in *POLICY and *PARAM the scheduling parameters for TARGET_THREAD. */ +extern int pthread_getschedparam (pthread_t __target_thread, + int *__restrict __policy, + struct sched_param *__restrict __param) + __THROW __nonnull ((2, 3)); + +/* Set the scheduling priority for TARGET_THREAD. */ +extern int pthread_setschedprio (pthread_t __target_thread, int __prio) + __THROW; + + +#ifdef __USE_UNIX98 +/* Determine level of concurrency. */ +extern int pthread_getconcurrency (void) __THROW; + +/* Set new concurrency level to LEVEL. */ +extern int pthread_setconcurrency (int __level) __THROW; +#endif + +#ifdef __USE_GNU +/* Yield the processor to another thread or process. + This function is similar to the POSIX `sched_yield' function but + might be differently implemented in the case of a m-on-n thread + implementation. */ +extern int pthread_yield (void) __THROW; + + +/* Limit specified thread TH to run only on the processors represented + in CPUSET. */ +extern int pthread_setaffinity_np (pthread_t __th, size_t __cpusetsize, + __const cpu_set_t *__cpuset) + __THROW __nonnull ((3)); + +/* Get bit set in CPUSET representing the processors TH can run on. */ +extern int pthread_getaffinity_np (pthread_t __th, size_t __cpusetsize, + cpu_set_t *__cpuset) + __THROW __nonnull ((3)); +#endif + + +/* Functions for handling initialization. */ + +/* Guarantee that the initialization function INIT_ROUTINE will be called + only once, even if pthread_once is executed several times with the + same ONCE_CONTROL argument. ONCE_CONTROL must point to a static or + extern variable initialized to PTHREAD_ONCE_INIT. + + The initialization functions might throw exception which is why + this function is not marked with __THROW. */ +extern int pthread_once (pthread_once_t *__once_control, + void (*__init_routine) (void)) __nonnull ((1, 2)); + + +/* Functions for handling cancellation. + + Note that these functions are explicitly not marked to not throw an + exception in C++ code. If cancellation is implemented by unwinding + this is necessary to have the compiler generate the unwind information. */ + +/* Set cancelability state of current thread to STATE, returning old + state in *OLDSTATE if OLDSTATE is not NULL. */ +extern int pthread_setcancelstate (int __state, int *__oldstate); + +/* Set cancellation state of current thread to TYPE, returning the old + type in *OLDTYPE if OLDTYPE is not NULL. */ +extern int pthread_setcanceltype (int __type, int *__oldtype); + +/* Cancel THREAD immediately or at the next possibility. */ +extern int pthread_cancel (pthread_t __th); + +/* Test for pending cancellation for the current thread and terminate + the thread as per pthread_exit(PTHREAD_CANCELED) if it has been + cancelled. */ +extern void pthread_testcancel (void); + + +/* Cancellation handling with integration into exception handling. */ + +typedef struct +{ + struct + { + __jmp_buf __cancel_jmp_buf; + int __mask_was_saved; + } __cancel_jmp_buf[1]; + void *__pad[4]; +} __pthread_unwind_buf_t __attribute__ ((__aligned__)); + +/* No special attributes by default. */ +#ifndef __cleanup_fct_attribute +# define __cleanup_fct_attribute +#endif + + +/* Structure to hold the cleanup handler information. */ +struct __pthread_cleanup_frame +{ + void (*__cancel_routine) (void *); + void *__cancel_arg; + int __do_it; + int __cancel_type; +}; + +#if defined __GNUC__ && defined __EXCEPTIONS +# ifdef __cplusplus +/* Class to handle cancellation handler invocation. */ +class __pthread_cleanup_class +{ + void (*__cancel_routine) (void *); + void *__cancel_arg; + int __do_it; + int __cancel_type; + + public: + __pthread_cleanup_class (void (*__fct) (void *), void *__arg) + : __cancel_routine (__fct), __cancel_arg (__arg), __do_it (1) { } + ~__pthread_cleanup_class () { if (__do_it) __cancel_routine (__cancel_arg); } + void __setdoit (int __newval) { __do_it = __newval; } + void __defer () { pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, + &__cancel_type); } + void __restore () const { pthread_setcanceltype (__cancel_type, 0); } +}; + +/* Install a cleanup handler: ROUTINE will be called with arguments ARG + when the thread is canceled or calls pthread_exit. ROUTINE will also + be called with arguments ARG when the matching pthread_cleanup_pop + is executed with non-zero EXECUTE argument. + + pthread_cleanup_push and pthread_cleanup_pop are macros and must always + be used in matching pairs at the same nesting level of braces. */ +# define pthread_cleanup_push(routine, arg) \ + do { \ + __pthread_cleanup_class __clframe (routine, arg) + +/* Remove a cleanup handler installed by the matching pthread_cleanup_push. + If EXECUTE is non-zero, the handler function is called. */ +# define pthread_cleanup_pop(execute) \ + __clframe.__setdoit (execute); \ + } while (0) + +# ifdef __USE_GNU +/* Install a cleanup handler as pthread_cleanup_push does, but also + saves the current cancellation type and sets it to deferred + cancellation. */ +# define pthread_cleanup_push_defer_np(routine, arg) \ + do { \ + __pthread_cleanup_class __clframe (routine, arg); \ + __clframe.__defer () + +/* Remove a cleanup handler as pthread_cleanup_pop does, but also + restores the cancellation type that was in effect when the matching + pthread_cleanup_push_defer was called. */ +# define pthread_cleanup_pop_restore_np(execute) \ + __clframe.__restore (); \ + __clframe.__setdoit (execute); \ + } while (0) +# endif +# else +/* Function called to call the cleanup handler. As an extern inline + function the compiler is free to decide inlining the change when + needed or fall back on the copy which must exist somewhere + else. */ +__extern_inline void +__pthread_cleanup_routine (struct __pthread_cleanup_frame *__frame) +{ + if (__frame->__do_it) + __frame->__cancel_routine (__frame->__cancel_arg); +} + +/* Install a cleanup handler: ROUTINE will be called with arguments ARG + when the thread is canceled or calls pthread_exit. ROUTINE will also + be called with arguments ARG when the matching pthread_cleanup_pop + is executed with non-zero EXECUTE argument. + + pthread_cleanup_push and pthread_cleanup_pop are macros and must always + be used in matching pairs at the same nesting level of braces. */ +# define pthread_cleanup_push(routine, arg) \ + do { \ + struct __pthread_cleanup_frame __clframe \ + __attribute__ ((__cleanup__ (__pthread_cleanup_routine))) \ + = { .__cancel_routine = (routine), .__cancel_arg = (arg), \ + .__do_it = 1 }; + +/* Remove a cleanup handler installed by the matching pthread_cleanup_push. + If EXECUTE is non-zero, the handler function is called. */ +# define pthread_cleanup_pop(execute) \ + __clframe.__do_it = (execute); \ + } while (0) + +# ifdef __USE_GNU +/* Install a cleanup handler as pthread_cleanup_push does, but also + saves the current cancellation type and sets it to deferred + cancellation. */ +# define pthread_cleanup_push_defer_np(routine, arg) \ + do { \ + struct __pthread_cleanup_frame __clframe \ + __attribute__ ((__cleanup__ (__pthread_cleanup_routine))) \ + = { .__cancel_routine = (routine), .__cancel_arg = (arg), \ + .__do_it = 1 }; \ + (void) pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, \ + &__clframe.__cancel_type) + +/* Remove a cleanup handler as pthread_cleanup_pop does, but also + restores the cancellation type that was in effect when the matching + pthread_cleanup_push_defer was called. */ +# define pthread_cleanup_pop_restore_np(execute) \ + (void) pthread_setcanceltype (__clframe.__cancel_type, NULL); \ + __clframe.__do_it = (execute); \ + } while (0) +# endif +# endif +#else +/* Install a cleanup handler: ROUTINE will be called with arguments ARG + when the thread is canceled or calls pthread_exit. ROUTINE will also + be called with arguments ARG when the matching pthread_cleanup_pop + is executed with non-zero EXECUTE argument. + + pthread_cleanup_push and pthread_cleanup_pop are macros and must always + be used in matching pairs at the same nesting level of braces. */ +# define pthread_cleanup_push(routine, arg) \ + do { \ + __pthread_unwind_buf_t __cancel_buf; \ + void (*__cancel_routine) (void *) = (routine); \ + void *__cancel_arg = (arg); \ + int not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *) \ + __cancel_buf.__cancel_jmp_buf, 0); \ + if (__builtin_expect (not_first_call, 0)) \ + { \ + __cancel_routine (__cancel_arg); \ + __pthread_unwind_next (&__cancel_buf); \ + /* NOTREACHED */ \ + } \ + \ + __pthread_register_cancel (&__cancel_buf); \ + do { +extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf) + __cleanup_fct_attribute; + +/* Remove a cleanup handler installed by the matching pthread_cleanup_push. + If EXECUTE is non-zero, the handler function is called. */ +# define pthread_cleanup_pop(execute) \ + do { } while (0);/* Empty to allow label before pthread_cleanup_pop. */\ + } while (0); \ + __pthread_unregister_cancel (&__cancel_buf); \ + if (execute) \ + __cancel_routine (__cancel_arg); \ + } while (0) +extern void __pthread_unregister_cancel (__pthread_unwind_buf_t *__buf) + __cleanup_fct_attribute; + +# ifdef __USE_GNU +/* Install a cleanup handler as pthread_cleanup_push does, but also + saves the current cancellation type and sets it to deferred + cancellation. */ +# define pthread_cleanup_push_defer_np(routine, arg) \ + do { \ + __pthread_unwind_buf_t __cancel_buf; \ + void (*__cancel_routine) (void *) = (routine); \ + void *__cancel_arg = (arg); \ + int not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *) \ + __cancel_buf.__cancel_jmp_buf, 0); \ + if (__builtin_expect (not_first_call, 0)) \ + { \ + __cancel_routine (__cancel_arg); \ + __pthread_unwind_next (&__cancel_buf); \ + /* NOTREACHED */ \ + } \ + \ + __pthread_register_cancel_defer (&__cancel_buf); \ + do { +extern void __pthread_register_cancel_defer (__pthread_unwind_buf_t *__buf) + __cleanup_fct_attribute; + +/* Remove a cleanup handler as pthread_cleanup_pop does, but also + restores the cancellation type that was in effect when the matching + pthread_cleanup_push_defer was called. */ +# define pthread_cleanup_pop_restore_np(execute) \ + do { } while (0);/* Empty to allow label before pthread_cleanup_pop. */\ + } while (0); \ + __pthread_unregister_cancel_restore (&__cancel_buf); \ + if (execute) \ + __cancel_routine (__cancel_arg); \ + } while (0) +extern void __pthread_unregister_cancel_restore (__pthread_unwind_buf_t *__buf) + __cleanup_fct_attribute; +# endif + +/* Internal interface to initiate cleanup. */ +extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf) + __cleanup_fct_attribute __attribute__ ((__noreturn__)) +# ifndef SHARED + __attribute__ ((__weak__)) +# endif + ; +#endif + +/* Function used in the macros. */ +struct __jmp_buf_tag; +extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __THROW; + + +/* Mutex handling. */ + +/* Initialize a mutex. */ +extern int pthread_mutex_init (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutexattr) + __THROW __nonnull ((1)); + +/* Destroy a mutex. */ +extern int pthread_mutex_destroy (pthread_mutex_t *__mutex) + __THROW __nonnull ((1)); + +/* Try locking a mutex. */ +extern int pthread_mutex_trylock (pthread_mutex_t *__mutex) + __THROW __nonnull ((1)); + +/* Lock a mutex. */ +extern int pthread_mutex_lock (pthread_mutex_t *__mutex) + __THROW __nonnull ((1)); + +#ifdef __USE_XOPEN2K +/* Wait until lock becomes available, or specified time passes. */ +extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex, + __const struct timespec *__restrict + __abstime) __THROW __nonnull ((1, 2)); +#endif + +/* Unlock a mutex. */ +extern int pthread_mutex_unlock (pthread_mutex_t *__mutex) + __THROW __nonnull ((1)); + + +/* Get the priority ceiling of MUTEX. */ +extern int pthread_mutex_getprioceiling (__const pthread_mutex_t * + __restrict __mutex, + int *__restrict __prioceiling) + __THROW __nonnull ((1, 2)); + +/* Set the priority ceiling of MUTEX to PRIOCEILING, return old + priority ceiling value in *OLD_CEILING. */ +extern int pthread_mutex_setprioceiling (pthread_mutex_t *__restrict __mutex, + int __prioceiling, + int *__restrict __old_ceiling) + __THROW __nonnull ((1, 3)); + + +#ifdef __USE_XOPEN2K8 +/* Declare the state protected by MUTEX as consistent. */ +extern int pthread_mutex_consistent (pthread_mutex_t *__mutex) + __THROW __nonnull ((1)); +# ifdef __USE_GNU +extern int pthread_mutex_consistent_np (pthread_mutex_t *__mutex) + __THROW __nonnull ((1)); +# endif +#endif + + +/* Functions for handling mutex attributes. */ + +/* Initialize mutex attribute object ATTR with default attributes + (kind is PTHREAD_MUTEX_TIMED_NP). */ +extern int pthread_mutexattr_init (pthread_mutexattr_t *__attr) + __THROW __nonnull ((1)); + +/* Destroy mutex attribute object ATTR. */ +extern int pthread_mutexattr_destroy (pthread_mutexattr_t *__attr) + __THROW __nonnull ((1)); + +/* Get the process-shared flag of the mutex attribute ATTR. */ +extern int pthread_mutexattr_getpshared (__const pthread_mutexattr_t * + __restrict __attr, + int *__restrict __pshared) + __THROW __nonnull ((1, 2)); + +/* Set the process-shared flag of the mutex attribute ATTR. */ +extern int pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr, + int __pshared) + __THROW __nonnull ((1)); + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K8 +/* Return in *KIND the mutex kind attribute in *ATTR. */ +extern int pthread_mutexattr_gettype (__const pthread_mutexattr_t *__restrict + __attr, int *__restrict __kind) + __THROW __nonnull ((1, 2)); + +/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL, + PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or + PTHREAD_MUTEX_DEFAULT). */ +extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind) + __THROW __nonnull ((1)); +#endif + +/* Return in *PROTOCOL the mutex protocol attribute in *ATTR. */ +extern int pthread_mutexattr_getprotocol (__const pthread_mutexattr_t * + __restrict __attr, + int *__restrict __protocol) + __THROW __nonnull ((1, 2)); + +/* Set the mutex protocol attribute in *ATTR to PROTOCOL (either + PTHREAD_PRIO_NONE, PTHREAD_PRIO_INHERIT, or PTHREAD_PRIO_PROTECT). */ +extern int pthread_mutexattr_setprotocol (pthread_mutexattr_t *__attr, + int __protocol) + __THROW __nonnull ((1)); + +/* Return in *PRIOCEILING the mutex prioceiling attribute in *ATTR. */ +extern int pthread_mutexattr_getprioceiling (__const pthread_mutexattr_t * + __restrict __attr, + int *__restrict __prioceiling) + __THROW __nonnull ((1, 2)); + +/* Set the mutex prioceiling attribute in *ATTR to PRIOCEILING. */ +extern int pthread_mutexattr_setprioceiling (pthread_mutexattr_t *__attr, + int __prioceiling) + __THROW __nonnull ((1)); + +#ifdef __USE_XOPEN2K +/* Get the robustness flag of the mutex attribute ATTR. */ +extern int pthread_mutexattr_getrobust (__const pthread_mutexattr_t *__attr, + int *__robustness) + __THROW __nonnull ((1, 2)); +# ifdef __USE_GNU +extern int pthread_mutexattr_getrobust_np (__const pthread_mutexattr_t *__attr, + int *__robustness) + __THROW __nonnull ((1, 2)); +# endif + +/* Set the robustness flag of the mutex attribute ATTR. */ +extern int pthread_mutexattr_setrobust (pthread_mutexattr_t *__attr, + int __robustness) + __THROW __nonnull ((1)); +# ifdef __USE_GNU +extern int pthread_mutexattr_setrobust_np (pthread_mutexattr_t *__attr, + int __robustness) + __THROW __nonnull ((1)); +# endif +#endif + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Functions for handling read-write locks. */ + +/* Initialize read-write lock RWLOCK using attributes ATTR, or use + the default values if later is NULL. */ +extern int pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock, + __const pthread_rwlockattr_t *__restrict + __attr) __THROW __nonnull ((1)); + +/* Destroy read-write lock RWLOCK. */ +extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock) + __THROW __nonnull ((1)); + +/* Acquire read lock for RWLOCK. */ +extern int pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock) + __THROW __nonnull ((1)); + +/* Try to acquire read lock for RWLOCK. */ +extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock) + __THROW __nonnull ((1)); + +# ifdef __USE_XOPEN2K +/* Try to acquire read lock for RWLOCK or return after specfied time. */ +extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock, + __const struct timespec *__restrict + __abstime) __THROW __nonnull ((1, 2)); +# endif + +/* Acquire write lock for RWLOCK. */ +extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock) + __THROW __nonnull ((1)); + +/* Try to acquire write lock for RWLOCK. */ +extern int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock) + __THROW __nonnull ((1)); + +# ifdef __USE_XOPEN2K +/* Try to acquire write lock for RWLOCK or return after specfied time. */ +extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock, + __const struct timespec *__restrict + __abstime) __THROW __nonnull ((1, 2)); +# endif + +/* Unlock RWLOCK. */ +extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock) + __THROW __nonnull ((1)); + + +/* Functions for handling read-write lock attributes. */ + +/* Initialize attribute object ATTR with default values. */ +extern int pthread_rwlockattr_init (pthread_rwlockattr_t *__attr) + __THROW __nonnull ((1)); + +/* Destroy attribute object ATTR. */ +extern int pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr) + __THROW __nonnull ((1)); + +/* Return current setting of process-shared attribute of ATTR in PSHARED. */ +extern int pthread_rwlockattr_getpshared (__const pthread_rwlockattr_t * + __restrict __attr, + int *__restrict __pshared) + __THROW __nonnull ((1, 2)); + +/* Set process-shared attribute of ATTR to PSHARED. */ +extern int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *__attr, + int __pshared) + __THROW __nonnull ((1)); + +/* Return current setting of reader/writer preference. */ +extern int pthread_rwlockattr_getkind_np (__const pthread_rwlockattr_t * + __restrict __attr, + int *__restrict __pref) + __THROW __nonnull ((1, 2)); + +/* Set reader/write preference. */ +extern int pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *__attr, + int __pref) __THROW __nonnull ((1)); +#endif + + +/* Functions for handling conditional variables. */ + +/* Initialize condition variable COND using attributes ATTR, or use + the default values if later is NULL. */ +extern int pthread_cond_init (pthread_cond_t *__restrict __cond, + __const pthread_condattr_t *__restrict + __cond_attr) __THROW __nonnull ((1)); + +/* Destroy condition variable COND. */ +extern int pthread_cond_destroy (pthread_cond_t *__cond) + __THROW __nonnull ((1)); + +/* Wake up one thread waiting for condition variable COND. */ +extern int pthread_cond_signal (pthread_cond_t *__cond) + __THROW __nonnull ((1)); + +/* Wake up all threads waiting for condition variables COND. */ +extern int pthread_cond_broadcast (pthread_cond_t *__cond) + __THROW __nonnull ((1)); + +/* Wait for condition variable COND to be signaled or broadcast. + MUTEX is assumed to be locked before. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int pthread_cond_wait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex) + __nonnull ((1, 2)); + +/* Wait for condition variable COND to be signaled or broadcast until + ABSTIME. MUTEX is assumed to be locked before. ABSTIME is an + absolute time specification; zero is the beginning of the epoch + (00:00:00 GMT, January 1, 1970). + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex, + __const struct timespec *__restrict + __abstime) __nonnull ((1, 2, 3)); + +/* Functions for handling condition variable attributes. */ + +/* Initialize condition variable attribute ATTR. */ +extern int pthread_condattr_init (pthread_condattr_t *__attr) + __THROW __nonnull ((1)); + +/* Destroy condition variable attribute ATTR. */ +extern int pthread_condattr_destroy (pthread_condattr_t *__attr) + __THROW __nonnull ((1)); + +/* Get the process-shared flag of the condition variable attribute ATTR. */ +extern int pthread_condattr_getpshared (__const pthread_condattr_t * + __restrict __attr, + int *__restrict __pshared) + __THROW __nonnull ((1, 2)); + +/* Set the process-shared flag of the condition variable attribute ATTR. */ +extern int pthread_condattr_setpshared (pthread_condattr_t *__attr, + int __pshared) __THROW __nonnull ((1)); + +#ifdef __USE_XOPEN2K +/* Get the clock selected for the conditon variable attribute ATTR. */ +extern int pthread_condattr_getclock (__const pthread_condattr_t * + __restrict __attr, + __clockid_t *__restrict __clock_id) + __THROW __nonnull ((1, 2)); + +/* Set the clock selected for the conditon variable attribute ATTR. */ +extern int pthread_condattr_setclock (pthread_condattr_t *__attr, + __clockid_t __clock_id) + __THROW __nonnull ((1)); +#endif + + +#ifdef __USE_XOPEN2K +/* Functions to handle spinlocks. */ + +/* Initialize the spinlock LOCK. If PSHARED is nonzero the spinlock can + be shared between different processes. */ +extern int pthread_spin_init (pthread_spinlock_t *__lock, int __pshared) + __THROW __nonnull ((1)); + +/* Destroy the spinlock LOCK. */ +extern int pthread_spin_destroy (pthread_spinlock_t *__lock) + __THROW __nonnull ((1)); + +/* Wait until spinlock LOCK is retrieved. */ +extern int pthread_spin_lock (pthread_spinlock_t *__lock) + __THROW __nonnull ((1)); + +/* Try to lock spinlock LOCK. */ +extern int pthread_spin_trylock (pthread_spinlock_t *__lock) + __THROW __nonnull ((1)); + +/* Release spinlock LOCK. */ +extern int pthread_spin_unlock (pthread_spinlock_t *__lock) + __THROW __nonnull ((1)); + + +/* Functions to handle barriers. */ + +/* Initialize BARRIER with the attributes in ATTR. The barrier is + opened when COUNT waiters arrived. */ +extern int pthread_barrier_init (pthread_barrier_t *__restrict __barrier, + __const pthread_barrierattr_t *__restrict + __attr, unsigned int __count) + __THROW __nonnull ((1)); + +/* Destroy a previously dynamically initialized barrier BARRIER. */ +extern int pthread_barrier_destroy (pthread_barrier_t *__barrier) + __THROW __nonnull ((1)); + +/* Wait on barrier BARRIER. */ +extern int pthread_barrier_wait (pthread_barrier_t *__barrier) + __THROW __nonnull ((1)); + + +/* Initialize barrier attribute ATTR. */ +extern int pthread_barrierattr_init (pthread_barrierattr_t *__attr) + __THROW __nonnull ((1)); + +/* Destroy previously dynamically initialized barrier attribute ATTR. */ +extern int pthread_barrierattr_destroy (pthread_barrierattr_t *__attr) + __THROW __nonnull ((1)); + +/* Get the process-shared flag of the barrier attribute ATTR. */ +extern int pthread_barrierattr_getpshared (__const pthread_barrierattr_t * + __restrict __attr, + int *__restrict __pshared) + __THROW __nonnull ((1, 2)); + +/* Set the process-shared flag of the barrier attribute ATTR. */ +extern int pthread_barrierattr_setpshared (pthread_barrierattr_t *__attr, + int __pshared) + __THROW __nonnull ((1)); +#endif + + +/* Functions for handling thread-specific data. */ + +/* Create a key value identifying a location in the thread-specific + data area. Each thread maintains a distinct thread-specific data + area. DESTR_FUNCTION, if non-NULL, is called with the value + associated to that key when the key is destroyed. + DESTR_FUNCTION is not called if the value associated is NULL when + the key is destroyed. */ +extern int pthread_key_create (pthread_key_t *__key, + void (*__destr_function) (void *)) + __THROW __nonnull ((1)); + +/* Destroy KEY. */ +extern int pthread_key_delete (pthread_key_t __key) __THROW; + +/* Return current value of the thread-specific data slot identified by KEY. */ +extern void *pthread_getspecific (pthread_key_t __key) __THROW; + +/* Store POINTER in the thread-specific data slot identified by KEY. */ +extern int pthread_setspecific (pthread_key_t __key, + __const void *__pointer) __THROW ; + + +#ifdef __USE_XOPEN2K +/* Get ID of CPU-time clock for thread THREAD_ID. */ +extern int pthread_getcpuclockid (pthread_t __thread_id, + __clockid_t *__clock_id) + __THROW __nonnull ((2)); +#endif + + +/* Install handlers to be called when a new process is created with FORK. + The PREPARE handler is called in the parent process just before performing + FORK. The PARENT handler is called in the parent process just after FORK. + The CHILD handler is called in the child process. Each of the three + handlers can be NULL, meaning that no handler needs to be called at that + point. + PTHREAD_ATFORK can be called several times, in which case the PREPARE + handlers are called in LIFO order (last added with PTHREAD_ATFORK, + first called before FORK), and the PARENT and CHILD handlers are called + in FIFO (first added, first called). */ + +extern int pthread_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void)) __THROW; + + +#ifdef __USE_EXTERN_INLINES +/* Optimizations. */ +__extern_inline int +__NTH (pthread_equal (pthread_t __thread1, pthread_t __thread2)) +{ + return __thread1 == __thread2; +} +#endif + +__END_DECLS + +#endif /* pthread.h */ diff --git a/libpthread/nptl/sysdeps/pthread/pthread_barrier_destroy.c b/libpthread/nptl/sysdeps/pthread/pthread_barrier_destroy.c new file mode 100644 index 000000000..2afe5b3c5 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_barrier_destroy.c @@ -0,0 +1,44 @@ +/* Copyright (C) 2002, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include "pthreadP.h" +#include <lowlevellock.h> + + +int +pthread_barrier_destroy ( + pthread_barrier_t *barrier) +{ + struct pthread_barrier *ibarrier; + int result = EBUSY; + + ibarrier = (struct pthread_barrier *) barrier; + + lll_lock (ibarrier->lock, ibarrier->private ^ FUTEX_PRIVATE_FLAG); + + if (__builtin_expect (ibarrier->left == ibarrier->init_count, 1)) + /* The barrier is not used anymore. */ + result = 0; + else + /* Still used, return with an error. */ + lll_unlock (ibarrier->lock, ibarrier->private ^ FUTEX_PRIVATE_FLAG); + + return result; +} diff --git a/libpthread/nptl/sysdeps/pthread/pthread_barrier_init.c b/libpthread/nptl/sysdeps/pthread/pthread_barrier_init.c new file mode 100644 index 000000000..f0396f929 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_barrier_init.c @@ -0,0 +1,71 @@ +/* Copyright (C) 2002, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include "pthreadP.h" +#include <lowlevellock.h> +#include <bits/kernel-features.h> + + +static const struct pthread_barrierattr default_attr = + { + .pshared = PTHREAD_PROCESS_PRIVATE + }; + + +int +pthread_barrier_init ( + pthread_barrier_t *barrier, + const pthread_barrierattr_t *attr, + unsigned int count) +{ + struct pthread_barrier *ibarrier; + + if (__builtin_expect (count == 0, 0)) + return EINVAL; + + const struct pthread_barrierattr *iattr + = (attr != NULL + ? iattr = (struct pthread_barrierattr *) attr + : &default_attr); + + if (iattr->pshared != PTHREAD_PROCESS_PRIVATE + && __builtin_expect (iattr->pshared != PTHREAD_PROCESS_SHARED, 0)) + /* Invalid attribute. */ + return EINVAL; + + ibarrier = (struct pthread_barrier *) barrier; + + /* Initialize the individual fields. */ + ibarrier->lock = LLL_LOCK_INITIALIZER; + ibarrier->left = count; + ibarrier->init_count = count; + ibarrier->curr_event = 0; + +#ifdef __ASSUME_PRIVATE_FUTEX + ibarrier->private = (iattr->pshared != PTHREAD_PROCESS_PRIVATE + ? 0 : FUTEX_PRIVATE_FLAG); +#else + ibarrier->private = (iattr->pshared != PTHREAD_PROCESS_PRIVATE + ? 0 : THREAD_GETMEM (THREAD_SELF, + header.private_futex)); +#endif + + return 0; +} diff --git a/libpthread/nptl/sysdeps/pthread/pthread_barrier_wait.c b/libpthread/nptl/sysdeps/pthread/pthread_barrier_wait.c new file mode 100644 index 000000000..d1135391e --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_barrier_wait.c @@ -0,0 +1,79 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 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 <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <pthreadP.h> + + +/* Wait on barrier. */ +int +pthread_barrier_wait ( + pthread_barrier_t *barrier) +{ + struct pthread_barrier *ibarrier = (struct pthread_barrier *) barrier; + int result = 0; + + /* Make sure we are alone. */ + lll_lock (ibarrier->lock, ibarrier->private ^ FUTEX_PRIVATE_FLAG); + + /* 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, + ibarrier->private ^ FUTEX_PRIVATE_FLAG); + + /* 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, ibarrier->private ^ FUTEX_PRIVATE_FLAG); + + /* Wait for the event counter of the barrier to change. */ + do + lll_futex_wait (&ibarrier->curr_event, event, + ibarrier->private ^ FUTEX_PRIVATE_FLAG); + 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, ibarrier->private ^ FUTEX_PRIVATE_FLAG); + + return result; +} diff --git a/libpthread/nptl/sysdeps/pthread/pthread_cond_broadcast.c b/libpthread/nptl/sysdeps/pthread/pthread_cond_broadcast.c new file mode 100644 index 000000000..04cfc3a72 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_cond_broadcast.c @@ -0,0 +1,90 @@ +/* Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 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 <endian.h> +#include <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <pthread.h> +#include <pthreadP.h> + +#include <bits/kernel-features.h> + + +int +attribute_hidden +__pthread_cond_broadcast ( + pthread_cond_t *cond) +{ + int pshared = (cond->__data.__mutex == (void *) ~0l) + ? LLL_SHARED : LLL_PRIVATE; + /* Make sure we are alone. */ + lll_lock (cond->__data.__lock, pshared); + + /* 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_unlock (cond->__data.__lock, pshared); + + /* 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. */ + /* XXX: Kernel so far can only requeue to the same type of futex, + in this case private (we don't requeue for pshared condvars). */ + if (__builtin_expect (mut->__data.__kind + & (PTHREAD_MUTEX_PRIO_INHERIT_NP + | PTHREAD_MUTEX_PSHARED_BIT), 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, LLL_PRIVATE), 0)) + { + /* The requeue functionality is not available. */ + wake_all: + lll_futex_wake (&cond->__data.__futex, INT_MAX, pshared); + } + + /* That's all. */ + return 0; + } + + /* We are done. */ + lll_unlock (cond->__data.__lock, pshared); + + return 0; +} + +weak_alias(__pthread_cond_broadcast, pthread_cond_broadcast) diff --git a/libpthread/nptl/sysdeps/pthread/pthread_cond_signal.c b/libpthread/nptl/sysdeps/pthread/pthread_cond_signal.c new file mode 100644 index 000000000..aa6d108ed --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_cond_signal.c @@ -0,0 +1,63 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 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 <endian.h> +#include <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <pthread.h> +#include <pthreadP.h> + +#include <bits/kernel-features.h> + + +int +attribute_hidden +__pthread_cond_signal ( + pthread_cond_t *cond) +{ + int pshared = (cond->__data.__mutex == (void *) ~0l) + ? LLL_SHARED : LLL_PRIVATE; + + /* Make sure we are alone. */ + lll_lock (cond->__data.__lock, pshared); + + /* 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, + pshared), 0)) + return 0; + + lll_futex_wake (&cond->__data.__futex, 1, pshared); + } + + /* We are done. */ + lll_unlock (cond->__data.__lock, pshared); + + return 0; +} + +weak_alias(__pthread_cond_signal, pthread_cond_signal) diff --git a/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c b/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c new file mode 100644 index 000000000..88aa0dbf1 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c @@ -0,0 +1,216 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 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 <endian.h> +#include <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <pthread.h> +#include <pthreadP.h> +#include <bits/kernel-features.h> + + +/* 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 +attribute_hidden +__pthread_cond_timedwait ( + 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; + + int pshared = (cond->__data.__mutex == (void *) ~0l) + ? LLL_SHARED : LLL_PRIVATE; + + /* Make sure we are along. */ + lll_lock (cond->__data.__lock, pshared); + + /* Now we can release the mutex. */ + int err = __pthread_mutex_unlock_usercnt (mutex, 0); + if (err) + { + lll_unlock (cond->__data.__lock, pshared); + return err; + } + + /* We have one new user of the condvar. */ + ++cond->__data.__total_seq; + ++cond->__data.__futex; + cond->__data.__nwaiters += 1 << COND_NWAITERS_SHIFT; + + /* 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_NWAITERS_SHIFT) - 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_unlock (cond->__data.__lock, pshared); + + /* 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, pshared); + + /* Disable asynchronous cancellation. */ + __pthread_disable_asynccancel (cbuffer.oldtype); + + /* We are going to look at shared data again, so get the lock. */ + lll_lock (cond->__data.__lock, pshared); + + /* 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_NWAITERS_SHIFT; + + /* 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_NWAITERS_SHIFT)) + lll_futex_wake (&cond->__data.__nwaiters, 1, pshared); + + /* We are done with the condvar. */ + lll_unlock (cond->__data.__lock, pshared); + + /* 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; +} + +weak_alias(__pthread_cond_timedwait, pthread_cond_timedwait) diff --git a/libpthread/nptl/sysdeps/pthread/pthread_cond_wait.c b/libpthread/nptl/sysdeps/pthread/pthread_cond_wait.c new file mode 100644 index 000000000..ad04f151d --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_cond_wait.c @@ -0,0 +1,193 @@ +/* Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 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 <endian.h> +#include <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <pthread.h> +#include <pthreadP.h> + + +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; + int pshared = (cbuffer->cond->__data.__mutex == (void *) ~0l) + ? LLL_SHARED : LLL_PRIVATE; + + /* We are going to modify shared data. */ + lll_lock (cbuffer->cond->__data.__lock, pshared); + + 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_NWAITERS_SHIFT; + + /* 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_NWAITERS_SHIFT)) + { + lll_futex_wake (&cbuffer->cond->__data.__nwaiters, 1, pshared); + destroying = 1; + } + + /* We are done. */ + lll_unlock (cbuffer->cond->__data.__lock, pshared); + + /* Wake everybody to make sure no condvar signal gets lost. */ + if (! destroying) + lll_futex_wake (&cbuffer->cond->__data.__futex, INT_MAX, pshared); + + /* Get the mutex before returning unless asynchronous cancellation + is in effect. */ + __pthread_mutex_cond_lock (cbuffer->mutex); +} + + +int +attribute_hidden +__pthread_cond_wait ( + pthread_cond_t *cond, + pthread_mutex_t *mutex) +{ + struct _pthread_cleanup_buffer buffer; + struct _condvar_cleanup_buffer cbuffer; + int err; + int pshared = (cond->__data.__mutex == (void *) ~0l) + ? LLL_SHARED : LLL_PRIVATE; + + /* Make sure we are along. */ + lll_lock (cond->__data.__lock, pshared); + + /* Now we can release the mutex. */ + err = __pthread_mutex_unlock_usercnt (mutex, 0); + if (__builtin_expect (err, 0)) + { + lll_unlock (cond->__data.__lock, pshared); + return err; + } + + /* We have one new user of the condvar. */ + ++cond->__data.__total_seq; + ++cond->__data.__futex; + cond->__data.__nwaiters += 1 << COND_NWAITERS_SHIFT; + + /* 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_unlock (cond->__data.__lock, pshared); + + /* 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, pshared); + + /* Disable asynchronous cancellation. */ + __pthread_disable_asynccancel (cbuffer.oldtype); + + /* We are going to look at shared data again, so get the lock. */ + lll_lock (cond->__data.__lock, pshared); + + /* 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_NWAITERS_SHIFT; + + /* 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_NWAITERS_SHIFT)) + lll_futex_wake (&cond->__data.__nwaiters, 1, pshared); + + /* We are done with the condvar. */ + lll_unlock (cond->__data.__lock, pshared); + + /* 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); +} + +weak_alias(__pthread_cond_wait, pthread_cond_wait) diff --git a/libpthread/nptl/sysdeps/pthread/pthread_once.c b/libpthread/nptl/sysdeps/pthread/pthread_once.c new file mode 100644 index 000000000..57bb6b977 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_once.c @@ -0,0 +1,54 @@ +/* Copyright (C) 2002, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" +#include <lowlevellock.h> + + + +static int once_lock = LLL_LOCK_INITIALIZER; + + +int +__pthread_once ( + 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, LLL_PRIVATE); + + /* 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, LLL_PRIVATE); + } + + return 0; +} +strong_alias (__pthread_once, pthread_once) diff --git a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_rdlock.c b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_rdlock.c new file mode 100644 index 000000000..af2adb395 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_rdlock.c @@ -0,0 +1,97 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 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 <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <pthread.h> +#include <pthreadP.h> + + +/* Acquire read lock for RWLOCK. */ +int +attribute_hidden +__pthread_rwlock_rdlock ( + pthread_rwlock_t *rwlock) +{ + int result = 0; + + /* Make sure we are along. */ + lll_lock (rwlock->__data.__lock, rwlock->__data.__shared); + + 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 + || PTHREAD_RWLOCK_PREFER_READER_P (rwlock))) + { + /* 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_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + + /* Wait for the writer to finish. */ + lll_futex_wait (&rwlock->__data.__readers_wakeup, waitval, + rwlock->__data.__shared); + + /* Get the lock. */ + lll_lock (rwlock->__data.__lock, rwlock->__data.__shared); + + --rwlock->__data.__nr_readers_queued; + } + + /* We are done, free the lock. */ + lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + + return result; +} + +weak_alias (__pthread_rwlock_rdlock, pthread_rwlock_rdlock) +strong_alias (__pthread_rwlock_rdlock, __pthread_rwlock_rdlock_internal) diff --git a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c new file mode 100644 index 000000000..3daefc71f --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c @@ -0,0 +1,137 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 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 <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <pthread.h> +#include <pthreadP.h> + + +/* Try to acquire read lock for RWLOCK or return after specfied time. */ +int +pthread_rwlock_timedrdlock ( + pthread_rwlock_t *rwlock, + const struct timespec *abstime) +{ + int result = 0; + + /* Make sure we are along. */ + lll_lock(rwlock->__data.__lock, rwlock->__data.__shared); + + 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 + || PTHREAD_RWLOCK_PREFER_READER_P (rwlock))) + { + /* 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_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + + /* Wait for the writer to finish. */ + err = lll_futex_timed_wait (&rwlock->__data.__readers_wakeup, + waitval, &rt, rwlock->__data.__shared); + + /* Get the lock. */ + lll_lock (rwlock->__data.__lock, rwlock->__data.__shared); + + --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_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + + return result; +} diff --git a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c new file mode 100644 index 000000000..e6fcb1640 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c @@ -0,0 +1,127 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 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 <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <pthread.h> +#include <pthreadP.h> + + +/* Try to acquire write lock for RWLOCK or return after specfied time. */ +int +pthread_rwlock_timedwrlock ( + pthread_rwlock_t *rwlock, + const struct timespec *abstime) +{ + int result = 0; + + /* Make sure we are along. */ + lll_lock (rwlock->__data.__lock, rwlock->__data.__shared); + + 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_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + + /* Wait for the writer or reader(s) to finish. */ + err = lll_futex_timed_wait (&rwlock->__data.__writer_wakeup, + waitval, &rt, rwlock->__data.__shared); + + /* Get the lock. */ + lll_lock (rwlock->__data.__lock, rwlock->__data.__shared); + + /* 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_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + + return result; +} diff --git a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_unlock.c b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_unlock.c new file mode 100644 index 000000000..510395e18 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_unlock.c @@ -0,0 +1,60 @@ +/* Copyright (C) 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 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 <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <pthread.h> +#include <pthreadP.h> + +/* Unlock RWLOCK. */ +int +attribute_hidden +__pthread_rwlock_unlock (pthread_rwlock_t *rwlock) +{ + lll_lock (rwlock->__data.__lock, rwlock->__data.__shared); + 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_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + lll_futex_wake (&rwlock->__data.__writer_wakeup, 1, + rwlock->__data.__shared); + return 0; + } + else if (rwlock->__data.__nr_readers_queued) + { + ++rwlock->__data.__readers_wakeup; + lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + lll_futex_wake (&rwlock->__data.__readers_wakeup, INT_MAX, + rwlock->__data.__shared); + return 0; + } + } + lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + return 0; +} + +weak_alias (__pthread_rwlock_unlock, pthread_rwlock_unlock) +strong_alias (__pthread_rwlock_unlock, __pthread_rwlock_unlock_internal) diff --git a/libpthread/nptl/sysdeps/pthread/pthread_rwlock_wrlock.c b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_wrlock.c new file mode 100644 index 000000000..63eed0bac --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_rwlock_wrlock.c @@ -0,0 +1,89 @@ +/* Copyright (C) 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 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 <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <pthread.h> +#include <pthreadP.h> + + +/* Acquire write lock for RWLOCK. */ +int +attribute_hidden +__pthread_rwlock_wrlock ( + pthread_rwlock_t *rwlock) +{ + int result = 0; + + /* Make sure we are along. */ + lll_lock (rwlock->__data.__lock, rwlock->__data.__shared); + + 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_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + + /* Wait for the writer or reader(s) to finish. */ + lll_futex_wait (&rwlock->__data.__writer_wakeup, waitval, + rwlock->__data.__shared); + + /* Get the lock. */ + lll_lock (rwlock->__data.__lock, rwlock->__data.__shared); + + /* To start over again, remove the thread from the writer list. */ + --rwlock->__data.__nr_writers_queued; + } + + /* We are done, free the lock. */ + lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + + return result; +} + +weak_alias (__pthread_rwlock_wrlock, pthread_rwlock_wrlock) +strong_alias (__pthread_rwlock_wrlock, __pthread_rwlock_wrlock_internal) diff --git a/libpthread/nptl/sysdeps/pthread/pthread_sigmask.c b/libpthread/nptl/sysdeps/pthread/pthread_sigmask.c new file mode 100644 index 000000000..6f66bbbff --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/pthread_sigmask.c @@ -0,0 +1,58 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <signal.h> +#include <pthreadP.h> +#include <sysdep.h> + + +int +pthread_sigmask ( + int how, + const sigset_t *newmask, + sigset_t *oldmask) +{ + sigset_t local_newmask; + + /* The only thing we have to make sure here is that SIGCANCEL and + SIGSETXID is not blocked. */ + if (newmask != NULL + && (__builtin_expect (__sigismember (newmask, SIGCANCEL), 0) + || __builtin_expect (__sigismember (newmask, SIGSETXID), 0))) + { + local_newmask = *newmask; + __sigdelset (&local_newmask, SIGCANCEL); + __sigdelset (&local_newmask, SIGSETXID); + newmask = &local_newmask; + } + +#ifdef INTERNAL_SYSCALL + /* We know that realtime signals are available if NPTL is used. */ + INTERNAL_SYSCALL_DECL (err); + int result = INTERNAL_SYSCALL (rt_sigprocmask, err, 4, how, newmask, + oldmask, _NSIG / 8); + + return (INTERNAL_SYSCALL_ERROR_P (result, err) + ? INTERNAL_SYSCALL_ERRNO (result, err) + : 0); +#else + return sigprocmask (how, newmask, oldmask) == -1 ? errno : 0; +#endif +} diff --git a/libpthread/nptl/sysdeps/pthread/pthread_spin_destroy.c b/libpthread/nptl/sysdeps/pthread/pthread_spin_destroy.c new file mode 100644 index 000000000..7118f8a01 --- /dev/null +++ b/libpthread/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 <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_spin_destroy ( + pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} diff --git a/libpthread/nptl/sysdeps/pthread/pthread_spin_init.c b/libpthread/nptl/sysdeps/pthread/pthread_spin_init.c new file mode 100644 index 000000000..c2275085e --- /dev/null +++ b/libpthread/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 <paulus@au.ibm.com>, 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/libpthread/nptl/sysdeps/pthread/pthread_spin_unlock.c b/libpthread/nptl/sysdeps/pthread/pthread_spin_unlock.c new file mode 100644 index 000000000..f97cadfbd --- /dev/null +++ b/libpthread/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 <paulus@au.ibm.com>, 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 <atomic.h> + +int +pthread_spin_unlock (pthread_spinlock_t *lock) +{ + atomic_full_barrier (); + *lock = 0; + return 0; +} diff --git a/libpthread/nptl/sysdeps/pthread/rt-unwind-resume.c b/libpthread/nptl/sysdeps/pthread/rt-unwind-resume.c new file mode 100644 index 000000000..743e675d4 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/rt-unwind-resume.c @@ -0,0 +1 @@ +#include <unwind-resume.c> diff --git a/libpthread/nptl/sysdeps/pthread/setxid.h b/libpthread/nptl/sysdeps/pthread/setxid.h new file mode 100644 index 000000000..aebdbd236 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/setxid.h @@ -0,0 +1,63 @@ +/* Copyright (C) 2004, 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 + 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 <sysdep.h> + +#define __SETXID_1(cmd, arg1) \ + cmd.id[0] = arg1 +#define __SETXID_2(cmd, arg1, arg2) \ + __SETXID_1 (cmd, arg1); cmd.id[1] = arg2 +#define __SETXID_3(cmd, arg1, arg2, arg3) \ + __SETXID_2 (cmd, arg1, arg2); cmd.id[2] = arg3 + +#ifdef SINGLE_THREAD +# define INLINE_SETXID_SYSCALL(name, nr, args...) \ + INLINE_SYSCALL (name, nr, args) +#elif defined SHARED +# define INLINE_SETXID_SYSCALL(name, nr, args...) \ + ({ \ + int __result; \ + if (__builtin_expect (__libc_pthread_functions_init, 0)) \ + { \ + struct xid_command __cmd; \ + __cmd.syscall_no = __NR_##name; \ + __SETXID_##nr (__cmd, args); \ + __result = PTHFCT_CALL (ptr__nptl_setxid, (&__cmd)); \ + } \ + else \ + __result = INLINE_SYSCALL (name, nr, args); \ + __result; \ + }) +#else +# define INLINE_SETXID_SYSCALL(name, nr, args...) \ + ({ \ + extern __typeof (__nptl_setxid) __nptl_setxid __attribute__((weak));\ + int __result; \ + if (__builtin_expect (__nptl_setxid != NULL, 0)) \ + { \ + struct xid_command __cmd; \ + __cmd.syscall_no = __NR_##name; \ + __SETXID_##nr (__cmd, args); \ + __result =__nptl_setxid (&__cmd); \ + } \ + else \ + __result = INLINE_SYSCALL (name, nr, args); \ + __result; \ + }) +#endif diff --git a/libpthread/nptl/sysdeps/pthread/sigaction.c b/libpthread/nptl/sysdeps/pthread/sigaction.c new file mode 100644 index 000000000..20cff8941 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/sigaction.c @@ -0,0 +1,51 @@ +/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef LIBC_SIGACTION + +#include <pthreadP.h> + +/* We use the libc implementation but we tell it to not allow + SIGCANCEL or SIGTIMER to be handled. */ +#define LIBC_SIGACTION 1 +#include <sigaction.c> + +int +sigaction (int sig, const struct sigaction *act, struct sigaction *oact); + +int +__sigaction (int sig, const struct sigaction *act, struct sigaction *oact) +{ + if (__builtin_expect (sig == SIGCANCEL || sig == SIGSETXID, 0)) + { + __set_errno (EINVAL); + return -1; + } + + return __libc_sigaction (sig, act, oact); +} +libc_hidden_proto(sigaction) +weak_alias (__sigaction, sigaction) +libc_hidden_weak(sigaction) + +#else + +# include_next <sigaction.c> + +#endif /* LIBC_SIGACTION */ diff --git a/libpthread/nptl/sysdeps/pthread/sigfillset.c b/libpthread/nptl/sysdeps/pthread/sigfillset.c new file mode 100644 index 000000000..eed75e237 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/sigfillset.c @@ -0,0 +1,21 @@ +/* Copyright (C) 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthreadP.h> + +#include <../../../../libc/signal/sigfillset.c> diff --git a/libpthread/nptl/sysdeps/pthread/sigprocmask.c b/libpthread/nptl/sysdeps/pthread/sigprocmask.c new file mode 100644 index 000000000..35aa843ba --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/sigprocmask.c @@ -0,0 +1,22 @@ +/* Copyright (C) 1997,1998,1999,2000,2001,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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthreadP.h> +#undef _LARGEFILE64_SOURCE + +#include <../../../../libc/sysdeps/linux/common/sigprocmask.c> diff --git a/libpthread/nptl/sysdeps/pthread/tcb-offsets.h b/libpthread/nptl/sysdeps/pthread/tcb-offsets.h new file mode 100644 index 000000000..3fe13702e --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/tcb-offsets.h @@ -0,0 +1 @@ +/* This is overridden by generated tcb-offsets.h on arches which need it. */ diff --git a/libpthread/nptl/sysdeps/pthread/timer_create.c b/libpthread/nptl/sysdeps/pthread/timer_create.c new file mode 100644 index 000000000..ae82c5af0 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/timer_create.c @@ -0,0 +1,170 @@ +/* Copyright (C) 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku <kaz@ashi.footprints.net>. + + 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 <errno.h> +#include <signal.h> +#include <pthread.h> +#include <time.h> +#include <unistd.h> + +#include "posix-timer.h" + + +/* Create new per-process timer using CLOCK. */ +int +timer_create ( + clockid_t clock_id, + struct sigevent *evp, + timer_t *timerid) +{ + int retval = -1; + struct timer_node *newtimer = NULL; + struct thread_node *thread = NULL; + + if (0 +#if defined _POSIX_CPUTIME && _POSIX_CPUTIME >= 0 + || clock_id == CLOCK_PROCESS_CPUTIME_ID +#endif +#if defined _POSIX_THREAD_CPUTIME && _POSIX_THREAD_CPUTIME >= 0 + || clock_id == CLOCK_THREAD_CPUTIME_ID +#endif + ) + { + /* We don't allow timers for CPU clocks. At least not in the + moment. */ + __set_errno (ENOTSUP); + return -1; + } + + if (clock_id != CLOCK_REALTIME) + { + __set_errno (EINVAL); + return -1; + } + + pthread_once (&__timer_init_once_control, __timer_init_once); + + if (__timer_init_failed) + { + __set_errno (ENOMEM); + return -1; + } + + pthread_mutex_lock (&__timer_mutex); + + newtimer = __timer_alloc (); + if (__builtin_expect (newtimer == NULL, 0)) + { + __set_errno (EAGAIN); + goto unlock_bail; + } + + if (evp != NULL) + newtimer->event = *evp; + else + { + newtimer->event.sigev_notify = SIGEV_SIGNAL; + newtimer->event.sigev_signo = SIGALRM; + newtimer->event.sigev_value.sival_ptr = timer_ptr2id (newtimer); + newtimer->event.sigev_notify_function = 0; + } + + newtimer->event.sigev_notify_attributes = &newtimer->attr; + newtimer->creator_pid = getpid (); + + switch (__builtin_expect (newtimer->event.sigev_notify, SIGEV_SIGNAL)) + { + case SIGEV_NONE: + case SIGEV_SIGNAL: + /* We have a global thread for delivering timed signals. + If it is not running, try to start it up. */ + thread = &__timer_signal_thread_rclk; + if (! thread->exists) + { + if (__builtin_expect (__timer_thread_start (thread), + 1) < 0) + { + __set_errno (EAGAIN); + goto unlock_bail; + } + } + break; + + case SIGEV_THREAD: + /* Copy over thread attributes or set up default ones. */ + if (evp->sigev_notify_attributes) + newtimer->attr = *(pthread_attr_t *) evp->sigev_notify_attributes; + else + pthread_attr_init (&newtimer->attr); + + /* Ensure thread attributes call for deatched thread. */ + pthread_attr_setdetachstate (&newtimer->attr, PTHREAD_CREATE_DETACHED); + + /* Try to find existing thread having the right attributes. */ + thread = __timer_thread_find_matching (&newtimer->attr, clock_id); + + /* If no existing thread has these attributes, try to allocate one. */ + if (thread == NULL) + thread = __timer_thread_alloc (&newtimer->attr, clock_id); + + /* Out of luck; no threads are available. */ + if (__builtin_expect (thread == NULL, 0)) + { + __set_errno (EAGAIN); + goto unlock_bail; + } + + /* If the thread is not running already, try to start it. */ + if (! thread->exists + && __builtin_expect (! __timer_thread_start (thread), 0)) + { + __set_errno (EAGAIN); + goto unlock_bail; + } + break; + + default: + __set_errno (EINVAL); + goto unlock_bail; + } + + newtimer->clock = clock_id; + newtimer->abstime = 0; + newtimer->armed = 0; + newtimer->thread = thread; + + *timerid = timer_ptr2id (newtimer); + retval = 0; + + if (__builtin_expect (retval, 0) == -1) + { + unlock_bail: + if (thread != NULL) + __timer_thread_dealloc (thread); + if (newtimer != NULL) + { + timer_delref (newtimer); + __timer_dealloc (newtimer); + } + } + + pthread_mutex_unlock (&__timer_mutex); + + return retval; +} diff --git a/libpthread/nptl/sysdeps/pthread/timer_delete.c b/libpthread/nptl/sysdeps/pthread/timer_delete.c new file mode 100644 index 000000000..4c53112db --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/timer_delete.c @@ -0,0 +1,70 @@ +/* Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku <kaz@ashi.footprints.net>. + + 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 <assert.h> +#include <errno.h> +#include <pthread.h> +#include <time.h> + +#include "posix-timer.h" + + +/* Delete timer TIMERID. */ +int +timer_delete ( + timer_t timerid) +{ + struct timer_node *timer; + int retval = -1; + + pthread_mutex_lock (&__timer_mutex); + + timer = timer_id2ptr (timerid); + if (! timer_valid (timer)) + /* Invalid timer ID or the timer is not in use. */ + __set_errno (EINVAL); + else + { + if (timer->armed && timer->thread != NULL) + { + struct thread_node *thread = timer->thread; + assert (thread != NULL); + + /* If thread is cancelled while waiting for handler to terminate, + the mutex is unlocked and timer_delete is aborted. */ + pthread_cleanup_push (__timer_mutex_cancel_handler, &__timer_mutex); + + /* If timer is currently being serviced, wait for it to finish. */ + while (thread->current_timer == timer) + pthread_cond_wait (&thread->cond, &__timer_mutex); + + pthread_cleanup_pop (0); + } + + /* Remove timer from whatever queue it may be on and deallocate it. */ + timer->inuse = TIMER_DELETED; + list_unlink_ip (&timer->links); + timer_delref (timer); + retval = 0; + } + + pthread_mutex_unlock (&__timer_mutex); + + return retval; +} diff --git a/libpthread/nptl/sysdeps/pthread/timer_getoverr.c b/libpthread/nptl/sysdeps/pthread/timer_getoverr.c new file mode 100644 index 000000000..f3e22215b --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/timer_getoverr.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku <kaz@ashi.footprints.net>. + + 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 <errno.h> +#include <pthread.h> +#include <time.h> + +#include "posix-timer.h" + + +/* Get expiration overrun for timer TIMERID. */ +int +timer_getoverrun (timerid) + timer_t timerid; +{ + struct timer_node *timer; + int retval = -1; + + pthread_mutex_lock (&__timer_mutex); + + if (! timer_valid (timer = timer_id2ptr (timerid))) + __set_errno (EINVAL); + else + retval = timer->overrun_count; + + pthread_mutex_unlock (&__timer_mutex); + + return retval; +} diff --git a/libpthread/nptl/sysdeps/pthread/timer_gettime.c b/libpthread/nptl/sysdeps/pthread/timer_gettime.c new file mode 100644 index 000000000..723a61632 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/timer_gettime.c @@ -0,0 +1,77 @@ +/* Copyright (C) 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku <kaz@ashi.footprints.net>. + + 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 <errno.h> +#include <pthread.h> +#include <time.h> + +#include "posix-timer.h" + + +/* Get current value of timer TIMERID and store it in VLAUE. */ +int +timer_gettime (timerid, value) + timer_t timerid; + struct itimerspec *value; +{ + struct timer_node *timer; + struct timespec now, expiry; + int retval = -1, armed = 0, valid; + clock_t clock = 0; + + pthread_mutex_lock (&__timer_mutex); + + timer = timer_id2ptr (timerid); + valid = timer_valid (timer); + + if (valid) { + armed = timer->armed; + expiry = timer->expirytime; + clock = timer->clock; + value->it_interval = timer->value.it_interval; + } + + pthread_mutex_unlock (&__timer_mutex); + + if (valid) + { + if (armed) + { + clock_gettime (clock, &now); + if (timespec_compare (&now, &expiry) < 0) + timespec_sub (&value->it_value, &expiry, &now); + else + { + value->it_value.tv_sec = 0; + value->it_value.tv_nsec = 0; + } + } + else + { + value->it_value.tv_sec = 0; + value->it_value.tv_nsec = 0; + } + + retval = 0; + } + else + __set_errno (EINVAL); + + return retval; +} diff --git a/libpthread/nptl/sysdeps/pthread/timer_routines.c b/libpthread/nptl/sysdeps/pthread/timer_routines.c new file mode 100644 index 000000000..8d5b1d13a --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/timer_routines.c @@ -0,0 +1,578 @@ +/* Helper code for POSIX timer implementation on NPTL. + Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku <kaz@ashi.footprints.net>. + + 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 <assert.h> +#include <errno.h> +#include <pthread.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <sysdep.h> +#include <time.h> +#include <unistd.h> +#include <sys/syscall.h> + +#include "posix-timer.h" +#include <pthreadP.h> + + +/* Number of threads used. */ +#define THREAD_MAXNODES 16 + +/* Array containing the descriptors for the used threads. */ +static struct thread_node thread_array[THREAD_MAXNODES]; + +/* Static array with the structures for all the timers. */ +struct timer_node __timer_array[TIMER_MAX]; + +/* Global lock to protect operation on the lists. */ +pthread_mutex_t __timer_mutex = PTHREAD_MUTEX_INITIALIZER; + +/* Variable to protext initialization. */ +pthread_once_t __timer_init_once_control = PTHREAD_ONCE_INIT; + +/* Nonzero if initialization of timer implementation failed. */ +int __timer_init_failed; + +/* Node for the thread used to deliver signals. */ +struct thread_node __timer_signal_thread_rclk; + +/* Lists to keep free and used timers and threads. */ +struct list_links timer_free_list; +struct list_links thread_free_list; +struct list_links thread_active_list; + + +#ifdef __NR_rt_sigqueueinfo +extern int __syscall_rt_sigqueueinfo (int, int, siginfo_t *); +#endif + + +/* List handling functions. */ +static inline void +list_init (struct list_links *list) +{ + list->next = list->prev = list; +} + +static inline void +list_append (struct list_links *list, struct list_links *newp) +{ + newp->prev = list->prev; + newp->next = list; + list->prev->next = newp; + list->prev = newp; +} + +static inline void +list_insbefore (struct list_links *list, struct list_links *newp) +{ + list_append (list, newp); +} + +/* + * Like list_unlink_ip, except that calling it on a node that + * is already unlinked is disastrous rather than a noop. + */ + +static inline void +list_unlink (struct list_links *list) +{ + struct list_links *lnext = list->next, *lprev = list->prev; + + lnext->prev = lprev; + lprev->next = lnext; +} + +static inline struct list_links * +list_first (struct list_links *list) +{ + return list->next; +} + +static inline struct list_links * +list_null (struct list_links *list) +{ + return list; +} + +static inline struct list_links * +list_next (struct list_links *list) +{ + return list->next; +} + +static inline int +list_isempty (struct list_links *list) +{ + return list->next == list; +} + + +/* Functions build on top of the list functions. */ +static inline struct thread_node * +thread_links2ptr (struct list_links *list) +{ + return (struct thread_node *) ((char *) list + - offsetof (struct thread_node, links)); +} + +static inline struct timer_node * +timer_links2ptr (struct list_links *list) +{ + return (struct timer_node *) ((char *) list + - offsetof (struct timer_node, links)); +} + + +/* Initialize a newly allocated thread structure. */ +static void +thread_init (struct thread_node *thread, const pthread_attr_t *attr, clockid_t clock_id) +{ + if (attr != NULL) + thread->attr = *attr; + else + { + pthread_attr_init (&thread->attr); + pthread_attr_setdetachstate (&thread->attr, PTHREAD_CREATE_DETACHED); + } + + thread->exists = 0; + list_init (&thread->timer_queue); + pthread_cond_init (&thread->cond, 0); + thread->current_timer = 0; + thread->captured = pthread_self (); + thread->clock_id = clock_id; +} + + +/* Initialize the global lists, and acquire global resources. Error + reporting is done by storing a non-zero value to the global variable + timer_init_failed. */ +static void +init_module (void) +{ + int i; + + list_init (&timer_free_list); + list_init (&thread_free_list); + list_init (&thread_active_list); + + for (i = 0; i < TIMER_MAX; ++i) + { + list_append (&timer_free_list, &__timer_array[i].links); + __timer_array[i].inuse = TIMER_FREE; + } + + for (i = 0; i < THREAD_MAXNODES; ++i) + list_append (&thread_free_list, &thread_array[i].links); + + thread_init (&__timer_signal_thread_rclk, 0, CLOCK_REALTIME); +} + + +/* This is a handler executed in a child process after a fork() + occurs. It reinitializes the module, resetting all of the data + structures to their initial state. The mutex is initialized in + case it was locked in the parent process. */ +static void +reinit_after_fork (void) +{ + init_module (); + pthread_mutex_init (&__timer_mutex, 0); +} + + +/* Called once form pthread_once in timer_init. This initializes the + module and ensures that reinit_after_fork will be executed in any + child process. */ +void +__timer_init_once (void) +{ + init_module (); + pthread_atfork (0, 0, reinit_after_fork); +} + + +/* Deinitialize a thread that is about to be deallocated. */ +static void +thread_deinit (struct thread_node *thread) +{ + assert (list_isempty (&thread->timer_queue)); + pthread_cond_destroy (&thread->cond); +} + + +/* Allocate a thread structure from the global free list. Global + mutex lock must be held by caller. The thread is moved to + the active list. */ +struct thread_node * +__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t clock_id) +{ + struct list_links *node = list_first (&thread_free_list); + + if (node != list_null (&thread_free_list)) + { + struct thread_node *thread = thread_links2ptr (node); + list_unlink (node); + thread_init (thread, desired_attr, clock_id); + list_append (&thread_active_list, node); + return thread; + } + + return 0; +} + + +/* Return a thread structure to the global free list. Global lock + must be held by caller. */ +void +__timer_thread_dealloc (struct thread_node *thread) +{ + thread_deinit (thread); + list_unlink (&thread->links); + list_append (&thread_free_list, &thread->links); +} + + +/* Each of our threads which terminates executes this cleanup + handler. We never terminate threads ourselves; if a thread gets here + it means that the evil application has killed it. If the thread has + timers, these require servicing and so we must hire a replacement + thread right away. We must also unblock another thread that may + have been waiting for this thread to finish servicing a timer (see + timer_delete()). */ + +static void +thread_cleanup (void *val) +{ + if (val != NULL) + { + struct thread_node *thread = val; + + /* How did the signal thread get killed? */ + assert (thread != &__timer_signal_thread_rclk); + + pthread_mutex_lock (&__timer_mutex); + + thread->exists = 0; + + /* We are no longer processing a timer event. */ + thread->current_timer = 0; + + if (list_isempty (&thread->timer_queue)) + __timer_thread_dealloc (thread); + else + (void) __timer_thread_start (thread); + + pthread_mutex_unlock (&__timer_mutex); + + /* Unblock potentially blocked timer_delete(). */ + pthread_cond_broadcast (&thread->cond); + } +} + + +/* Handle a timer which is supposed to go off now. */ +static void +thread_expire_timer (struct thread_node *self, struct timer_node *timer) +{ + self->current_timer = timer; /* Lets timer_delete know timer is running. */ + + pthread_mutex_unlock (&__timer_mutex); + + switch (__builtin_expect (timer->event.sigev_notify, SIGEV_SIGNAL)) + { + case SIGEV_NONE: + break; + + case SIGEV_SIGNAL: +#ifdef __NR_rt_sigqueueinfo + { + siginfo_t info; + + /* First, clear the siginfo_t structure, so that we don't pass our + stack content to other tasks. */ + memset (&info, 0, sizeof (siginfo_t)); + /* We must pass the information about the data in a siginfo_t + value. */ + info.si_signo = timer->event.sigev_signo; + info.si_code = SI_TIMER; + info.si_pid = timer->creator_pid; + info.si_uid = getuid (); + info.si_value = timer->event.sigev_value; + + INLINE_SYSCALL (rt_sigqueueinfo, 3, info.si_pid, info.si_signo, &info); + } +#else + if (pthread_kill (self->captured, timer->event.sigev_signo) != 0) + { + if (pthread_kill (self->id, timer->event.sigev_signo) != 0) + abort (); + } +#endif + break; + + case SIGEV_THREAD: + timer->event.sigev_notify_function (timer->event.sigev_value); + break; + + default: + assert (! "unknown event"); + break; + } + + pthread_mutex_lock (&__timer_mutex); + + self->current_timer = 0; + + pthread_cond_broadcast (&self->cond); +} + + +/* Thread function; executed by each timer thread. The job of this + function is to wait on the thread's timer queue and expire the + timers in chronological order as close to their scheduled time as + possible. */ +static void +__attribute__ ((noreturn)) +thread_func (void *arg) +{ + struct thread_node *self = arg; + + /* Register cleanup handler, in case rogue application terminates + this thread. (This cannot happen to __timer_signal_thread, which + doesn't invoke application callbacks). */ + + pthread_cleanup_push (thread_cleanup, self); + + pthread_mutex_lock (&__timer_mutex); + + while (1) + { + struct list_links *first; + struct timer_node *timer = NULL; + + /* While the timer queue is not empty, inspect the first node. */ + first = list_first (&self->timer_queue); + if (first != list_null (&self->timer_queue)) + { + struct timespec now; + + timer = timer_links2ptr (first); + + /* This assumes that the elements of the list of one thread + are all for the same clock. */ + clock_gettime (timer->clock, &now); + + while (1) + { + /* If the timer is due or overdue, remove it from the queue. + If it's a periodic timer, re-compute its new time and + requeue it. Either way, perform the timer expiry. */ + if (timespec_compare (&now, &timer->expirytime) < 0) + break; + + list_unlink_ip (first); + + if (__builtin_expect (timer->value.it_interval.tv_sec, 0) != 0 + || timer->value.it_interval.tv_nsec != 0) + { + timer->overrun_count = 0; + timespec_add (&timer->expirytime, &timer->expirytime, + &timer->value.it_interval); + while (timespec_compare (&timer->expirytime, &now) < 0) + { + timespec_add (&timer->expirytime, &timer->expirytime, + &timer->value.it_interval); + if (timer->overrun_count < DELAYTIMER_MAX) + ++timer->overrun_count; + } + __timer_thread_queue_timer (self, timer); + } + + thread_expire_timer (self, timer); + + first = list_first (&self->timer_queue); + if (first == list_null (&self->timer_queue)) + break; + + timer = timer_links2ptr (first); + } + } + + /* If the queue is not empty, wait until the expiry time of the + first node. Otherwise wait indefinitely. Insertions at the + head of the queue must wake up the thread by broadcasting + this condition variable. */ + if (timer != NULL) + pthread_cond_timedwait (&self->cond, &__timer_mutex, + &timer->expirytime); + else + pthread_cond_wait (&self->cond, &__timer_mutex); + } + /* This macro will never be executed since the while loop loops + forever - but we have to add it for proper nesting. */ + pthread_cleanup_pop (1); +} + + +/* Enqueue a timer in wakeup order in the thread's timer queue. + Returns 1 if the timer was inserted at the head of the queue, + causing the queue's next wakeup time to change. */ + +int +__timer_thread_queue_timer (struct thread_node *thread, + struct timer_node *insert) +{ + struct list_links *iter; + int athead = 1; + + for (iter = list_first (&thread->timer_queue); + iter != list_null (&thread->timer_queue); + iter = list_next (iter)) + { + struct timer_node *timer = timer_links2ptr (iter); + + if (timespec_compare (&insert->expirytime, &timer->expirytime) < 0) + break; + athead = 0; + } + + list_insbefore (iter, &insert->links); + return athead; +} + + +/* Start a thread and associate it with the given thread node. Global + lock must be held by caller. */ +int +__timer_thread_start (struct thread_node *thread) +{ + int retval = 1; + + assert (!thread->exists); + thread->exists = 1; + + if (pthread_create (&thread->id, &thread->attr, + (void *(*) (void *)) thread_func, thread) != 0) + { + thread->exists = 0; + retval = -1; + } + + return retval; +} + + +void +__timer_thread_wakeup (struct thread_node *thread) +{ + pthread_cond_broadcast (&thread->cond); +} + + +/* Compare two pthread_attr_t thread attributes for exact equality. + Returns 1 if they are equal, otherwise zero if they are not equal + or contain illegal values. This version is NPTL-specific for + performance reason. One could use the access functions to get the + values of all the fields of the attribute structure. */ +static int +thread_attr_compare (const pthread_attr_t *left, const pthread_attr_t *right) +{ + struct pthread_attr *ileft = (struct pthread_attr *) left; + struct pthread_attr *iright = (struct pthread_attr *) right; + + return (ileft->flags == iright->flags + && ileft->schedpolicy == iright->schedpolicy + && (ileft->schedparam.sched_priority + == iright->schedparam.sched_priority) + && ileft->guardsize == iright->guardsize + && ileft->stackaddr == iright->stackaddr + && ileft->stacksize == iright->stacksize + && ((ileft->cpuset == NULL && iright->cpuset == NULL) + || (ileft->cpuset != NULL && iright->cpuset != NULL + && ileft->cpusetsize == iright->cpusetsize + && memcmp (ileft->cpuset, iright->cpuset, + ileft->cpusetsize) == 0))); +} + + +/* Search the list of active threads and find one which has matching + attributes. Global mutex lock must be held by caller. */ +struct thread_node * +__timer_thread_find_matching (const pthread_attr_t *desired_attr, + clockid_t desired_clock_id) +{ + struct list_links *iter = list_first (&thread_active_list); + + while (iter != list_null (&thread_active_list)) + { + struct thread_node *candidate = thread_links2ptr (iter); + + if (thread_attr_compare (desired_attr, &candidate->attr) + && desired_clock_id == candidate->clock_id) + return candidate; + + iter = list_next (iter); + } + + return NULL; +} + + +/* Grab a free timer structure from the global free list. The global + lock must be held by the caller. */ +struct timer_node * +__timer_alloc (void) +{ + struct list_links *node = list_first (&timer_free_list); + + if (node != list_null (&timer_free_list)) + { + struct timer_node *timer = timer_links2ptr (node); + list_unlink_ip (node); + timer->inuse = TIMER_INUSE; + timer->refcount = 1; + return timer; + } + + return NULL; +} + + +/* Return a timer structure to the global free list. The global lock + must be held by the caller. */ +void +__timer_dealloc (struct timer_node *timer) +{ + assert (timer->refcount == 0); + timer->thread = NULL; /* Break association between timer and thread. */ + timer->inuse = TIMER_FREE; + list_append (&timer_free_list, &timer->links); +} + + +/* Thread cancellation handler which unlocks a mutex. */ +void +__timer_mutex_cancel_handler (void *arg) +{ + pthread_mutex_unlock (arg); +} diff --git a/libpthread/nptl/sysdeps/pthread/timer_settime.c b/libpthread/nptl/sysdeps/pthread/timer_settime.c new file mode 100644 index 000000000..592b5271b --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/timer_settime.c @@ -0,0 +1,137 @@ +/* Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku <kaz@ashi.footprints.net>. + + 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 <errno.h> +#include <pthread.h> +#include <time.h> + +#include "posix-timer.h" + + +/* Set timer TIMERID to VALUE, returning old value in OVLAUE. */ +int +timer_settime (timerid, flags, value, ovalue) + timer_t timerid; + int flags; + const struct itimerspec *value; + struct itimerspec *ovalue; +{ + struct timer_node *timer; + struct thread_node *thread = NULL; + struct timespec now; + int have_now = 0, need_wakeup = 0; + int retval = -1; + + timer = timer_id2ptr (timerid); + if (timer == NULL) + { + __set_errno (EINVAL); + goto bail; + } + + if (value->it_interval.tv_nsec < 0 + || value->it_interval.tv_nsec >= 1000000000 + || value->it_value.tv_nsec < 0 + || value->it_value.tv_nsec >= 1000000000) + { + __set_errno (EINVAL); + goto bail; + } + + /* Will need to know current time since this is a relative timer; + might as well make the system call outside of the lock now! */ + + if ((flags & TIMER_ABSTIME) == 0) + { + clock_gettime (timer->clock, &now); + have_now = 1; + } + + pthread_mutex_lock (&__timer_mutex); + timer_addref (timer); + + /* One final check of timer validity; this one is possible only + until we have the mutex, because it accesses the inuse flag. */ + + if (! timer_valid(timer)) + { + __set_errno (EINVAL); + goto unlock_bail; + } + + if (ovalue != NULL) + { + ovalue->it_interval = timer->value.it_interval; + + if (timer->armed) + { + if (! have_now) + { + pthread_mutex_unlock (&__timer_mutex); + clock_gettime (timer->clock, &now); + have_now = 1; + pthread_mutex_lock (&__timer_mutex); + timer_addref (timer); + } + + timespec_sub (&ovalue->it_value, &timer->expirytime, &now); + } + else + { + ovalue->it_value.tv_sec = 0; + ovalue->it_value.tv_nsec = 0; + } + } + + timer->value = *value; + + list_unlink_ip (&timer->links); + timer->armed = 0; + + thread = timer->thread; + + /* A value of { 0, 0 } causes the timer to be stopped. */ + if (value->it_value.tv_sec != 0 + || __builtin_expect (value->it_value.tv_nsec != 0, 1)) + { + if ((flags & TIMER_ABSTIME) != 0) + /* The user specified the expiration time. */ + timer->expirytime = value->it_value; + else + timespec_add (&timer->expirytime, &now, &value->it_value); + + /* Only need to wake up the thread if timer is inserted + at the head of the queue. */ + if (thread != NULL) + need_wakeup = __timer_thread_queue_timer (thread, timer); + timer->armed = 1; + } + + retval = 0; + +unlock_bail: + timer_delref (timer); + pthread_mutex_unlock (&__timer_mutex); + +bail: + if (thread != NULL && need_wakeup) + __timer_thread_wakeup (thread); + + return retval; +} diff --git a/libpthread/nptl/sysdeps/pthread/tpp.c b/libpthread/nptl/sysdeps/pthread/tpp.c new file mode 100644 index 000000000..9adab791b --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/tpp.c @@ -0,0 +1,172 @@ +/* Thread Priority Protect helpers. + Copyright (C) 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2006. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <atomic.h> +#include <errno.h> +#include <pthreadP.h> +#include <sched.h> +#include <stdlib.h> +#include "uClibc-glue.h" + +int __sched_fifo_min_prio = -1; +int __sched_fifo_max_prio = -1; + +void +__init_sched_fifo_prio (void) +{ + __sched_fifo_max_prio = sched_get_priority_max (SCHED_FIFO); + atomic_write_barrier (); + __sched_fifo_min_prio = sched_get_priority_min (SCHED_FIFO); +} + +int +__pthread_tpp_change_priority (int previous_prio, int new_prio) +{ + struct pthread *self = THREAD_SELF; + struct priority_protection_data *tpp = THREAD_GETMEM (self, tpp); + + if (tpp == NULL) + { + if (__sched_fifo_min_prio == -1) + __init_sched_fifo_prio (); + + size_t size = sizeof *tpp; + size += (__sched_fifo_max_prio - __sched_fifo_min_prio + 1) + * sizeof (tpp->priomap[0]); + tpp = calloc (size, 1); + if (tpp == NULL) + return ENOMEM; + tpp->priomax = __sched_fifo_min_prio - 1; + THREAD_SETMEM (self, tpp, tpp); + } + + assert (new_prio == -1 + || (new_prio >= __sched_fifo_min_prio + && new_prio <= __sched_fifo_max_prio)); + assert (previous_prio == -1 + || (previous_prio >= __sched_fifo_min_prio + && previous_prio <= __sched_fifo_max_prio)); + + int priomax = tpp->priomax; + int newpriomax = priomax; + if (new_prio != -1) + { + if (tpp->priomap[new_prio - __sched_fifo_min_prio] + 1 == 0) + return EAGAIN; + ++tpp->priomap[new_prio - __sched_fifo_min_prio]; + if (new_prio > priomax) + newpriomax = new_prio; + } + + if (previous_prio != -1) + { + if (--tpp->priomap[previous_prio - __sched_fifo_min_prio] == 0 + && priomax == previous_prio + && previous_prio > new_prio) + { + int i; + for (i = previous_prio - 1; i >= __sched_fifo_min_prio; --i) + if (tpp->priomap[i - __sched_fifo_min_prio]) + break; + newpriomax = i; + } + } + + if (priomax == newpriomax) + return 0; + + lll_lock (self->lock, LLL_PRIVATE); + + tpp->priomax = newpriomax; + + int result = 0; + + if ((self->flags & ATTR_FLAG_SCHED_SET) == 0) + { + if (__sched_getparam (self->tid, &self->schedparam) != 0) + result = errno; + else + self->flags |= ATTR_FLAG_SCHED_SET; + } + + if ((self->flags & ATTR_FLAG_POLICY_SET) == 0) + { + self->schedpolicy = __sched_getscheduler (self->tid); + if (self->schedpolicy == -1) + result = errno; + else + self->flags |= ATTR_FLAG_POLICY_SET; + } + + if (result == 0) + { + struct sched_param sp = self->schedparam; + if (sp.sched_priority < newpriomax || sp.sched_priority < priomax) + { + if (sp.sched_priority < newpriomax) + sp.sched_priority = newpriomax; + + if (__sched_setscheduler (self->tid, self->schedpolicy, &sp) < 0) + result = errno; + } + } + + lll_unlock (self->lock, LLL_PRIVATE); + + return result; +} + +int +__pthread_current_priority (void) +{ + struct pthread *self = THREAD_SELF; + if ((self->flags & (ATTR_FLAG_POLICY_SET | ATTR_FLAG_SCHED_SET)) + == (ATTR_FLAG_POLICY_SET | ATTR_FLAG_SCHED_SET)) + return self->schedparam.sched_priority; + + int result = 0; + + lll_lock (self->lock, LLL_PRIVATE); + + if ((self->flags & ATTR_FLAG_SCHED_SET) == 0) + { + if (__sched_getparam (self->tid, &self->schedparam) != 0) + result = -1; + else + self->flags |= ATTR_FLAG_SCHED_SET; + } + + if ((self->flags & ATTR_FLAG_POLICY_SET) == 0) + { + self->schedpolicy = __sched_getscheduler (self->tid); + if (self->schedpolicy == -1) + result = -1; + else + self->flags |= ATTR_FLAG_POLICY_SET; + } + + if (result != -1) + result = self->schedparam.sched_priority; + + lll_unlock (self->lock, LLL_PRIVATE); + + return result; +} diff --git a/libpthread/nptl/sysdeps/pthread/uClibc-glue.h b/libpthread/nptl/sysdeps/pthread/uClibc-glue.h new file mode 100644 index 000000000..b957dedc9 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/uClibc-glue.h @@ -0,0 +1,47 @@ +#ifndef _UCLIBC_GLUE_H +#define _UCLIBC_GLUE_H 1 + +#include <features.h> +#include <sys/cdefs.h> +#include <bits/uClibc_page.h> + +#ifdef IS_IN_libpthread +#include <bits/kernel-features.h> + +#ifndef __GLIBC_HAVE_LONG_LONG +# define __GLIBC_HAVE_LONG_LONG +#endif + +#define __getpagesize getpagesize +#define __sched_get_priority_max sched_get_priority_max +#define __sched_get_priority_min sched_get_priority_min +#define __sched_getscheduler sched_getscheduler +#define __sched_setscheduler sched_setscheduler +#define __sched_getparam sched_getparam +#define __getpid getpid +#define __gettimeofday gettimeofday +#define __poll poll +#define __sysctl sysctl +#define __open open +#define __read read +#define __close close +#define __on_exit on_exit +#define __libc_current_sigrtmin_private __libc_current_sigrtmin +#define __clone clone + +extern void *__libc_stack_end; +extern int __cxa_atexit (void (*func) (void *), void *arg, void *d); + +#endif /* IS_IN_libpthread */ + +#ifdef __UCLIBC_HAS_XLOCALE__ +# define __uselocale(x) uselocale(x) +#else +# define __uselocale(x) ((void)0) +#endif + +/* Use a funky version in a probably vein attempt at preventing gdb + * from dlopen()'ing glibc's libthread_db library... */ +#define VERSION __stringify(__UCLIBC_MAJOR__) "." __stringify(__UCLIBC_MINOR__) "." __stringify(__UCLIBC_SUBLEVEL__) + +#endif diff --git a/libpthread/nptl/sysdeps/pthread/unwind-forcedunwind.c b/libpthread/nptl/sysdeps/pthread/unwind-forcedunwind.c new file mode 100644 index 000000000..273c8bb3f --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/unwind-forcedunwind.c @@ -0,0 +1,151 @@ +/* Copyright (C) 2003, 2005, 2006, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>. + + 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 <dlfcn.h> +#include <stdio.h> +#include <unwind.h> +#include <pthreadP.h> +#include <sysdep.h> +#include <libgcc_s.h> + +#define __libc_dlopen(x) dlopen(x, (RTLD_LOCAL | RTLD_LAZY)) +#define __libc_dlsym dlsym +#define __libc_dlclose dlclose + +static void *libgcc_s_handle; +static void (*libgcc_s_resume) (struct _Unwind_Exception *exc); +static _Unwind_Reason_Code (*libgcc_s_personality) + (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *, + struct _Unwind_Context *); +static _Unwind_Reason_Code (*libgcc_s_forcedunwind) + (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *); +static _Unwind_Word (*libgcc_s_getcfa) (struct _Unwind_Context *); + +void +__attribute_noinline__ +pthread_cancel_init (void) +{ + void *resume; + void *personality; + void *forcedunwind; + void *getcfa; + void *handle; + + if (__builtin_expect (libgcc_s_handle != NULL, 1)) + { + /* Force gcc to reload all values. */ + __asm__ volatile ("" ::: "memory"); + return; + } + + handle = __libc_dlopen (LIBGCC_S_SO); + + if (handle == NULL + || (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL + || (personality = __libc_dlsym (handle, "__gcc_personality_v0")) == NULL + || (forcedunwind = __libc_dlsym (handle, "_Unwind_ForcedUnwind")) + == NULL + || (getcfa = __libc_dlsym (handle, "_Unwind_GetCFA")) == NULL +#ifdef ARCH_CANCEL_INIT + || ARCH_CANCEL_INIT (handle) +#endif + ) + { + printf (LIBGCC_S_SO " must be installed for pthread_cancel to work\n"); + abort(); + } + + PTR_MANGLE (resume); + libgcc_s_resume = resume; + PTR_MANGLE (personality); + libgcc_s_personality = personality; + PTR_MANGLE (forcedunwind); + libgcc_s_forcedunwind = forcedunwind; + PTR_MANGLE (getcfa); + libgcc_s_getcfa = getcfa; + /* Make sure libgcc_s_handle is written last. Otherwise, + pthread_cancel_init might return early even when the pointer the + caller is interested in is not initialized yet. */ + atomic_write_barrier (); + libgcc_s_handle = handle; +} + +void +__libc_freeres_fn_section +__unwind_freeres (void) +{ + void *handle = libgcc_s_handle; + if (handle != NULL) + { + libgcc_s_handle = NULL; + __libc_dlclose (handle); + } +} + +void +_Unwind_Resume (struct _Unwind_Exception *exc) +{ + if (__builtin_expect (libgcc_s_handle == NULL, 0)) + pthread_cancel_init (); + + void (*resume) (struct _Unwind_Exception *exc) = libgcc_s_resume; + PTR_DEMANGLE (resume); + resume (exc); +} + +_Unwind_Reason_Code +__gcc_personality_v0 (int version, _Unwind_Action actions, + _Unwind_Exception_Class exception_class, + struct _Unwind_Exception *ue_header, + struct _Unwind_Context *context) +{ + if (__builtin_expect (libgcc_s_handle == NULL, 0)) + pthread_cancel_init (); + + _Unwind_Reason_Code (*personality) + (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *, + struct _Unwind_Context *) = libgcc_s_personality; + PTR_DEMANGLE (personality); + return personality (version, actions, exception_class, ue_header, context); +} + +_Unwind_Reason_Code +_Unwind_ForcedUnwind (struct _Unwind_Exception *exc, _Unwind_Stop_Fn stop, + void *stop_argument) +{ + if (__builtin_expect (libgcc_s_handle == NULL, 0)) + pthread_cancel_init (); + + _Unwind_Reason_Code (*forcedunwind) + (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *) + = libgcc_s_forcedunwind; + PTR_DEMANGLE (forcedunwind); + return forcedunwind (exc, stop, stop_argument); +} + +_Unwind_Word +_Unwind_GetCFA (struct _Unwind_Context *context) +{ + if (__builtin_expect (libgcc_s_handle == NULL, 0)) + pthread_cancel_init (); + + _Unwind_Word (*getcfa) (struct _Unwind_Context *) = libgcc_s_getcfa; + PTR_DEMANGLE (getcfa); + return getcfa (context); +} diff --git a/libpthread/nptl/sysdeps/pthread/unwind-resume.c b/libpthread/nptl/sysdeps/pthread/unwind-resume.c new file mode 100644 index 000000000..94da075d1 --- /dev/null +++ b/libpthread/nptl/sysdeps/pthread/unwind-resume.c @@ -0,0 +1,76 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>. + + 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 <dlfcn.h> +#include <stdio.h> +#include <stdlib.h> +#include <unwind.h> +#include <libgcc_s.h> + +#define __libc_dlopen(x) dlopen(x, (RTLD_LOCAL | RTLD_LAZY)) +#define __libc_dlsym dlsym +#define __libc_dlclose dlclose + +static void (*libgcc_s_resume) (struct _Unwind_Exception *exc); +static _Unwind_Reason_Code (*libgcc_s_personality) + (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *, + struct _Unwind_Context *); + +extern +void abort(void); + +static void +init (void) +{ + void *resume, *personality; + void *handle; + resume = personality = NULL; + handle = dlopen (LIBGCC_S_SO, (RTLD_LOCAL | RTLD_LAZY)); + + if (handle == NULL + || (resume = dlsym (handle, "_Unwind_Resume")) == NULL + || (personality = dlsym (handle, "__gcc_personality_v0")) == NULL) + { + printf (LIBGCC_S_SO " must be installed for pthread_cancel to work\n"); + abort(); + } + + libgcc_s_resume = resume; + libgcc_s_personality = personality; +} + +void +_Unwind_Resume (struct _Unwind_Exception *exc) +{ + if (__builtin_expect (libgcc_s_resume == NULL, 0)) + init (); + libgcc_s_resume (exc); +} + +_Unwind_Reason_Code +__gcc_personality_v0 (int version, _Unwind_Action actions, + _Unwind_Exception_Class exception_class, + struct _Unwind_Exception *ue_header, + struct _Unwind_Context *context) +{ + if (__builtin_expect (libgcc_s_personality == NULL, 0)) + init (); + return libgcc_s_personality (version, actions, exception_class, + ue_header, context); +} diff --git a/libpthread/nptl/sysdeps/sh/Makefile b/libpthread/nptl/sysdeps/sh/Makefile new file mode 100644 index 000000000..81bddf688 --- /dev/null +++ b/libpthread/nptl/sysdeps/sh/Makefile @@ -0,0 +1,3 @@ +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif diff --git a/libpthread/nptl/sysdeps/sh/Makefile.arch b/libpthread/nptl/sysdeps/sh/Makefile.arch new file mode 100644 index 000000000..541901cc0 --- /dev/null +++ b/libpthread/nptl/sysdeps/sh/Makefile.arch @@ -0,0 +1,56 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_SSRC = pthread_spin_unlock.S pthread_spin_trylock.S +libpthread_CSRC = pthread_spin_lock.c pthread_spin_init.c + +ASFLAGS-pthread_spin_unlock.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +ASFLAGS-pthread_spin_trylock.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + +CFLAGS-pthread_spin_lock.c += -D_GNU_SOURCE + +CFLAGS-sh = $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +PTHREAD_ARCH_DIR := $(top_srcdir)libpthread/nptl/sysdeps/sh +PTHREAD_ARCH_OUT := $(top_builddir)libpthread/nptl/sysdeps/sh +PTHREAD_ARCH_OBJ := $(patsubst %.S,$(PTHREAD_ARCH_OUT)/%.o,$(libpthread_SSRC)) +PTHREAD_ARCH_OBJ += $(patsubst %.c,$(PTHREAD_ARCH_OUT)/%.o,$(libpthread_CSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(PTHREAD_ARCH_OBJ:.o=.os) +else +libpthread-a-y += $(PTHREAD_ARCH_OBJ) +endif +libpthread-so-y += $(PTHREAD_ARCH_OBJ:.o=.oS) + +libpthread-nomulti-y += $(PTHREAD_ARCH_OBJ) + +objclean-y += nptl_arch_clean +headers_clean-y += nptl_arch_headers_clean + +# +# Create 'tcb-offsets.h' header file. +# +CFLAGS-tcb-offsets.c = -S + +$(PTHREAD_ARCH_OUT)/tcb-offsets.c: $(PTHREAD_ARCH_DIR)/tcb-offsets.sym + $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ + +$(PTHREAD_ARCH_OUT)/tcb-offsets.s: $(PTHREAD_ARCH_OUT)/tcb-offsets.c + $(compile.c) + +$(PTHREAD_ARCH_OUT)/tcb-offsets.h: $(PTHREAD_ARCH_OUT)/tcb-offsets.s + $(do_sed) -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $@ + +pregen-headers-$(UCLIBC_HAS_THREADS_NATIVE) += $(PTHREAD_ARCH_OUT)/tcb-offsets.h + +nptl_arch_headers_clean: + $(do_rm) $(addprefix $(PTHREAD_ARCH_OUT)/tcb-offsets., c s h) + +nptl_arch_clean: + $(do_rm) $(addprefix $(PTHREAD_ARCH_OUT)/*., o os oS) diff --git a/libpthread/nptl/sysdeps/sh/dl-tls.h b/libpthread/nptl/sysdeps/sh/dl-tls.h new file mode 100644 index 000000000..98e2f1904 --- /dev/null +++ b/libpthread/nptl/sysdeps/sh/dl-tls.h @@ -0,0 +1,29 @@ +/* Thread-local storage handling in the ELF dynamic linker. SH version. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + + +extern void *__tls_get_addr (tls_index *ti); diff --git a/libpthread/nptl/sysdeps/sh/jmpbuf-unwind.h b/libpthread/nptl/sysdeps/sh/jmpbuf-unwind.h new file mode 100644 index 000000000..41c3c3984 --- /dev/null +++ b/libpthread/nptl/sysdeps/sh/jmpbuf-unwind.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 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 <setjmp.h> +#include <stdint.h> +#include <unwind.h> + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ + _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(jmpbuf, address, adj) \ + ((uintptr_t) (address) - (adj) < (uintptr_t) (jmpbuf)[0].__regs[7] - (adj)) + +extern __typeof(longjmp) __libc_longjmp attribute_noreturn; + +/* We use the normal lobngjmp for unwinding. */ +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/libpthread/nptl/sysdeps/sh/pthread_spin_init.c b/libpthread/nptl/sysdeps/sh/pthread_spin_init.c new file mode 100644 index 000000000..0a47981aa --- /dev/null +++ b/libpthread/nptl/sysdeps/sh/pthread_spin_init.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Not needed. pthread_spin_init is an alias for pthread_spin_unlock. */ diff --git a/libpthread/nptl/sysdeps/sh/pthread_spin_lock.c b/libpthread/nptl/sysdeps/sh/pthread_spin_lock.c new file mode 100644 index 000000000..d158183f0 --- /dev/null +++ b/libpthread/nptl/sysdeps/sh/pthread_spin_lock.c @@ -0,0 +1,35 @@ +/* Copyright (C) 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; 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_lock (lock) + pthread_spinlock_t *lock; +{ + unsigned int val; + + do + __asm__ volatile ("tas.b @%1; movt %0" + : "=&r" (val) + : "r" (lock) + : "memory"); + while (val == 0); + + return 0; +} diff --git a/libpthread/nptl/sysdeps/sh/pthread_spin_trylock.S b/libpthread/nptl/sysdeps/sh/pthread_spin_trylock.S new file mode 100644 index 000000000..18112ba23 --- /dev/null +++ b/libpthread/nptl/sysdeps/sh/pthread_spin_trylock.S @@ -0,0 +1,32 @@ +/* Copyright (C) 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthread-errnos.h> + + .globl pthread_spin_trylock + .type pthread_spin_trylock,@function + .align 5 +pthread_spin_trylock: + tas.b @r4 + bf/s 1f + mov #EBUSY, r0 + mov #0, r0 +1: + rts + nop + .size pthread_spin_trylock,.-pthread_spin_trylock diff --git a/libpthread/nptl/sysdeps/sh/pthread_spin_unlock.S b/libpthread/nptl/sysdeps/sh/pthread_spin_unlock.S new file mode 100644 index 000000000..c77acaffe --- /dev/null +++ b/libpthread/nptl/sysdeps/sh/pthread_spin_unlock.S @@ -0,0 +1,30 @@ +/* Copyright (C) 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + .globl pthread_spin_unlock + .type pthread_spin_unlock,@function + .align 5 +pthread_spin_unlock: + mov #0,r0 + rts + mov.l r0,@r4 + .size pthread_spin_unlock,.-pthread_spin_unlock + + /* The implementation of pthread_spin_init is identical. */ + .globl pthread_spin_init +pthread_spin_init = pthread_spin_unlock diff --git a/libpthread/nptl/sysdeps/sh/pthreaddef.h b/libpthread/nptl/sysdeps/sh/pthreaddef.h new file mode 100644 index 000000000..c1902fb54 --- /dev/null +++ b/libpthread/nptl/sysdeps/sh/pthreaddef.h @@ -0,0 +1,49 @@ +/* Copyright (C) 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. */ +#define STACK_ALIGN 8 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 2048 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 8 + + +/* Location of current stack frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + + +/* XXX Until we have a better place keep the definitions here. */ + +/* While there is no such syscall. */ +#define __exit_thread_inline(val) \ + while (1) { \ + if (__builtin_constant_p (val) && (val) == 0) \ + __asm__ volatile ("mov #0,r4; mov %0,r3; trapa #0x11\n\t" SYSCALL_INST_PAD \ + :: "i" (__NR_exit)); \ + else \ + __asm__ volatile ("mov %1,r4; mov %0,r3; trapa #0x11\n\t" SYSCALL_INST_PAD \ + :: "i" (__NR_exit), "r" (val)); \ + } diff --git a/libpthread/nptl/sysdeps/sh/tcb-offsets.sym b/libpthread/nptl/sysdeps/sh/tcb-offsets.sym new file mode 100644 index 000000000..753b72b2d --- /dev/null +++ b/libpthread/nptl/sysdeps/sh/tcb-offsets.sym @@ -0,0 +1,15 @@ +#include <sysdep.h> +#include <tls.h> + +RESULT offsetof (struct pthread, result) +TID offsetof (struct pthread, tid) +PID offsetof (struct pthread, pid) +CANCELHANDLING offsetof (struct pthread, cancelhandling) +CLEANUP_JMP_BUF offsetof (struct pthread, cleanup_jmp_buf) +MULTIPLE_THREADS_OFFSET offsetof (struct pthread, header.multiple_threads) +TLS_PRE_TCB_SIZE sizeof (struct pthread) +MUTEX_FUTEX offsetof (pthread_mutex_t, __data.__lock) +POINTER_GUARD offsetof (tcbhead_t, pointer_guard) +#ifndef __ASSUME_PRIVATE_FUTEX +PRIVATE_FUTEX offsetof (struct pthread, header.private_futex) +#endif diff --git a/libpthread/nptl/sysdeps/sh/tls.h b/libpthread/nptl/sysdeps/sh/tls.h new file mode 100644 index 000000000..2c538eded --- /dev/null +++ b/libpthread/nptl/sysdeps/sh/tls.h @@ -0,0 +1,182 @@ +/* Definition for thread-local data handling. NPTL/SH version. + 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 + 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. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ +# include <stdbool.h> +# include <stddef.h> +# include <stdint.h> +# include <stdlib.h> +# include <list.h> +# include <sysdep.h> +# include <bits/kernel-features.h> + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +typedef struct +{ + dtv_t *dtv; + uintptr_t pointer_guard; +} tcbhead_t; + +# define TLS_MULTIPLE_THREADS_IN_TCB 1 + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif /* __ASSEMBLER__ */ + + +/* We require TLS support in the tools. */ +#define HAVE_TLS_SUPPORT +#define HAVE___THREAD 1 +#define HAVE_TLS_MODEL_ATTRIBUTE 1 +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +#ifndef __ASSEMBLER__ + +/* Get system call information. */ +# include <sysdep.h> + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* The TLS blocks start right after the TCB. */ +# define TLS_DTV_AT_TP 1 + +/* Get the thread descriptor definition. */ +# include <descr.h> + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + ((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + ({ tcbhead_t *__tcbp; \ + __asm __volatile ("stc gbr,%0" : "=r" (__tcbp)); \ + __tcbp->dtv = (dtv);}) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) \ + (((tcbhead_t *) (tcbp))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + ({ __asm __volatile ("ldc %0,gbr" : : "r" (tcbp)); 0; }) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ tcbhead_t *__tcbp; \ + __asm __volatile ("stc gbr,%0" : "=r" (__tcbp)); \ + __tcbp->dtv;}) + +/* Return the thread descriptor for the current thread. + The contained asm must *not* be marked volatile since otherwise + assignments like + struct pthread *self = thread_self(); + do not get optimized away. */ +# define THREAD_SELF \ + ({ struct pthread *__self; \ + __asm ("stc gbr,%0" : "=r" (__self)); \ + __self - 1;}) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF \ + REGISTER (32, 32, REG_GBR * 4, -sizeof (struct pthread)) + +/* Read member of the thread descriptor directly. */ +# define THREAD_GETMEM(descr, member) (descr->member) + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +# define THREAD_GETMEM_NC(descr, member, idx) (descr->member[idx]) + +/* Set member of the thread descriptor directly. */ +# define THREAD_SETMEM(descr, member, value) \ + descr->member = (value) + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +# define THREAD_SETMEM_NC(descr, member, idx, value) \ + descr->member[idx] = (value) + +#define THREAD_GET_POINTER_GUARD() \ + ({ tcbhead_t *__tcbp; \ + __asm __volatile ("stc gbr,%0" : "=r" (__tcbp)); \ + __tcbp->pointer_guard;}) + #define THREAD_SET_POINTER_GUARD(value) \ + ({ tcbhead_t *__tcbp; \ + __asm __volatile ("stc gbr,%0" : "=r" (__tcbp)); \ + __tcbp->pointer_guard = (value);}) +#define THREAD_COPY_POINTER_GUARD(descr) \ + ({ tcbhead_t *__tcbp; \ + __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, LLL_PRIVATE); \ + } \ + 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/libpthread/nptl/sysdeps/sparc/Makefile b/libpthread/nptl/sysdeps/sparc/Makefile new file mode 100644 index 000000000..81bddf688 --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/Makefile @@ -0,0 +1,3 @@ +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif diff --git a/libpthread/nptl/sysdeps/sparc/Makefile.arch b/libpthread/nptl/sysdeps/sparc/Makefile.arch new file mode 100644 index 000000000..632b75b4f --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/Makefile.arch @@ -0,0 +1,53 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_CSRC = sparc32/pthread_spin_lock.c \ + sparc32/pthread_spin_trylock.c + +CFLAGS-pthread_spin_lock.c += -D_GNU_SOURCE + +CFLAGS-sparc = $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +PTHREAD_ARCH_DIR := $(top_srcdir)libpthread/nptl/sysdeps/sparc +PTHREAD_ARCH_OUT := $(top_builddir)libpthread/nptl/sysdeps/sparc +PTHREAD_ARCH_OBJ := $(patsubst %.S,$(PTHREAD_ARCH_OUT)/%.o,$(libpthread_SSRC)) +PTHREAD_ARCH_OBJ += $(patsubst %.c,$(PTHREAD_ARCH_OUT)/%.o,$(libpthread_CSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(PTHREAD_ARCH_OBJ:.o=.os) +else +libpthread-a-y += $(PTHREAD_ARCH_OBJ) +endif +libpthread-so-y += $(PTHREAD_ARCH_OBJ:.o=.oS) + +libpthread-nomulti-y += $(PTHREAD_ARCH_OBJ) + +objclean-y += nptl_arch_clean +headers_clean-y += nptl_arch_headers_clean + +# +# Create 'tcb-offsets.h' header file. +# +CFLAGS-tcb-offsets.c = -S + +$(PTHREAD_ARCH_OUT)/tcb-offsets.c: $(PTHREAD_ARCH_DIR)/tcb-offsets.sym + $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ + +$(PTHREAD_ARCH_OUT)/tcb-offsets.s: $(PTHREAD_ARCH_OUT)/tcb-offsets.c + $(compile.c) + +$(PTHREAD_ARCH_OUT)/tcb-offsets.h: $(PTHREAD_ARCH_OUT)/tcb-offsets.s + $(do_sed) -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $@ + +pregen-headers-$(UCLIBC_HAS_THREADS_NATIVE) += $(PTHREAD_ARCH_OUT)/tcb-offsets.h + +nptl_arch_headers_clean: + $(do_rm) $(addprefix $(PTHREAD_ARCH_OUT)/tcb-offsets., c s h) + +nptl_arch_clean: + $(do_rm) $(addprefix $(PTHREAD_ARCH_OUT)/*., o os oS) diff --git a/libpthread/nptl/sysdeps/sparc/dl-tls.h b/libpthread/nptl/sysdeps/sparc/dl-tls.h new file mode 100644 index 000000000..6edf8d525 --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/dl-tls.h @@ -0,0 +1,29 @@ +/* Thread-local storage handling in the ELF dynamic linker. SPARC version. + Copyright (C) 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + + +extern void *__tls_get_addr (tls_index *ti); diff --git a/libpthread/nptl/sysdeps/sparc/jmpbuf-unwind.h b/libpthread/nptl/sysdeps/sparc/jmpbuf-unwind.h new file mode 100644 index 000000000..6cbb37baf --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/jmpbuf-unwind.h @@ -0,0 +1,5 @@ +#if defined(__arch64__) +#include "sparc64/jmpbuf-unwind.h" +#else +#include "sparc32/jmpbuf-unwind.h" +#endif diff --git a/libpthread/nptl/sysdeps/sparc/pthreaddef.h b/libpthread/nptl/sysdeps/sparc/pthreaddef.h new file mode 100644 index 000000000..d4695c47d --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/pthreaddef.h @@ -0,0 +1,5 @@ +#if defined(__arch64__) +#include "sparc64/pthreaddef.h" +#else +#include "sparc32/pthreaddef.h" +#endif diff --git a/libpthread/nptl/sysdeps/sparc/sparc32/jmpbuf-unwind.h b/libpthread/nptl/sysdeps/sparc/sparc32/jmpbuf-unwind.h new file mode 100644 index 000000000..71a358209 --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc32/jmpbuf-unwind.h @@ -0,0 +1,32 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 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 <setjmp.h> +#include <stdint.h> +#include <unwind.h> + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ + _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ + ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_SP] - (_adj)) + +/* We use the normal longjmp for unwinding. */ +extern __typeof(longjmp) __libc_longjmp attribute_noreturn; +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/libpthread/nptl/sysdeps/sparc/sparc32/pthread_spin_lock.c b/libpthread/nptl/sysdeps/sparc/sparc32/pthread_spin_lock.c new file mode 100644 index 000000000..d3c6e3049 --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc32/pthread_spin_lock.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 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_lock (pthread_spinlock_t *lock) +{ + __asm __volatile + ("1: ldstub [%0], %%g2\n" + " orcc %%g2, 0x0, %%g0\n" + " bne,a 2f\n" + " ldub [%0], %%g2\n" + ".subsection 2\n" + "2: orcc %%g2, 0x0, %%g0\n" + " bne,a 2b\n" + " ldub [%0], %%g2\n" + " b,a 1b\n" + ".previous" + : /* no outputs */ + : "r" (lock) + : "g2", "memory", "cc"); + return 0; +} diff --git a/libpthread/nptl/sysdeps/sparc/sparc32/pthread_spin_trylock.c b/libpthread/nptl/sysdeps/sparc/sparc32/pthread_spin_trylock.c new file mode 100644 index 000000000..bcc3158fd --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc32/pthread_spin_trylock.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 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 <errno.h> +#include "pthreadP.h" + +int +pthread_spin_trylock (pthread_spinlock_t *lock) +{ + int res; + __asm __volatile ("ldstub [%1], %0" : "=r" (res) : "r" (lock) : "memory"); + return res == 0 ? 0 : EBUSY; +} diff --git a/libpthread/nptl/sysdeps/sparc/sparc32/pthreaddef.h b/libpthread/nptl/sysdeps/sparc/sparc32/pthreaddef.h new file mode 100644 index 000000000..9908df9e9 --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc32/pthreaddef.h @@ -0,0 +1,40 @@ +/* Copyright (C) 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. */ +#define STACK_ALIGN 16 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 2048 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 16 + + +/* Location of current stack frame. */ +#define CURRENT_STACK_FRAME (stack_pointer + (2 * 64)) +register char *stack_pointer __asm__("%sp"); + +/* XXX Until we have a better place keep the definitions here. */ + +/* While there is no such syscall. */ +#define __exit_thread_inline(val) \ + INLINE_SYSCALL (exit, 1, (val)) diff --git a/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_lock.c b/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_lock.c new file mode 100644 index 000000000..8880f535b --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_lock.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 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_lock (pthread_spinlock_t *lock) +{ + __asm __volatile + ("1: ldstub [%0], %%g2\n" + " brnz,pn %%g2, 2f\n" + " membar #StoreLoad | #StoreStore\n" + ".subsection 2\n" + "2: ldub [%0], %%g2\n" + " brnz,pt %%g2, 2b\n" + " membar #LoadLoad\n" + " b,a,pt %%xcc, 1b\n" + ".previous" + : /* no outputs */ + : "r" (lock) + : "g2", "memory"); + return 0; +} diff --git a/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_trylock.c b/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_trylock.c new file mode 100644 index 000000000..3b20a2180 --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_trylock.c @@ -0,0 +1 @@ +#include <sparc64/pthread_spin_trylock.c> diff --git a/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_unlock.c b/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_unlock.c new file mode 100644 index 000000000..482cbe3d7 --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_unlock.c @@ -0,0 +1 @@ +#include <sparc64/pthread_spin_unlock.c> diff --git a/libpthread/nptl/sysdeps/sparc/sparc64/jmpbuf-unwind.h b/libpthread/nptl/sysdeps/sparc/sparc64/jmpbuf-unwind.h new file mode 100644 index 000000000..5cef8b1cf --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc64/jmpbuf-unwind.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 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 <setjmp.h> +#include <stdint.h> +#include <unwind.h> + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ + _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ + ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_SP] - (_adj)) + +/* We use the normal lobngjmp for unwinding. */ +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_lock.c b/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_lock.c new file mode 100644 index 000000000..77171d9b9 --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_lock.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 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_lock (pthread_spinlock_t *lock) +{ + __asm __volatile + ("1: ldstub [%0], %%g5\n" + " brnz,pn %%g5, 2f\n" + " membar #StoreLoad | #StoreStore\n" + ".subsection 2\n" + "2: ldub [%0], %%g5\n" + " brnz,pt %%g5, 2b\n" + " membar #LoadLoad\n" + " b,a,pt %%xcc, 1b\n" + ".previous" + : /* no outputs */ + : "r" (lock) + : "g5", "memory"); + return 0; +} diff --git a/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_trylock.c b/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_trylock.c new file mode 100644 index 000000000..2bda809da --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_trylock.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 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 <errno.h> +#include "pthreadP.h" + +int +pthread_spin_trylock (pthread_spinlock_t *lock) +{ + int res; + __asm __volatile + ("ldstub [%1], %0\n" + "membar #StoreLoad | #StoreStore" + : "=r" (res) + : "r" (lock) + : "memory"); + return res == 0 ? 0 : EBUSY; +} diff --git a/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_unlock.c b/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_unlock.c new file mode 100644 index 000000000..7037675a2 --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc64/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 <paulus@au.ibm.com>, 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 <atomic.h> + +int +pthread_spin_unlock (pthread_spinlock_t *lock) +{ + __asm __volatile ("membar #StoreStore | #LoadStore"); + *lock = 0; + return 0; +} diff --git a/libpthread/nptl/sysdeps/sparc/sparc64/pthreaddef.h b/libpthread/nptl/sysdeps/sparc/sparc64/pthreaddef.h new file mode 100644 index 000000000..ec7651211 --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/sparc64/pthreaddef.h @@ -0,0 +1,40 @@ +/* Copyright (C) 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (4 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. */ +#define STACK_ALIGN 16 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 4096 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 16 + + +/* Location of current stack frame. */ +#define CURRENT_STACK_FRAME (stack_pointer + (2 * 128)) +register char *stack_pointer __asm__("%sp"); + +/* XXX Until we have a better place keep the definitions here. */ + +/* While there is no such syscall. */ +#define __exit_thread_inline(val) \ + INLINE_SYSCALL (exit, 1, (val)) diff --git a/libpthread/nptl/sysdeps/sparc/tcb-offsets.sym b/libpthread/nptl/sysdeps/sparc/tcb-offsets.sym new file mode 100644 index 000000000..923af8a5b --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/tcb-offsets.sym @@ -0,0 +1,7 @@ +#include <sysdep.h> +#include <tls.h> + +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) +POINTER_GUARD offsetof (tcbhead_t, pointer_guard) +PID offsetof (struct pthread, pid) +TID offsetof (struct pthread, tid) diff --git a/libpthread/nptl/sysdeps/sparc/tls.h b/libpthread/nptl/sysdeps/sparc/tls.h new file mode 100644 index 000000000..e93542c9f --- /dev/null +++ b/libpthread/nptl/sysdeps/sparc/tls.h @@ -0,0 +1,181 @@ +/* Definitions for thread-local data handling. NPTL/sparc version. + 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 + 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. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ +# include <stdbool.h> +# include <stddef.h> +# include <stdint.h> +# include <stdlib.h> +# include <list.h> +# include <bits/kernel-features.h> + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessary the + thread descriptor used by libpthread. */ + 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 +#ifndef __ASSUME_PRIVATE_FUTEX + int private_futex; +#endif +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif /* __ASSEMBLER__ */ + +/* We require TLS support in the tools. */ +#define HAVE_TLS_SUPPORT +#define HAVE___THREAD 1 +#define HAVE_TLS_MODEL_ATTRIBUTE 1 + +/* Signal that TLS support is available. */ +#define USE_TLS 1 + +#ifndef __ASSEMBLER__ +/* Get system call information. */ +# include <sysdep.h> + +/* Get the thread descriptor definition. */ +# include <descr.h> + +register struct pthread *__thread_self __asm__("%g7"); + +/* This is the size of the initial TCB. Can't be just sizeof (tcbhead_t), + because NPTL getpid, __libc_alloca_cutoff etc. need (almost) the whole + struct pthread even when not linked with -lpthread. */ +# define TLS_INIT_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(DTV) \ + (((tcbhead_t *) __thread_self)->dtv = (DTV)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +/* Code to initially initialize the thread pointer. */ +# define TLS_INIT_TP(descr, secondcall) \ + (__thread_self = (__typeof (__thread_self)) (descr), NULL) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) __thread_self)->dtv) + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF_INCLUDE <sys/ucontext.h> +# define DB_THREAD_SELF \ + REGISTER (32, 32, REG_G7 * 4, 0) REGISTER (64, 64, REG_G7 * 8, 0) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + descr->member +#define THREAD_GETMEM_NC(descr, member, idx) \ + descr->member[idx] +#define THREAD_SETMEM(descr, member, value) \ + descr->member = (value) +#define THREAD_SETMEM_NC(descr, member, idx, value) \ + descr->member[idx] = (value) + +/* Set the stack guard field in TCB head. */ +#define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.stack_guard, value) +# define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->header.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, header.stack_guard)) + +/* Get/set the stack guard field in TCB head. */ +#define THREAD_GET_POINTER_GUARD() \ + THREAD_GETMEM (THREAD_SELF, header.pointer_guard) +#define THREAD_SET_POINTER_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.pointer_guard, value) +# 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, LLL_PRIVATE); \ + } \ + 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/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile new file mode 100644 index 000000000..34d647527 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../../../ +top_builddir=../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile.in b/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile.in new file mode 100644 index 000000000..ac642f272 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile.in @@ -0,0 +1,256 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_CSRC = pthread_attr_getaffinity.c \ + pthread_attr_setaffinity.c pthread_getaffinity.c \ + pthread_getcpuclockid.c pthread_kill.c \ + pthread_mutex_cond_lock.c pthread_setaffinity.c \ + pthread_yield.c sem_post.c sem_timedwait.c \ + pthread_sigqueue.c \ + sem_trywait.c sem_wait.c pt-fork.c \ + sigtimedwait.c sigwaitinfo.c sigwait.c pt-sleep.c + +libpthread_SSRC = #ptw-close.S ptw-open.S ptw-waitid.S ptw-waidpid.S ptw-write.S + +libc_CSRC = libc_pthread_init.c libc_multiple_threads.c \ + register-atfork.c unregister-atfork.c getpid.c \ + raise.c sleep.c jmp-unwind.c + +# These provide both a cancellable and a not cancellable implementation +libc_SSRC = close.S open.S write.S read.S waitpid.S + +librt_CSRC := mq_notify.c timer_create.c timer_delete.c \ + timer_getoverr.c timer_gettime.c timer_routines.c \ + timer_settime.c + + +ifeq ($(TARGET_ARCH),alpha) +libpthread_CSRC += lowlevellock.c +libc_CSRC += libc-lowlevellock.c +librt_CSRC := mq_notify.c +endif + +ifeq ($(TARGET_ARCH),arm) +libc_SSRC := $(filter-out waitpid.S,$(libc_SSRC)) +libpthread_CSRC += lowlevelrobustlock.c +endif + +ifeq ($(TARGET_ARCH),mips) +libpthread_CSRC += lowlevellock.c lowlevelrobustlock.c +libc_CSRC += libc-lowlevellock.c +endif + +ifeq ($(TARGET_ARCH),powerpc) +libpthread_CSRC += lowlevellock.c +libc_CSRC += libc-lowlevellock.c +librt_CSRC := mq_notify.c +endif + +ifeq ($(TARGET_ARCH),sparc) +libpthread_CSRC += __syscall_error.c lowlevelrobustlock.c +librt_CSRC += __syscall_error.c +endif + +ifeq ($(TARGET_ARCH),sh) +SH_PTHREAD_SPECIFIC := sem_post.c sem_wait.c sem_timedwait.c sem_trywait.c +libpthread_CSRC := $(filter-out $(SH_PTHREAD_SPECIFIC),$(libpthread_CSRC)) +endif + +ifeq ($(TARGET_ARCH),i386) +X86_PTHREAD_SPECIFIC := sem_post.c sem_wait.c sem_timedwait.c sem_trywait.c +libpthread_CSRC := $(filter-out $(X86_PTHREAD_SPECIFIC),$(libpthread_CSRC)) +endif + +ifeq ($(TARGET_ARCH),x86_64) +libc_SSRC := $(filter-out waitpid.S,$(libc_SSRC)) +X64_PTHREAD_SPECIFIC := sem_post.c sem_wait.c sem_timedwait.c sem_trywait.c +libpthread_CSRC := $(filter-out $(X64_PTHREAD_SPECIFIC),$(libpthread_CSRC)) +endif + +CFLAGS-pthread_getcpuclockid.c = -I$(top_srcdir)librt +CFLAGS-pt-pread_pwrite.c = -I$(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH) \ + -I$(top_srcdir)libc/sysdeps/linux/common +CFLAGS-mq_notify.c = -I$(top_srcdir)librt -DIS_IN_librt=1 +CFLAGS-timer_create.c = -I$(top_srcdir)librt -DIS_IN_librt=1 +CFLAGS-timer_delete.c = -I$(top_srcdir)librt -DIS_IN_librt=1 +CFLAGS-timer_getoverr.c = -I$(top_srcdir)librt -DIS_IN_librt=1 +CFLAGS-timer_gettime.c = -I$(top_srcdir)librt -DIS_IN_librt=1 +CFLAGS-timer_routines.c = -I$(top_srcdir)librt -DIS_IN_librt=1 +CFLAGS-timer_settime.c = -I$(top_srcdir)librt -DIS_IN_librt=1 + +CFLAGS-linux = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +CFLAGS-OMIT-libc_pthread_init.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-libc_multiple_threads.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-register-atfork.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-unregister-atfork.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-getpid.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-raise.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-sleep.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-libc-lowlevellock.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + +CFLAGS-OMIT-close.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-open.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-read.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-write.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-waitpid.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + +CFLAGS-OMIT-mq_notify.c = -DIS_IN_libpthread=1 +CFLAGS-OMIT-timer_create.c = -DIS_IN_libpthread=1 +CFLAGS-OMIT-timer_delete.c = -DIS_IN_libpthread=1 +CFLAGS-OMIT-timer_getoverr.c = -DIS_IN_libpthread=1 +CFLAGS-OMIT-timer_gettime.c = -DIS_IN_libpthread=1 +CFLAGS-OMIT-timer_routines.c = -DIS_IN_libpthread=1 +CFLAGS-OMIT-timer_settime.c = -DIS_IN_libpthread=1 + +PTHREAD_LINUX_DIR := $(top_srcdir)libpthread/nptl/sysdeps/unix/sysv/linux +PTHREAD_LINUX_OUT := $(top_builddir)libpthread/nptl/sysdeps/unix/sysv/linux + +PTHREAD_LINUX_OBJ := $(patsubst %.c,$(PTHREAD_LINUX_OUT)/%.o,$(libpthread_CSRC)) +PTHREAD_LINUX_OBJ += $(patsubst %.S,$(PTHREAD_LINUX_OUT)/%.o,$(libpthread_SSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(PTHREAD_LINUX_OBJ:.o=.os) +else +libpthread-a-y += $(PTHREAD_LINUX_OBJ) +endif +libpthread-so-y += $(PTHREAD_LINUX_OBJ:.o=.oS) +libpthread-so-y += $(PTHREAD_LINUX_OUT)/pt-raise.oS +libpthread-nomulti-y += $(PTHREAD_LINUX_OBJ) + +ASFLAGS-open.S = -D_LIBC_REENTRANT +ASFLAGS-close.S = -D_LIBC_REENTRANT +ASFLAGS-read.S = -D_LIBC_REENTRANT +ASFLAGS-write.S = -D_LIBC_REENTRANT +ASFLAGS-waitpid.S = -D_LIBC_REENTRANT + +LIBC_LINUX_OBJ := $(patsubst %.c,$(PTHREAD_LINUX_OUT)/%.o,$(libc_CSRC)) +LIBC_LINUX_OBJ += $(patsubst %.S,$(PTHREAD_LINUX_OUT)/%.o,$(libc_SSRC)) + +libc-static-y += $(LIBC_LINUX_OBJ) +libc-shared-y += $(LIBC_LINUX_OBJ:.o=.oS) +libc-nomulti-y += $(LIBC_LINUX_OBJ) + +LIBRT_LINUX_OBJ := $(patsubst %.c,$(PTHREAD_LINUX_OUT)/%.o,$(librt_CSRC)) + +librt-a-y += $(LIBRT_LINUX_OBJ) +librt-so-y += $(LIBRT_LINUX_OBJ:.o=.oS) + +objclean-y += nptl_linux_clean +headers_clean-y += nptl_linux_headers_clean + +# +# Create header files. +# +CFLAGS-gen_lowlevelbarrier.c = -S +CFLAGS-gen_lowlevelcond.c = -S +CFLAGS-gen_lowlevelrwlock.c = -S +CFLAGS-gen_lowlevelrobustlock.c = -S +CFLAGS-gen_lunwindbuf.c = -S +CFLAGS-gen_lstructsem.c = -S +CFLAGS-gen_lpthread-pi-defines.c = -S + +$(PTHREAD_LINUX_OUT)/gen_lowlevelbarrier.c: $(PTHREAD_LINUX_DIR)/lowlevelbarrier.sym + $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ + +$(PTHREAD_LINUX_OUT)/gen_lowlevelcond.c: $(PTHREAD_LINUX_DIR)/lowlevelcond.sym + $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ + +$(PTHREAD_LINUX_OUT)/gen_lowlevelrwlock.c: $(PTHREAD_LINUX_DIR)/lowlevelrwlock.sym + $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ + +$(PTHREAD_LINUX_OUT)/gen_lowlevelrobustlock.c: $(PTHREAD_LINUX_DIR)/lowlevelrobustlock.sym + $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ + +$(PTHREAD_LINUX_OUT)/gen_lunwindbuf.c: $(PTHREAD_LINUX_DIR)/unwindbuf.sym + $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ + +$(PTHREAD_LINUX_OUT)/gen_lstructsem.c: $(PTHREAD_LINUX_DIR)/structsem.sym + $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ + +$(PTHREAD_LINUX_OUT)/gen_lpthread-pi-defines.c: $(PTHREAD_LINUX_DIR)/pthread-pi-defines.sym + $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ + + +$(PTHREAD_LINUX_OUT)/gen_lowlevelbarrier.s: $(PTHREAD_LINUX_OUT)/gen_lowlevelbarrier.c + $(compile.c) + +$(PTHREAD_LINUX_OUT)/gen_lowlevelcond.s: $(PTHREAD_LINUX_OUT)/gen_lowlevelcond.c + $(compile.c) + +$(PTHREAD_LINUX_OUT)/gen_lowlevelrwlock.s: $(PTHREAD_LINUX_OUT)/gen_lowlevelrwlock.c + $(compile.c) + +$(PTHREAD_LINUX_OUT)/gen_lowlevelrobustlock.s: $(PTHREAD_LINUX_OUT)/gen_lowlevelrobustlock.c + $(compile.c) + +$(PTHREAD_LINUX_OUT)/gen_lunwindbuf.s: $(PTHREAD_LINUX_OUT)/gen_lunwindbuf.c + $(compile.c) + +$(PTHREAD_LINUX_OUT)/gen_lstructsem.s: $(PTHREAD_LINUX_OUT)/gen_lstructsem.c + $(compile.c) + +$(PTHREAD_LINUX_OUT)/gen_lpthread-pi-defines.s: $(PTHREAD_LINUX_OUT)/gen_lpthread-pi-defines.c + $(compile.c) + + +$(PTHREAD_LINUX_OUT)/lowlevelbarrier.h: $(PTHREAD_LINUX_OUT)/gen_lowlevelbarrier.s + $(do_sed) -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $@ + +$(PTHREAD_LINUX_OUT)/lowlevelcond.h: $(PTHREAD_LINUX_OUT)/gen_lowlevelcond.s + $(do_sed) -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $@ + +$(PTHREAD_LINUX_OUT)/lowlevelrwlock.h: $(PTHREAD_LINUX_OUT)/gen_lowlevelrwlock.s + $(do_sed) -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $@ + +$(PTHREAD_LINUX_OUT)/lowlevelrobustlock.h: $(PTHREAD_LINUX_OUT)/gen_lowlevelrobustlock.s + $(do_sed) -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $@ + +$(PTHREAD_LINUX_OUT)/unwindbuf.h: $(PTHREAD_LINUX_OUT)/gen_lunwindbuf.s + $(do_sed) -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $@ + +$(PTHREAD_LINUX_OUT)/structsem.h: $(PTHREAD_LINUX_OUT)/gen_lstructsem.s + $(do_sed) -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $@ + +$(PTHREAD_LINUX_OUT)/pthread-pi-defines.h: $(PTHREAD_LINUX_OUT)/gen_lpthread-pi-defines.s + $(do_sed) -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $@ + +pregen-headers-$(UCLIBC_HAS_THREADS_NATIVE) += \ + $(PTHREAD_LINUX_OUT)/lowlevelbarrier.h \ + $(PTHREAD_LINUX_OUT)/lowlevelcond.h \ + $(PTHREAD_LINUX_OUT)/lowlevelrwlock.h \ + $(PTHREAD_LINUX_OUT)/lowlevelrobustlock.h \ + $(PTHREAD_LINUX_OUT)/unwindbuf.h \ + $(PTHREAD_LINUX_OUT)/structsem.h \ + $(PTHREAD_LINUX_OUT)/pthread-pi-defines.h + +HEADERS_BITS_PTHREAD := $(notdir $(wildcard $(PTHREAD_LINUX_DIR)/bits/*.h)) +ALL_HEADERS_BITS_PTHREAD := $(addprefix include/bits/,$(HEADERS_BITS_PTHREAD)) + +$(ALL_HEADERS_BITS_PTHREAD): + $(do_ln) ../../$(PTHREAD_LINUX_DIR)/bits/$(@F) $(top_builddir)$@ + +nptl_linux_headers_clean: + $(do_rm) $(addprefix $(PTHREAD_LINUX_OUT)/gen_lowlevelbarrier., c s) \ + $(addprefix $(PTHREAD_LINUX_OUT)/gen_lowlevelcond., c s) \ + $(addprefix $(PTHREAD_LINUX_OUT)/gen_lowlevelrwlock., c s) \ + $(addprefix $(PTHREAD_LINUX_OUT)/gen_lowlevelrobustlock., c s) \ + $(addprefix $(PTHREAD_LINUX_OUT)/gen_lunwindbuf., c s) \ + $(addprefix $(PTHREAD_LINUX_OUT)/gen_lstructsem., c s) \ + $(addprefix $(PTHREAD_LINUX_OUT)/gen_lpthread-pi-defines., c s) \ + $(PTHREAD_LINUX_OUT)/lowlevelbarrier.h \ + $(PTHREAD_LINUX_OUT)/lowlevelcond.h \ + $(PTHREAD_LINUX_OUT)/lowlevelrwlock.h \ + $(PTHREAD_LINUX_OUT)/lowlevelrobustlock.h \ + $(PTHREAD_LINUX_OUT)/unwindbuf.h \ + $(PTHREAD_LINUX_OUT)/structsem.h \ + $(PTHREAD_LINUX_OUT)/pthread-pi-defines.h + + +nptl_linux_clean: + $(do_rm) $(addprefix $(PTHREAD_LINUX_OUT)/*., o os oS) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/__syscall_error.c b/libpthread/nptl/sysdeps/unix/sysv/linux/__syscall_error.c new file mode 100644 index 000000000..5e109a83b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/__syscall_error.c @@ -0,0 +1,18 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org> + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <errno.h> +#include <features.h> + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +int __syscall_error(int err_no) attribute_hidden; +int __syscall_error(int err_no) +{ + __set_errno(err_no); + return -1; +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/accept.S b/libpthread/nptl/sysdeps/unix/sysv/linux/accept.S new file mode 100644 index 000000000..529763d80 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/accept.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_accept +#error Missing definition of NR_accept needed for cancellation. +#endif +PSEUDO (__libc_accept, accept, 3) +ret +PSEUDO_END(__libc_accept) +libc_hidden_def (__libc_accept) +weak_alias (__libc_accept, __accept) +libc_hidden_weak (__accept) +weak_alias (__libc_accept, accept) +libc_hidden_weak (accept) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/Makefile new file mode 100644 index 000000000..8c8084079 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/Makefile @@ -0,0 +1,2 @@ +# pull in __syscall_error routine, __sigprocmask, __syscall_rt_sigaction +libpthread-routines += ptw-sysdep ptw-sigprocmask ptw-rt_sigaction diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h new file mode 100644 index 000000000..a7c9740a0 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h @@ -0,0 +1,100 @@ +/* Minimum guaranteed maximum values for system limits. Linux/Alpha version. + Copyright (C) 1993-1998,2000,2002-2004,2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 +#ifndef ARG_MAX +# define __undef_ARG_MAX +#endif + +/* The kernel sources contain a file with all the needed information. */ +#include <linux/limits.h> + +/* 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 +/* Have to remove ARG_MAX? */ +#ifdef __undef_ARG_MAX +# undef ARG_MAX +# undef __undef_ARG_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. We are free to choose a reasonable value. */ +#define PTHREAD_STACK_MIN 24576 + +/* 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/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h new file mode 100644 index 000000000..41c0be197 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h @@ -0,0 +1,168 @@ +/* Machine-specific pthread type layouts. Alpha version. + 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 + 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. */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#define __SIZEOF_PTHREAD_ATTR_T 56 +#define __SIZEOF_PTHREAD_MUTEX_T 40 +#define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +#define __SIZEOF_PTHREAD_COND_T 48 +#define __SIZEOF_PTHREAD_CONDATTR_T 4 +#define __SIZEOF_PTHREAD_RWLOCK_T 56 +#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +#define __SIZEOF_PTHREAD_BARRIER_T 32 +#define __SIZEOF_PTHREAD_BARRIERATTR_T 4 + + +/* Thread identifiers. The structure of the attribute type is + deliberately not exposed. */ +typedef unsigned long int pthread_t; + + +typedef union +{ + char __size[__SIZEOF_PTHREAD_ATTR_T]; + long int __align; +} pthread_attr_t; + + +typedef struct __pthread_internal_list +{ + struct __pthread_internal_list *__prev; + struct __pthread_internal_list *__next; +} __pthread_list_t; + + +/* Data structures for mutex handling. The structure of the attribute + type is deliberately not exposed. */ +typedef union +{ + struct __pthread_mutex_s + { + int __lock; + unsigned int __count; + int __owner; + unsigned int __nusers; + /* KIND must stay at this position in the structure to maintain + binary compatibility. */ + int __kind; + int __spins; + __pthread_list_t __list; +#define __PTHREAD_MUTEX_HAVE_PREV 1 + } __data; + char __size[__SIZEOF_PTHREAD_MUTEX_T]; + long int __align; +} pthread_mutex_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; + int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling. The structure of + the attribute type is deliberately not exposed. */ +typedef union +{ + struct + { + int __lock; + unsigned int __futex; + __extension__ unsigned long long int __total_seq; + __extension__ unsigned long long int __wakeup_seq; + __extension__ unsigned long long int __woken_seq; + void *__mutex; + unsigned int __nwaiters; + unsigned int __broadcast_seq; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_CONDATTR_T]; + int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling. The + structure of the attribute type is deliberately not exposed. */ +typedef union +{ + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + int __writer; + int __shared; + unsigned long int __pad1; + unsigned long int __pad2; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned int __flags; + } __data; + char __size[__SIZEOF_PTHREAD_RWLOCK_T]; + long int __align; +} pthread_rwlock_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; + long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef volatile int pthread_spinlock_t; + +/* POSIX barriers data type. The structure of the type is + deliberately not exposed. */ +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIER_T]; + long int __align; +} pthread_barrier_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; + int __align; +} pthread_barrierattr_t; +#endif + + +#endif /* bits/pthreadtypes.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/semaphore.h new file mode 100644 index 000000000..be4469c69 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/semaphore.h @@ -0,0 +1,34 @@ +/* Machine-specific POSIX semaphore type layouts. Alpha version. + Copyright (C) 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SEMAPHORE_H +# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." +#endif + +# define __SIZEOF_SEM_T 32 + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + + +typedef union +{ + char __size[__SIZEOF_SEM_T]; + long int __align; +} sem_t; diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/clone.S new file mode 100644 index 000000000..eea1cbeed --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <sysdeps/unix/sysv/linux/alpha/clone.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/createthread.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/createthread.c new file mode 100644 index 000000000..6a51e73da --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/createthread.c @@ -0,0 +1,23 @@ +/* Copyright (C) 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Value passed to 'clone' for initialization of the thread register. */ +#define TLS_VALUE (pd + 1) + +/* Get the real implementation. */ +#include <nptl/sysdeps/pthread/createthread.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/fork.c new file mode 100644 index 000000000..ca85fc008 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/fork.c @@ -0,0 +1,30 @@ +/* Copyright (C) 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sched.h> +#include <signal.h> +#include <sysdep.h> +#include <tls.h> + + +#define ARCH_FORK() \ + INLINE_SYSCALL (clone, 5, \ + CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, \ + NULL, NULL, &THREAD_SELF->tid, NULL) + +#include "../fork.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h new file mode 100644 index 000000000..b7f4de338 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h @@ -0,0 +1,284 @@ +/* Copyright (C) 2003, 2004, 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 + 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 Libr \ary; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H 1 + +#include <time.h> +#include <sys/param.h> +#include <bits/pthreadtypes.h> +#include <atomic.h> +#include <sysdep.h> +#include <bits/kernel-features.h> + + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 +#define FUTEX_WAKE_OP 5 +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 +#define FUTEX_WAIT_BITSET 9 +#define FUTEX_WAKE_BITSET 10 +#define FUTEX_PRIVATE_FLAG 128 +#define FUTEX_CLOCK_REALTIME 256 + +#define FUTEX_BITSET_MATCH_ANY 0xffffffff + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \ + & THREAD_GETMEM (THREAD_SELF, header.private_futex)))) +# endif +#endif + + +#define lll_futex_wait(futexp, val, private) \ + lll_futex_timed_wait (futexp, val, NULL, private) + +#define lll_futex_timed_wait(futexp, val, timespec, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAIT, private), \ + (val), (timespec)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret : __ret; \ + }) + +#define lll_futex_wake(futexp, nr, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAKE, private), \ + (nr), 0); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret : __ret; \ + }) + +#define lll_robust_dead(futexv, private) \ + do \ + { \ + int *__futexp = &(futexv); \ + atomic_or (__futexp, FUTEX_OWNER_DIED); \ + lll_futex_wake (__futexp, 1, private); \ + } \ + while (0) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_CMP_REQUEUE, private),\ + (nr_wake), (nr_move), (mutex), (val)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_WAKE_OP, private), \ + (nr_wake), (nr_wake2), (futexp2), \ + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + + + + +static inline int __attribute__((always_inline)) +__lll_trylock(int *futex) +{ + return atomic_compare_and_exchange_val_acq (futex, 1, 0) != 0; +} +#define lll_trylock(lock) __lll_trylock (&(lock)) + + +static inline int __attribute__((always_inline)) +__lll_cond_trylock(int *futex) +{ + return atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0; +} +#define lll_cond_trylock(lock) __lll_cond_trylock (&(lock)) + + +static inline int __attribute__((always_inline)) +__lll_robust_trylock(int *futex, int id) +{ + return atomic_compare_and_exchange_val_acq (futex, id, 0) != 0; +} +#define lll_robust_trylock(lock, id) \ + __lll_robust_trylock (&(lock), id) + +extern void __lll_lock_wait_private (int *futex) attribute_hidden; +extern void __lll_lock_wait (int *futex, int private) attribute_hidden; +extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden; + +static inline void __attribute__((always_inline)) +__lll_lock(int *futex, int private) +{ + if (atomic_compare_and_exchange_bool_acq (futex, 1, 0) != 0) + { + if (__builtin_constant_p (private) && private == LLL_PRIVATE) + __lll_lock_wait_private (futex); + else + __lll_lock_wait (futex, private); + } +} +#define lll_lock(futex, private) __lll_lock (&(futex), private) + + +static inline int __attribute__ ((always_inline)) +__lll_robust_lock (int *futex, int id, int private) +{ + int result = 0; + if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0) + result = __lll_robust_lock_wait (futex, private); + return result; +} +#define lll_robust_lock(futex, id, private) \ + __lll_robust_lock (&(futex), id, private) + + +static inline void __attribute__ ((always_inline)) +__lll_cond_lock (int *futex, int private) +{ + if (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0) + __lll_lock_wait (futex, private); +} +#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private) + + +#define lll_robust_cond_lock(futex, id, private) \ + __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private) + + +extern int __lll_timedlock_wait (int *futex, const struct timespec *, + int private) attribute_hidden; +extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *, + int private) attribute_hidden; + +static inline int __attribute__ ((always_inline)) +__lll_timedlock (int *futex, const struct timespec *abstime, int private) +{ + int result = 0; + if (atomic_compare_and_exchange_bool_acq (futex, 1, 0) != 0) + result = __lll_timedlock_wait (futex, abstime, private); + return result; +} +#define lll_timedlock(futex, abstime, private) \ + __lll_timedlock (&(futex), abstime, private) + + +static inline int __attribute__ ((always_inline)) +__lll_robust_timedlock (int *futex, const struct timespec *abstime, + int id, int private) +{ + int result = 0; + if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0) + result = __lll_robust_timedlock_wait (futex, abstime, private); + return result; +} +#define lll_robust_timedlock(futex, abstime, id, private) \ + __lll_robust_timedlock (&(futex), abstime, id, private) + + +#define __lll_unlock(futex, private) \ + (void) \ + ({ int *__futex = (futex); \ + int __oldval = atomic_exchange_rel (__futex, 0); \ + if (__builtin_expect (__oldval > 1, 0)) \ + lll_futex_wake (__futex, 1, private); \ + }) +#define lll_unlock(futex, private) __lll_unlock(&(futex), private) + + +#define __lll_robust_unlock(futex, private) \ + (void) \ + ({ int *__futex = (futex); \ + int __oldval = atomic_exchange_rel (__futex, 0); \ + if (__builtin_expect (__oldval & FUTEX_WAITERS, 0)) \ + lll_futex_wake (__futex, 1, private); \ + }) +#define lll_robust_unlock(futex, private) \ + __lll_robust_unlock(&(futex), private) + + +#define lll_islocked(futex) \ + (futex != 0) + +/* Initializers for lock. */ +#define LLL_LOCK_INITIALIZER (0) +#define LLL_LOCK_INITIALIZER_LOCKED (1) + + +/* The kernel notifies a process which uses CLONE_CLEARTID via futex + wakeup when the clone terminates. The memory location contains the + thread ID while the clone is running and is reset to zero + afterwards. */ +#define lll_wait_tid(tid) \ + do { \ + __typeof (tid) __tid; \ + while ((__tid = (tid)) != 0) \ + lll_futex_wait (&(tid), __tid, LLL_SHARED); \ + } while (0) + +extern int __lll_timedwait_tid (int *, const struct timespec *) + attribute_hidden; + +#define lll_timedwait_tid(tid, abstime) \ + ({ \ + int __res = 0; \ + if ((tid) != 0) \ + __res = __lll_timedwait_tid (&(tid), (abstime)); \ + __res; \ + }) + +#endif /* lowlevellock.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pt-vfork.S new file mode 100644 index 000000000..ec5d175be --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pt-vfork.S @@ -0,0 +1,43 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <tcb-offsets.h> + +#undef PSEUDO_PREPARE_ARGS +#define PSEUDO_PREPARE_ARGS \ + /* Load the current cached pid value across the vfork. */ \ + rduniq; \ + ldl a2, PID_OFFSET(v0); \ + mov v0, a1; \ + /* Write back its negation, to indicate that the pid value is \ + uninitialized in the the child, and in the window between \ + here and the point at which we restore the value. */ \ + negl a2, t0; \ + stl t0, PID_OFFSET(v0); + +PSEUDO (__vfork, vfork, 0) + + /* If we're back in the parent, restore the saved pid. */ + beq v0, 1f + stl a2, PID_OFFSET(a1) +1: ret + +PSEUDO_END (__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pthread_once.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pthread_once.c new file mode 100644 index 000000000..7edee6625 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pthread_once.c @@ -0,0 +1,97 @@ +/* Copyright (C) 2003, 2004, 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 + 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 <lowlevellock.h> + + +unsigned long int __fork_generation attribute_hidden; + +static void +clear_once_control (void *arg) +{ + pthread_once_t *once_control = (pthread_once_t *) arg; + + *once_control = 0; + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +} + +int +attribute_hidden +__pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) +{ + for (;;) + { + int oldval; + int newval; + int tmp; + + /* Pseudo code: + newval = __fork_generation | 1; + oldval = *once_control; + if ((oldval & 2) == 0) + *once_control = newval; + Do this atomically. + */ + newval = __fork_generation | 1; + __asm __volatile ( + "1: ldl_l %0, %2\n" + " and %0, 2, %1\n" + " bne %1, 2f\n" + " mov %3, %1\n" + " stl_c %1, %2\n" + " beq %1, 1b\n" + "2: mb" + : "=&r" (oldval), "=&r" (tmp), "=m" (*once_control) + : "r" (newval), "m" (*once_control)); + + /* Check if the initializer has already been done. */ + if ((oldval & 2) != 0) + return 0; + + /* Check if another thread already runs the initializer. */ + if ((oldval & 1) == 0) + break; + + /* Check whether the initializer execution was interrupted by a fork. */ + if (oldval != newval) + break; + + /* Same generation, some other thread was faster. Wait. */ + lll_futex_wait (once_control, oldval, LLL_PRIVATE); + } + + /* This thread is the first here. Do the initialization. + Register a cleanup handler so that in case the thread gets + interrupted the initialization can be restarted. */ + pthread_cleanup_push (clear_once_control, once_control); + + init_routine (); + + pthread_cleanup_pop (0); + + /* Add one to *once_control to take the bottom 2 bits from 01 to 10. */ + atomic_increment (once_control); + + /* Wake up all other threads. */ + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); + + return 0; +} +weak_alias (__pthread_once, pthread_once) +strong_alias (__pthread_once, __pthread_once_internal) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sem_post.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sem_post.c new file mode 100644 index 000000000..27fd817e6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sem_post.c @@ -0,0 +1,5 @@ +/* ??? This is an ass-backwards way to do this. We should simply define + the acquire/release semantics of atomic_exchange_and_add. And even if + we don't do this, we should be using atomic_full_barrier or otherwise. */ +#define __lll_rel_instr "mb" +#include "../sem_post.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h new file mode 100644 index 000000000..7049b3607 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h @@ -0,0 +1,177 @@ +/* Copyright (C) 2003, 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <nptl/pthreadP.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# ifdef PROF +# define PSEUDO_PROF \ + .set noat; \ + lda AT, _mcount; \ + jsr AT, (AT), _mcount; \ + .set at +# else +# define PSEUDO_PROF +# endif + +/* ??? Assumes that nothing comes between PSEUDO and PSEUDO_END + besides "ret". */ + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .globl name; \ + .align 4; \ + .type name, @function; \ + .usepv name, std; \ + cfi_startproc; \ +__LABEL(name) \ + ldgp gp, 0(pv); \ + PSEUDO_PROF; \ + PSEUDO_PREPARE_ARGS \ + SINGLE_THREAD_P(t0); \ + bne t0, $pseudo_cancel; \ + lda v0, SYS_ify(syscall_name); \ + call_pal PAL_callsys; \ + bne a3, SYSCALL_ERROR_LABEL; \ +__LABEL($pseudo_ret) \ + .subsection 2; \ + cfi_startproc; \ +__LABEL($pseudo_cancel) \ + subq sp, 64, sp; \ + cfi_def_cfa_offset(64); \ + stq ra, 0(sp); \ + cfi_offset(ra, -64); \ + SAVE_ARGS_##args; \ + CENABLE; \ + LOAD_ARGS_##args; \ + /* Save the CENABLE return value in RA. That register \ + is preserved across syscall and the real return \ + address is saved on the stack. */ \ + mov v0, ra; \ + lda v0, SYS_ify(syscall_name); \ + call_pal PAL_callsys; \ + stq v0, 8(sp); \ + mov ra, a0; \ + bne a3, $multi_error; \ + CDISABLE; \ + ldq ra, 0(sp); \ + ldq v0, 8(sp); \ + addq sp, 64, sp; \ + cfi_remember_state; \ + cfi_restore(ra); \ + cfi_def_cfa_offset(0); \ + ret; \ + cfi_restore_state; \ +__LABEL($multi_error) \ + CDISABLE; \ + ldq ra, 0(sp); \ + ldq v0, 8(sp); \ + addq sp, 64, sp; \ + cfi_restore(ra); \ + cfi_def_cfa_offset(0); \ +__LABEL($syscall_error) \ + SYSCALL_ERROR_HANDLER; \ + cfi_endproc; \ + .previous + +# undef PSEUDO_END +# define PSEUDO_END(sym) \ + cfi_endproc; \ + .subsection 2; \ + .size sym, .-sym + +# define SAVE_ARGS_0 /* Nothing. */ +# define SAVE_ARGS_1 SAVE_ARGS_0; stq a0, 8(sp) +# define SAVE_ARGS_2 SAVE_ARGS_1; stq a1, 16(sp) +# define SAVE_ARGS_3 SAVE_ARGS_2; stq a2, 24(sp) +# define SAVE_ARGS_4 SAVE_ARGS_3; stq a3, 32(sp) +# define SAVE_ARGS_5 SAVE_ARGS_4; stq a4, 40(sp) +# define SAVE_ARGS_6 SAVE_ARGS_5; stq a5, 48(sp) + +# define LOAD_ARGS_0 /* Nothing. */ +# define LOAD_ARGS_1 LOAD_ARGS_0; ldq a0, 8(sp) +# define LOAD_ARGS_2 LOAD_ARGS_1; ldq a1, 16(sp) +# define LOAD_ARGS_3 LOAD_ARGS_2; ldq a2, 24(sp) +# define LOAD_ARGS_4 LOAD_ARGS_3; ldq a3, 32(sp) +# define LOAD_ARGS_5 LOAD_ARGS_4; ldq a4, 40(sp) +# define LOAD_ARGS_6 LOAD_ARGS_5; ldq a5, 48(sp) + +# ifdef IS_IN_libpthread +# define __local_enable_asynccancel __pthread_enable_asynccancel +# define __local_disable_asynccancel __pthread_disable_asynccancel +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define __local_enable_asynccancel __libc_enable_asynccancel +# define __local_disable_asynccancel __libc_disable_asynccancel +# define __local_multiple_threads __libc_multiple_threads +# elif defined IS_IN_librt +# define __local_enable_asynccancel __librt_enable_asynccancel +# define __local_disable_asynccancel __librt_disable_asynccancel +# else +# error Unsupported library +# endif + +# ifdef __PIC__ +# define CENABLE bsr ra, __local_enable_asynccancel !samegp +# define CDISABLE bsr ra, __local_disable_asynccancel !samegp +# else +# define CENABLE jsr ra, __local_enable_asynccancel; ldgp ra, 0(gp) +# define CDISABLE jsr ra, __local_disable_asynccancel; ldgp ra, 0(gp) +# endif + +# if defined IS_IN_libpthread || !defined NOT_IN_libc +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P \ + __builtin_expect (__local_multiple_threads == 0, 1) +# elif defined(__PIC__) +# define SINGLE_THREAD_P(reg) ldl reg, __local_multiple_threads(gp) !gprel +# else +# define SINGLE_THREAD_P(reg) \ + ldah reg, __local_multiple_threads(gp) !gprelhigh; \ + ldl reg, __local_multiple_threads(reg) !gprellow +# endif +# else +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P(reg) \ + call_pal PAL_rduniq; \ + ldl reg, MULTIPLE_THREADS_OFFSET($0) +# endif +# endif + +#else + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_create.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_create.c new file mode 100644 index 000000000..172223af3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_create.c @@ -0,0 +1 @@ +#include "../x86_64/timer_create.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_delete.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_delete.c new file mode 100644 index 000000000..537516e0a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_delete.c @@ -0,0 +1 @@ +#include "../x86_64/timer_delete.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_getoverr.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_getoverr.c new file mode 100644 index 000000000..3f21a73c9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_getoverr.c @@ -0,0 +1 @@ +#include "../x86_64/timer_getoverr.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_gettime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_gettime.c new file mode 100644 index 000000000..a50143adc --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_gettime.c @@ -0,0 +1 @@ +#include "../x86_64/timer_gettime.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_settime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_settime.c new file mode 100644 index 000000000..37baeffac --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_settime.c @@ -0,0 +1 @@ +#include "../x86_64/timer_settime.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/vfork.S new file mode 100644 index 000000000..f4ed9311b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/vfork.S @@ -0,0 +1,46 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <tcb-offsets.h> + +#undef PSEUDO_PREPARE_ARGS +#define PSEUDO_PREPARE_ARGS \ + /* Load the current cached pid value across the vfork. */ \ + rduniq; \ + ldl a2, PID_OFFSET(v0); \ + mov v0, a1; \ + /* If the cached value is initialized (nonzero), then write \ + back its negation, or INT_MIN, to indicate that the pid \ + value is uninitialized in the the child, and in the window \ + between here and the point at which we restore the value. */ \ + ldah t0, -0x8000; \ + negl a2, t1; \ + cmovne a2, t1, t0; \ + stl t0, PID_OFFSET(v0); + +PSEUDO (__vfork, vfork, 0) + + /* If we're back in the parent, restore the saved pid. */ + beq v0, 1f + stl a2, PID_OFFSET(a1) +1: ret + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile new file mode 100644 index 000000000..43a6fad84 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../../../../ +top_builddir=../../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile.arch b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile.arch new file mode 100644 index 000000000..c5852818d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile.arch @@ -0,0 +1,58 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_SSRC = pt-vfork.S +libpthread_CSRC = pthread_once.c lowlevellock.c \ + pt-__syscall_rt_sigaction.c pt-__syscall_error.c + +libc_a_CSRC = fork.c lowlevellock.c +libc_a_SSRC = clone.S vfork.S + +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y) +CFLAGS-fork.c = -D__USE_STDIO_FUTEXES__ +endif +CFLAGS-pthread_once.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-pt-__syscall_rt_sigaction.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-lowlevellock.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-pt-__syscall_error.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + +ASFLAGS-pt-vfork.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -marm +# We always compile it in arm mode because of SAVE_PID macro +# This macro should be alternatively implemented in THUMB +# assembly. +ASFLAGS-vfork.S = -marm + +CFLAGS += $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +LINUX_ARCH_DIR:=$(top_srcdir)libpthread/nptl/sysdeps/unix/sysv/linux/arm +LINUX_ARCH_OUT:=$(top_builddir)libpthread/nptl/sysdeps/unix/sysv/linux/arm + +LINUX_ARCH_OBJ:=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libpthread_SSRC)) +LINUX_ARCH_OBJ+=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libpthread_CSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(LINUX_ARCH_OBJ:.o=.os) +else +libpthread-a-y += $(LINUX_ARCH_OBJ) +endif +libpthread-so-y += $(LINUX_ARCH_OBJ:.o=.oS) + +libpthread-nomulti-y+=$(LINUX_ARCH_OBJ) + +LIBC_LINUX_ARCH_OBJ:=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libc_a_CSRC)) +LIBC_LINUX_ARCH_OBJ+=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libc_a_SSRC)) + +libc-static-y+=$(LIBC_LINUX_ARCH_OBJ) +libc-shared-y+=$(LIBC_LINUX_ARCH_OBJ:.o=.oS) + +libc-nomulti-y+=$(LIBC_LINUX_ARCH_OBJ) + +objclean-y+=pthread_linux_arch_objclean + +pthread_linux_arch_objclean: + $(RM) $(LINUX_ARCH_OUT)/*.{o,os,oS} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/atomic.h b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/atomic.h new file mode 100644 index 000000000..b0586ea1e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/atomic.h @@ -0,0 +1,122 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stdint.h> +#include <sysdep.h> + + +typedef int8_t atomic8_t; +typedef uint8_t uatomic8_t; +typedef int_fast8_t atomic_fast8_t; +typedef uint_fast8_t uatomic_fast8_t; + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + +void __arm_link_error (void); + +#ifdef __thumb2__ +#define atomic_full_barrier() \ + __asm__ __volatile__ \ + ("movw\tip, #0x0fa0\n\t" \ + "movt\tip, #0xffff\n\t" \ + "blx\tip" \ + : : : "ip", "lr", "cc", "memory"); +#else +#define atomic_full_barrier() \ + __asm__ __volatile__ \ + ("mov\tip, #0xffff0fff\n\t" \ + "mov\tlr, pc\n\t" \ + "add\tpc, ip, #(0xffff0fa0 - 0xffff0fff)" \ + : : : "ip", "lr", "cc", "memory"); +#endif + +/* Atomic compare and exchange. This sequence relies on the kernel to + provide a compare and exchange operation which is atomic on the + current architecture, either via cleverness on pre-ARMv6 or via + ldrex / strex on ARMv6. */ + +#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ + ({ __arm_link_error (); oldval; }) + +#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ + ({ __arm_link_error (); oldval; }) + +/* It doesn't matter what register is used for a_oldval2, but we must + specify one to work around GCC PR rtl-optimization/21223. Otherwise + it may cause a_oldval or a_tmp to be moved to a different register. */ + +#ifdef __thumb2__ +/* Thumb-2 has ldrex/strex. However it does not have barrier instructions, + so we still need to use the kernel helper. */ +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + ({ register __typeof (oldval) a_oldval asm ("r0"); \ + register __typeof (oldval) a_newval asm ("r1") = (newval); \ + register __typeof (mem) a_ptr asm ("r2") = (mem); \ + register __typeof (oldval) a_tmp asm ("r3"); \ + register __typeof (oldval) a_oldval2 asm ("r4") = (oldval); \ + __asm__ __volatile__ \ + ("0:\tldr\t%[tmp],[%[ptr]]\n\t" \ + "cmp\t%[tmp], %[old2]\n\t" \ + "bne\t1f\n\t" \ + "mov\t%[old], %[old2]\n\t" \ + "movw\t%[tmp], #0x0fc0\n\t" \ + "movt\t%[tmp], #0xffff\n\t" \ + "blx\t%[tmp]\n\t" \ + "bcc\t0b\n\t" \ + "mov\t%[tmp], %[old2]\n\t" \ + "1:" \ + : [old] "=&r" (a_oldval), [tmp] "=&r" (a_tmp) \ + : [new] "r" (a_newval), [ptr] "r" (a_ptr), \ + [old2] "r" (a_oldval2) \ + : "ip", "lr", "cc", "memory"); \ + a_tmp; }) +#else +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + ({ register __typeof (oldval) a_oldval asm ("r0"); \ + register __typeof (oldval) a_newval asm ("r1") = (newval); \ + register __typeof (mem) a_ptr asm ("r2") = (mem); \ + register __typeof (oldval) a_tmp asm ("r3"); \ + register __typeof (oldval) a_oldval2 asm ("r4") = (oldval); \ + __asm__ __volatile__ \ + ("0:\tldr\t%[tmp],[%[ptr]]\n\t" \ + "cmp\t%[tmp], %[old2]\n\t" \ + "bne\t1f\n\t" \ + "mov\t%[old], %[old2]\n\t" \ + "mov\t%[tmp], #0xffff0fff\n\t" \ + "mov\tlr, pc\n\t" \ + "add\tpc, %[tmp], #(0xffff0fc0 - 0xffff0fff)\n\t" \ + "bcc\t0b\n\t" \ + "mov\t%[tmp], %[old2]\n\t" \ + "1:" \ + : [old] "=&r" (a_oldval), [tmp] "=&r" (a_tmp) \ + : [new] "r" (a_newval), [ptr] "r" (a_ptr), \ + [old2] "r" (a_oldval2) \ + : "ip", "lr", "cc", "memory"); \ + a_tmp; }) +#endif + +#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + ({ __arm_link_error (); oldval; }) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/pthreadtypes.h new file mode 100644 index 000000000..e1b115c8c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/pthreadtypes.h @@ -0,0 +1,181 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#include <endian.h> + +#define __SIZEOF_PTHREAD_ATTR_T 36 +#define __SIZEOF_PTHREAD_MUTEX_T 24 +#define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +#define __SIZEOF_PTHREAD_COND_T 48 +#define __SIZEOF_PTHREAD_COND_COMPAT_T 12 +#define __SIZEOF_PTHREAD_CONDATTR_T 4 +#define __SIZEOF_PTHREAD_RWLOCK_T 32 +#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +#define __SIZEOF_PTHREAD_BARRIER_T 20 +#define __SIZEOF_PTHREAD_BARRIERATTR_T 4 + + +/* Thread identifiers. The structure of the attribute type is not + exposed on purpose. */ +typedef unsigned long int pthread_t; + + +typedef union +{ + char __size[__SIZEOF_PTHREAD_ATTR_T]; + long int __align; +} pthread_attr_t; + + +typedef struct __pthread_internal_slist +{ + struct __pthread_internal_slist *__next; +} __pthread_slist_t; + + +/* Data structures for mutex handling. The structure of the attribute + type is not exposed on purpose. */ +typedef union +{ + struct __pthread_mutex_s + { + int __lock; + unsigned int __count; + int __owner; + /* KIND must stay at this position in the structure to maintain + binary compatibility. */ + int __kind; + unsigned int __nusers; + __extension__ union + { + int __spins; + __pthread_slist_t __list; + }; + } __data; + char __size[__SIZEOF_PTHREAD_MUTEX_T]; + long int __align; +} pthread_mutex_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; + long int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling. The structure of + the attribute type is not exposed on purpose. */ +typedef union +{ + struct + { + int __lock; + unsigned int __futex; + __extension__ unsigned long long int __total_seq; + __extension__ unsigned long long int __wakeup_seq; + __extension__ unsigned long long int __woken_seq; + void *__mutex; + unsigned int __nwaiters; + unsigned int __broadcast_seq; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_CONDATTR_T]; + long int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling. The + structure of the attribute type is not exposed on purpose. */ +typedef union +{ + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned char __pad1; + unsigned char __pad2; + unsigned char __shared; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; +#else + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; + unsigned char __shared; + unsigned char __pad1; + unsigned char __pad2; +#endif + int __writer; + } __data; + char __size[__SIZEOF_PTHREAD_RWLOCK_T]; + long int __align; +} pthread_rwlock_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; + long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type. The structure of the type is + deliberately not exposed. */ +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIER_T]; + long int __align; +} pthread_barrier_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; + int __align; +} pthread_barrierattr_t; +#endif + + +#endif /* bits/pthreadtypes.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/semaphore.h new file mode 100644 index 000000000..dadfac2af --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/semaphore.h @@ -0,0 +1,35 @@ +/* Copyright (C) 2002, 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 + 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. */ + +#ifndef _SEMAPHORE_H +# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." +#endif + + +#define __SIZEOF_SEM_T 16 + + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + + +typedef union +{ + char __size[__SIZEOF_SEM_T]; + long int __align; +} sem_t; diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/clone.S new file mode 100644 index 000000000..23227eb24 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/clone.S @@ -0,0 +1,3 @@ +#define RESET_PID +#include <tcb-offsets.h> +#include "../../../../../../../libc/sysdeps/linux/arm/clone.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/createthread.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/createthread.c new file mode 100644 index 000000000..2d4355980 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/createthread.c @@ -0,0 +1,23 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Value passed to 'clone' for initialization of the thread register. */ +#define TLS_VALUE (pd + 1) + +/* Get the real implementation. */ +#include <sysdeps/pthread/createthread.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/fork.c new file mode 100644 index 000000000..1c8f4c43a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/fork.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Phil Blundell <pb@nexus.co.uk>, 2005 + + 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 <sched.h> +#include <signal.h> +#include <sysdep.h> +#include <tls.h> + + +#define ARCH_FORK() \ + INLINE_SYSCALL (clone, 5, \ + CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, \ + NULL, NULL, NULL, &THREAD_SELF->tid) + +#include "../fork.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.c new file mode 100644 index 000000000..8c8955e05 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.c @@ -0,0 +1,134 @@ +/* low level locking for pthread library. Generic futex-using version. + 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <sys/time.h> +#include <tls.h> + +void +__lll_lock_wait_private (int *futex) +{ + do + { + int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1); + if (oldval != 0) + lll_futex_wait (futex, 2, LLL_PRIVATE); + } + while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0); +} + + +/* These functions don't get included in libc.so */ +#ifdef IS_IN_libpthread +void +__lll_lock_wait (int *futex, int private) +{ + do + { + int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1); + if (oldval != 0) + lll_futex_wait (futex, 2, private); + } + while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0); +} + + +int +__lll_timedlock_wait (int *futex, const struct timespec *abstime, int private) +{ + struct timespec rt; + + /* Reject invalid timeouts. */ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + /* Upgrade the lock. */ + if (atomic_exchange_acq (futex, 2) == 0) + return 0; + + do + { + struct timeval tv; + + /* Get the current time. */ + (void) gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + + /* Already timed out? */ + if (rt.tv_sec < 0) + return ETIMEDOUT; + + // XYZ: Lost the lock to check whether it was private. + lll_futex_timed_wait (futex, 2, &rt, private); + } + while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0); + + return 0; +} + + +int +__lll_timedwait_tid (int *tidp, const struct timespec *abstime) +{ + int tid; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + /* Repeat until thread terminated. */ + while ((tid = *tidp) != 0) + { + struct timeval tv; + struct timespec rt; + + /* Get the current time. */ + (void) gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + + /* Already timed out? */ + if (rt.tv_sec < 0) + return ETIMEDOUT; + + /* Wait until thread terminates. */ + // XYZ: Lost the lock to check whether it was private. + if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT) + return ETIMEDOUT; + } + + return 0; +} +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.h new file mode 100644 index 000000000..4c7d08c92 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.h @@ -0,0 +1,282 @@ +/* Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H 1 + +#include <time.h> +#include <sys/param.h> +#include <bits/pthreadtypes.h> +#include <atomic.h> +#include <sysdep.h> +#include <bits/kernel-features.h> + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 +#define FUTEX_WAKE_OP 5 +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 +#define FUTEX_WAIT_BITSET 9 +#define FUTEX_WAKE_BITSET 10 +#define FUTEX_PRIVATE_FLAG 128 +#define FUTEX_CLOCK_REALTIME 256 + +#define FUTEX_BITSET_MATCH_ANY 0xffffffff + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \ + & THREAD_GETMEM (THREAD_SELF, header.private_futex)))) +# endif +#endif + + +#define lll_futex_wait(futexp, val, private) \ + lll_futex_timed_wait(futexp, val, NULL, private) + +#define lll_futex_timed_wait(futexp, val, timespec, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAIT, private), \ + (val), (timespec)); \ + __ret; \ + }) + +#define lll_futex_wake(futexp, nr, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAKE, private), \ + (nr), 0); \ + __ret; \ + }) + +#define lll_robust_dead(futexv, private) \ + do \ + { \ + int *__futexp = &(futexv); \ + atomic_or (__futexp, FUTEX_OWNER_DIED); \ + lll_futex_wake (__futexp, 1, private); \ + } \ + while (0) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_CMP_REQUEUE, private),\ + (nr_wake), (nr_move), (mutex), (val)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_WAKE_OP, private), \ + (nr_wake), (nr_wake2), (futexp2), \ + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + + +#define lll_trylock(lock) \ + atomic_compare_and_exchange_val_acq(&(lock), 1, 0) + +#define lll_cond_trylock(lock) \ + atomic_compare_and_exchange_val_acq(&(lock), 2, 0) + +#define __lll_robust_trylock(futex, id) \ + (atomic_compare_and_exchange_val_acq (futex, id, 0) != 0) +#define lll_robust_trylock(lock, id) \ + __lll_robust_trylock (&(lock), id) + +extern void __lll_lock_wait_private (int *futex) attribute_hidden; +extern void __lll_lock_wait (int *futex, int private) attribute_hidden; +extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden; + +#define __lll_lock(futex, private) \ + ((void) ({ \ + int *__futex = (futex); \ + if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex, \ + 1, 0), 0)) \ + { \ + if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \ + __lll_lock_wait_private (__futex); \ + else \ + __lll_lock_wait (__futex, private); \ + } \ + })) +#define lll_lock(futex, private) __lll_lock (&(futex), private) + + +#define __lll_robust_lock(futex, id, private) \ + ({ \ + int *__futex = (futex); \ + int __val = 0; \ + \ + if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \ + 0), 0)) \ + __val = __lll_robust_lock_wait (__futex, private); \ + __val; \ + }) +#define lll_robust_lock(futex, id, private) \ + __lll_robust_lock (&(futex), id, private) + + +#define __lll_cond_lock(futex, private) \ + ((void) ({ \ + int *__futex = (futex); \ + if (__builtin_expect (atomic_exchange_acq (__futex, 2), 0)) \ + __lll_lock_wait (__futex, private); \ + })) +#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private) + + +#define lll_robust_cond_lock(futex, id, private) \ + __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private) + + +extern int __lll_timedlock_wait (int *futex, const struct timespec *, + int private) attribute_hidden; +extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *, + int private) attribute_hidden; + +#define __lll_timedlock(futex, abstime, private) \ + ({ \ + int *__futex = (futex); \ + int __val = 0; \ + \ + if (__builtin_expect (atomic_exchange_acq (__futex, 1), 0)) \ + __val = __lll_timedlock_wait (__futex, abstime, private); \ + __val; \ + }) +#define lll_timedlock(futex, abstime, private) \ + __lll_timedlock (&(futex), abstime, private) + + +#define __lll_robust_timedlock(futex, abstime, id, private) \ + ({ \ + int *__futex = (futex); \ + int __val = 0; \ + \ + if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \ + 0), 0)) \ + __val = __lll_robust_timedlock_wait (__futex, abstime, private); \ + __val; \ + }) +#define lll_robust_timedlock(futex, abstime, id, private) \ + __lll_robust_timedlock (&(futex), abstime, id, private) + + +#define __lll_unlock(futex, private) \ + (void) \ + ({ int *__futex = (futex); \ + int __oldval = atomic_exchange_rel (__futex, 0); \ + if (__builtin_expect (__oldval > 1, 0)) \ + lll_futex_wake (__futex, 1, private); \ + }) +#define lll_unlock(futex, private) __lll_unlock(&(futex), private) + + +#define __lll_robust_unlock(futex, private) \ + (void) \ + ({ int *__futex = (futex); \ + int __oldval = atomic_exchange_rel (__futex, 0); \ + if (__builtin_expect (__oldval & FUTEX_WAITERS, 0)) \ + lll_futex_wake (__futex, 1, private); \ + }) +#define lll_robust_unlock(futex, private) \ + __lll_robust_unlock(&(futex), private) + + +#define lll_islocked(futex) \ + (futex != 0) + + +/* Our internal lock implementation is identical to the binary-compatible + mutex implementation. */ + +/* Initializers for lock. */ +#define LLL_LOCK_INITIALIZER (0) +#define LLL_LOCK_INITIALIZER_LOCKED (1) + +/* The states of a lock are: + 0 - untaken + 1 - taken by one user + >1 - taken by more users */ + +/* The kernel notifies a process which uses CLONE_CLEARTID via futex + wakeup when the clone terminates. The memory location contains the + thread ID while the clone is running and is reset to zero + afterwards. */ +#define lll_wait_tid(tid) \ + do { \ + __typeof (tid) __tid; \ + while ((__tid = (tid)) != 0) \ + lll_futex_wait (&(tid), __tid, LLL_SHARED);\ + } while (0) + +extern int __lll_timedwait_tid (int *, const struct timespec *) + attribute_hidden; + +#define lll_timedwait_tid(tid, abstime) \ + ({ \ + int __res = 0; \ + if ((tid) != 0) \ + __res = __lll_timedwait_tid (&(tid), (abstime)); \ + __res; \ + }) + +#endif /* lowlevellock.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/nptl-aeabi_unwind_cpp_pr1.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/nptl-aeabi_unwind_cpp_pr1.c new file mode 100644 index 000000000..7b8352243 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/nptl-aeabi_unwind_cpp_pr1.c @@ -0,0 +1 @@ +#include <aeabi_unwind_cpp_pr1.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-__syscall_error.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-__syscall_error.c new file mode 100644 index 000000000..5a48a9b2e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-__syscall_error.c @@ -0,0 +1 @@ +#include <../../../../../../../libc/sysdeps/linux/arm/__syscall_error.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-__syscall_rt_sigaction.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-__syscall_rt_sigaction.c new file mode 100644 index 000000000..50137c84a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-__syscall_rt_sigaction.c @@ -0,0 +1 @@ +#include <../../../../../../../libc/sysdeps/linux/common/__syscall_rt_sigaction.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-gettimeofday.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-gettimeofday.c new file mode 100644 index 000000000..08710f1c8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-gettimeofday.c @@ -0,0 +1,5 @@ +#include <sys/syscall.h> +#include <sys/time.h> + +int gettimeofday (struct timeval *, struct timezone *) attribute_hidden; +_syscall2(int, gettimeofday, struct timeval *, tv, struct timezone *, tz); diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-vfork.S new file mode 100644 index 000000000..9764e9ee2 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-vfork.S @@ -0,0 +1,38 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <tcb-offsets.h> + +/* Save the PID value. */ +#define SAVE_PID \ + str lr, [sp, #-4]!; /* Save LR. */ \ + mov r0, #0xffff0fff; /* Point to the high page. */ \ + mov lr, pc; /* Save our return address. */ \ + sub pc, r0, #31; /* Jump to the TLS entry. */ \ + ldr lr, [sp], #4; /* Restore LR. */ \ + mov r2, r0; /* Save the TLS addr in r2. */ \ + ldr r3, [r2, #PID_OFFSET]; /* Load the saved PID. */ \ + rsb r0, r3, #0; /* Negate it. */ \ + str r0, [r2, #PID_OFFSET] /* Store the temporary PID. */ + +/* Restore the old PID value in the parent. */ +#define RESTORE_PID \ + cmp r0, #0; /* If we are the parent... */ \ + strne r3, [r2, #PID_OFFSET] /* ... restore the saved PID. */ + +#INCLUDE <../../../../../../../LIBC/SYSDEPS/LINUX/ARM/VFORK.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pthread_once.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pthread_once.c new file mode 100644 index 000000000..a482ddccd --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pthread_once.c @@ -0,0 +1,100 @@ +/* Copyright (C) 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" +#include <lowlevellock.h> + +unsigned long int __fork_generation attribute_hidden; + +static void +clear_once_control (void *arg) +{ + pthread_once_t *once_control = (pthread_once_t *) arg; + + *once_control = 0; + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +} + +int +attribute_hidden +__pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) +{ + for (;;) + { + int oldval; + int newval; + + /* Pseudo code: + newval = __fork_generation | 1; + oldval = *once_control; + if ((oldval & 2) == 0) + *once_control = newval; + Do this atomically. + */ + do + { + newval = __fork_generation | 1; + oldval = *once_control; + if (oldval & 2) + break; + } while (atomic_compare_and_exchange_val_acq (once_control, newval, oldval) != oldval); + + /* Check if the initializer has already been done. */ + if ((oldval & 2) != 0) + return 0; + + /* Check if another thread already runs the initializer. */ + if ((oldval & 1) == 0) + break; + + /* Check whether the initializer execution was interrupted by a fork. */ + if (oldval != newval) + break; + + /* Same generation, some other thread was faster. Wait. */ + lll_futex_wait (once_control, oldval, LLL_PRIVATE); + } + + /* This thread is the first here. Do the initialization. + Register a cleanup handler so that in case the thread gets + interrupted the initialization can be restarted. */ + pthread_cleanup_push (clear_once_control, once_control); + + init_routine (); + + pthread_cleanup_pop (0); + + /* Say that the initialisation is done. */ + *once_control = __fork_generation | 2; + + /* Wake up all other threads. */ + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); + + return 0; +} +weak_alias (__pthread_once, pthread_once) +strong_alias (__pthread_once, __pthread_once_internal) + +#if defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__PIC__) +/* When statically linked, if pthread_create is used, this file + will be brought in. The exception handling code in GCC assumes + that if pthread_create is available, so are these. */ +const void *include_pthread_getspecific attribute_hidden = pthread_getspecific; +const void *include_pthread_setspecific attribute_hidden = pthread_setspecific; +const void *include_pthread_key_create attribute_hidden = pthread_key_create; +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h new file mode 100644 index 000000000..423c23195 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h @@ -0,0 +1,137 @@ +/* Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <tcb-offsets.h> +#ifndef __ASSEMBLER__ +# include <pthreadP.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .section ".text"; \ + PSEUDO_PROLOGUE; \ + .type __##syscall_name##_nocancel,%function; \ + .globl __##syscall_name##_nocancel; \ + __##syscall_name##_nocancel: \ + DO_CALL (syscall_name, args); \ + PSEUDO_RET; \ + .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ + ENTRY (name); \ + SINGLE_THREAD_P; \ + DOARGS_##args; \ + bne .Lpseudo_cancel; \ + DO_CALL (syscall_name, 0); \ + UNDOARGS_##args; \ + cmn r0, $4096; \ + PSEUDO_RET; \ + .Lpseudo_cancel: \ + DOCARGS_##args; /* save syscall args etc. around CENABLE. */ \ + CENABLE; \ + mov ip, r0; /* put mask in safe place. */ \ + UNDOCARGS_##args; /* restore syscall args. */ \ + swi SYS_ify (syscall_name); /* do the call. */ \ + str r0, [sp, $-4]!; /* save syscall return value. */ \ + mov r0, ip; /* get mask back. */ \ + CDISABLE; \ + ldmfd sp!, {r0, lr}; /* retrieve return value and address. */ \ + UNDOARGS_##args; \ + cmn r0, $4096; + +# define DOCARGS_0 str lr, [sp, #-4]!; +# define UNDOCARGS_0 + +# define DOCARGS_1 stmfd sp!, {r0, lr}; +# define UNDOCARGS_1 ldr r0, [sp], #4; + +# define DOCARGS_2 stmfd sp!, {r0, r1, lr}; +# define UNDOCARGS_2 ldmfd sp!, {r0, r1}; + +# define DOCARGS_3 stmfd sp!, {r0, r1, r2, lr}; +# define UNDOCARGS_3 ldmfd sp!, {r0, r1, r2}; + +# define DOCARGS_4 stmfd sp!, {r0, r1, r2, r3, lr}; +# define UNDOCARGS_4 ldmfd sp!, {r0, r1, r2, r3}; + +# define DOCARGS_5 DOCARGS_4 +# define UNDOCARGS_5 UNDOCARGS_4 + +# define DOCARGS_6 DOCARGS_5 +# define UNDOCARGS_6 UNDOCARGS_5 + +# ifdef IS_IN_libpthread +# define CENABLE bl PLTJMP(__pthread_enable_asynccancel) +# define CDISABLE bl PLTJMP(__pthread_disable_asynccancel) +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define CENABLE bl PLTJMP(__libc_enable_asynccancel) +# define CDISABLE bl PLTJMP(__libc_disable_asynccancel) +# define __local_multiple_threads __libc_multiple_threads +# elif defined IS_IN_librt +# define CENABLE bl PLTJMP(__librt_enable_asynccancel) +# define CDISABLE bl PLTJMP(__librt_disable_asynccancel) +# else +# error Unsupported library +# endif + +# if defined IS_IN_libpthread || !defined NOT_IN_libc +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +# define SINGLE_THREAD_P \ + ldr ip, 1b; \ +2: \ + ldr ip, [pc, ip]; \ + teq ip, #0; +# define PSEUDO_PROLOGUE \ + 1: .word __local_multiple_threads - 2f - 8; +# endif +# else +/* There is no __local_multiple_threads for librt, so use the TCB. */ +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +# else +# define PSEUDO_PROLOGUE +# define SINGLE_THREAD_P \ + stmfd sp!, {r0, lr}; \ + bl __aeabi_read_tp; \ + ldr ip, [r0, #MULTIPLE_THREADS_OFFSET]; \ + ldmfd sp!, {r0, lr}; \ + teq ip, #0 +# define SINGLE_THREAD_P_PIC(x) SINGLE_THREAD_P +# endif +# endif + +#elif !defined __ASSEMBLER__ + +/* For rtld, et cetera. */ +# define SINGLE_THREAD_P 1 +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c new file mode 100644 index 000000000..d095d3083 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c @@ -0,0 +1,149 @@ +/* Copyright (C) 2003, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>. + + 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 <dlfcn.h> +#include <stdio.h> +#include <unwind.h> +#include <pthreadP.h> +#define __libc_dlopen(x) dlopen(x, (RTLD_LOCAL | RTLD_LAZY)) +#define __libc_dlsym dlsym +#define __libc_dlclose dlclose + +static void *libgcc_s_handle; +static void (*libgcc_s_resume) (struct _Unwind_Exception *exc); +static _Unwind_Reason_Code (*libgcc_s_personality) + (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *, + struct _Unwind_Context *); +static _Unwind_Reason_Code (*libgcc_s_forcedunwind) + (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *); +static _Unwind_Word (*libgcc_s_getcfa) (struct _Unwind_Context *); +static void (*libgcc_s_sjlj_register) (struct SjLj_Function_Context *); +static void (*libgcc_s_sjlj_unregister) (struct SjLj_Function_Context *); + +void +__attribute_noinline__ +pthread_cancel_init (void) +{ + void *resume, *personality, *forcedunwind, *getcfa; + void *handle; + void *sjlj_register, *sjlj_unregister; + + if (__builtin_expect (libgcc_s_handle != NULL, 1)) + { + /* Force gcc to reload all values. */ + asm volatile ("" ::: "memory"); + return; + } + + handle = __libc_dlopen ("libgcc_s.so.1"); + + if (handle == NULL + || (sjlj_register = __libc_dlsym (handle, "_Unwind_SjLj_Register")) == NULL + || (sjlj_unregister = __libc_dlsym (handle, "_Unwind_SjLj_Unregister")) == NULL + || (resume = __libc_dlsym (handle, "_Unwind_SjLj_Resume")) == NULL + || (personality = __libc_dlsym (handle, "__gcc_personality_sj0")) == NULL + || (forcedunwind = __libc_dlsym (handle, "_Unwind_SjLj_ForcedUnwind")) + == NULL + || (getcfa = __libc_dlsym (handle, "_Unwind_GetCFA")) == NULL + ) + fprintf(stderr, "libgcc_s.so.1 must be installed for pthread_cancel to work\n"); + + libgcc_s_resume = resume; + libgcc_s_personality = personality; + libgcc_s_forcedunwind = forcedunwind; + libgcc_s_sjlj_register = sjlj_register; + libgcc_s_sjlj_unregister = sjlj_unregister; + libgcc_s_getcfa = getcfa; + /* Make sure libgcc_s_getcfa is written last. Otherwise, + pthread_cancel_init might return early even when the pointer the + caller is interested in is not initialized yet. */ + atomic_write_barrier (); + libgcc_s_handle = handle; +} + +void +__libc_freeres_fn_section +__unwind_freeres (void) +{ + void *handle = libgcc_s_handle; + if (handle != NULL) + { + libgcc_s_handle = NULL; + __libc_dlclose (handle); + } +} + +void +_Unwind_Resume (struct _Unwind_Exception *exc) +{ + if (__builtin_expect (libgcc_s_resume == NULL, 0)) + pthread_cancel_init (); + + libgcc_s_resume (exc); +} + +_Unwind_Reason_Code +__gcc_personality_v0 (int version, _Unwind_Action actions, + _Unwind_Exception_Class exception_class, + struct _Unwind_Exception *ue_header, + struct _Unwind_Context *context) +{ + if (__builtin_expect (libgcc_s_personality == NULL, 0)) + pthread_cancel_init (); + + return libgcc_s_personality (version, actions, exception_class, + ue_header, context); +} + +_Unwind_Reason_Code +_Unwind_ForcedUnwind (struct _Unwind_Exception *exc, _Unwind_Stop_Fn stop, + void *stop_argument) +{ + if (__builtin_expect (libgcc_s_forcedunwind == NULL, 0)) + pthread_cancel_init (); + + return libgcc_s_forcedunwind (exc, stop, stop_argument); +} + +_Unwind_Word +_Unwind_GetCFA (struct _Unwind_Context *context) +{ + if (__builtin_expect (libgcc_s_getcfa == NULL, 0)) + pthread_cancel_init (); + + return libgcc_s_getcfa (context); +} + +void +_Unwind_SjLj_Register (struct SjLj_Function_Context *fc) +{ + if (__builtin_expect (libgcc_s_sjlj_register == NULL, 0)) + pthread_cancel_init (); + + libgcc_s_sjlj_register (fc); +} + +void +_Unwind_SjLj_Unregister (struct SjLj_Function_Context *fc) +{ + if (__builtin_expect (libgcc_s_sjlj_unregister == NULL, 0)) + pthread_cancel_init (); + + libgcc_s_sjlj_unregister (fc); +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-resume.c b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-resume.c new file mode 100644 index 000000000..bf0348ac2 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-resume.c @@ -0,0 +1,90 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>. + + 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 <dlfcn.h> +#include <stdio.h> +#include <unwind.h> +#define __libc_dlopen(x) dlopen(x, (RTLD_LOCAL | RTLD_LAZY)) +#define __libc_dlsym dlsym +#define __libc_dlclose dlclose + +static void (*libgcc_s_resume) (struct _Unwind_Exception *exc); +static _Unwind_Reason_Code (*libgcc_s_personality) + (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *, + struct _Unwind_Context *); +static void (*libgcc_s_sjlj_register) (struct SjLj_Function_Context *); +static void (*libgcc_s_sjlj_unregister) (struct SjLj_Function_Context *); + +static void +init (void) +{ + void *resume, *personality; + void *handle; + void *sjlj_register, *sjlj_unregister; + + handle = __libc_dlopen ("libgcc_s.so.1"); + + if (handle == NULL + || (sjlj_register = __libc_dlsym (handle, "_Unwind_SjLj_Register")) == NULL + || (sjlj_unregister = __libc_dlsym (handle, "_Unwind_SjLj_Unregister")) == NULL + || (resume = __libc_dlsym (handle, "_Unwind_SjLj_Resume")) == NULL + || (personality = __libc_dlsym (handle, "__gcc_personality_sj0")) == NULL) + fprintf(stderr, "libgcc_s.so.1 must be installed for pthread_cancel to work\n"); + + libgcc_s_resume = resume; + libgcc_s_personality = personality; + libgcc_s_sjlj_register = sjlj_register; + libgcc_s_sjlj_unregister = sjlj_unregister; +} + +void +_Unwind_Resume (struct _Unwind_Exception *exc) +{ + if (__builtin_expect (libgcc_s_resume == NULL, 0)) + init (); + libgcc_s_resume (exc); +} + +_Unwind_Reason_Code +__gcc_personality_v0 (int version, _Unwind_Action actions, + _Unwind_Exception_Class exception_class, + struct _Unwind_Exception *ue_header, + struct _Unwind_Context *context) +{ + if (__builtin_expect (libgcc_s_personality == NULL, 0)) + init (); + return libgcc_s_personality (version, actions, exception_class, + ue_header, context); +} + +void +_Unwind_SjLj_Register (struct SjLj_Function_Context *fc) +{ + if (__builtin_expect (libgcc_s_sjlj_register == NULL, 0)) + init (); + libgcc_s_sjlj_register (fc); +} + +void +_Unwind_SjLj_Unregister (struct SjLj_Function_Context *fc) +{ + if (__builtin_expect (libgcc_s_sjlj_unregister == NULL, 0)) + init (); + libgcc_s_sjlj_unregister (fc); +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind.h b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind.h new file mode 100644 index 000000000..eeb9cf8b6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind.h @@ -0,0 +1,279 @@ +/* Header file for the ARM EABI unwinder + Copyright (C) 2003, 2004, 2005, 2009 Free Software Foundation, Inc. + Contributed by Paul Brook + + This file is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + In addition to the permissions in the GNU General Public License, the + Free Software Foundation gives you unlimited permission to link the + compiled version of this file into combinations with other programs, + and to distribute those combinations without any restriction coming + from the use of this file. (The General Public License restrictions + do apply in other respects; for example, they cover modification of + the file, and distribution when not linked into a combine + executable.) + + This file 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* Language-independent unwinder header public defines. This contains both + ABI defined objects, and GNU support routines. */ + +#ifndef UNWIND_ARM_H +#define UNWIND_ARM_H + +#define __ARM_EABI_UNWINDER__ 1 + +#ifdef __cplusplus +extern "C" { +#endif + typedef unsigned _Unwind_Word __attribute__((__mode__(__word__))); + typedef signed _Unwind_Sword __attribute__((__mode__(__word__))); + typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__))); + typedef unsigned _Unwind_Internal_Ptr __attribute__((__mode__(__pointer__))); + typedef _Unwind_Word _uw; + typedef unsigned _uw64 __attribute__((mode(__DI__))); + typedef unsigned _uw16 __attribute__((mode(__HI__))); + typedef unsigned _uw8 __attribute__((mode(__QI__))); + + typedef enum + { + _URC_OK = 0, /* operation completed successfully */ + _URC_FOREIGN_EXCEPTION_CAUGHT = 1, + _URC_END_OF_STACK = 5, + _URC_HANDLER_FOUND = 6, + _URC_INSTALL_CONTEXT = 7, + _URC_CONTINUE_UNWIND = 8, + _URC_FAILURE = 9 /* unspecified failure of some kind */ + } + _Unwind_Reason_Code; + + typedef enum + { + _US_VIRTUAL_UNWIND_FRAME = 0, + _US_UNWIND_FRAME_STARTING = 1, + _US_UNWIND_FRAME_RESUME = 2, + _US_ACTION_MASK = 3, + _US_FORCE_UNWIND = 8, + _US_END_OF_STACK = 16 + } + _Unwind_State; + + /* Provided only for for compatibility with existing code. */ + typedef int _Unwind_Action; +#define _UA_SEARCH_PHASE 1 +#define _UA_CLEANUP_PHASE 2 +#define _UA_HANDLER_FRAME 4 +#define _UA_FORCE_UNWIND 8 +#define _UA_END_OF_STACK 16 +#define _URC_NO_REASON _URC_OK + + typedef struct _Unwind_Control_Block _Unwind_Control_Block; + typedef struct _Unwind_Context _Unwind_Context; + typedef _uw _Unwind_EHT_Header; + + + /* UCB: */ + + struct _Unwind_Control_Block + { +#ifdef _LIBC + /* For the benefit of code which assumes this is a scalar. All + glibc ever does is clear it. */ + _uw64 exception_class; +#else + char exception_class[8]; +#endif + void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block *); + /* Unwinder cache, private fields for the unwinder's use */ + struct + { + _uw reserved1; /* Forced unwind stop fn, 0 if not forced */ + _uw reserved2; /* Personality routine address */ + _uw reserved3; /* Saved callsite address */ + _uw reserved4; /* Forced unwind stop arg */ + _uw reserved5; + } + unwinder_cache; + /* Propagation barrier cache (valid after phase 1): */ + struct + { + _uw sp; + _uw bitpattern[5]; + } + barrier_cache; + /* Cleanup cache (preserved over cleanup): */ + struct + { + _uw bitpattern[4]; + } + cleanup_cache; + /* Pr cache (for pr's benefit): */ + struct + { + _uw fnstart; /* function start address */ + _Unwind_EHT_Header *ehtp; /* pointer to EHT entry header word */ + _uw additional; /* additional data */ + _uw reserved1; + } + pr_cache; + long long int :0; /* Force alignment to 8-byte boundary */ + }; + + /* Virtual Register Set*/ + + typedef enum + { + _UVRSC_CORE = 0, /* integer register */ + _UVRSC_VFP = 1, /* vfp */ + _UVRSC_FPA = 2, /* fpa */ + _UVRSC_WMMXD = 3, /* Intel WMMX data register */ + _UVRSC_WMMXC = 4 /* Intel WMMX control register */ + } + _Unwind_VRS_RegClass; + + typedef enum + { + _UVRSD_UINT32 = 0, + _UVRSD_VFPX = 1, + _UVRSD_FPAX = 2, + _UVRSD_UINT64 = 3, + _UVRSD_FLOAT = 4, + _UVRSD_DOUBLE = 5 + } + _Unwind_VRS_DataRepresentation; + + typedef enum + { + _UVRSR_OK = 0, + _UVRSR_NOT_IMPLEMENTED = 1, + _UVRSR_FAILED = 2 + } + _Unwind_VRS_Result; + + /* Frame unwinding state. */ + typedef struct + { + /* The current word (bytes packed msb first). */ + _uw data; + /* Pointer to the next word of data. */ + _uw *next; + /* The number of bytes left in this word. */ + _uw8 bytes_left; + /* The number of words pointed to by ptr. */ + _uw8 words_left; + } + __gnu_unwind_state; + + typedef _Unwind_Reason_Code (*personality_routine) (_Unwind_State, + _Unwind_Control_Block *, _Unwind_Context *); + + _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *, _Unwind_VRS_RegClass, + _uw, _Unwind_VRS_DataRepresentation, + void *); + + _Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context *, _Unwind_VRS_RegClass, + _uw, _Unwind_VRS_DataRepresentation, + void *); + + _Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context *, _Unwind_VRS_RegClass, + _uw, _Unwind_VRS_DataRepresentation); + + + /* Support functions for the PR. */ +#define _Unwind_Exception _Unwind_Control_Block + typedef char _Unwind_Exception_Class[8]; + + void * _Unwind_GetLanguageSpecificData (_Unwind_Context *); + _Unwind_Ptr _Unwind_GetRegionStart (_Unwind_Context *); + + /* These two should never be used. */ + _Unwind_Ptr _Unwind_GetDataRelBase (_Unwind_Context *); + _Unwind_Ptr _Unwind_GetTextRelBase (_Unwind_Context *); + + /* Interface functions: */ + _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block *ucbp); + void __attribute__((noreturn)) _Unwind_Resume(_Unwind_Control_Block *ucbp); + _Unwind_Reason_Code _Unwind_Resume_or_Rethrow (_Unwind_Control_Block *ucbp); + + typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) + (int, _Unwind_Action, _Unwind_Exception_Class, + _Unwind_Control_Block *, struct _Unwind_Context *, void *); + _Unwind_Reason_Code _Unwind_ForcedUnwind (_Unwind_Control_Block *, + _Unwind_Stop_Fn, void *); + _Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *); + void _Unwind_Complete(_Unwind_Control_Block *ucbp); + void _Unwind_DeleteException (_Unwind_Exception *); + + _Unwind_Reason_Code __gnu_unwind_frame (_Unwind_Control_Block *, + _Unwind_Context *); + _Unwind_Reason_Code __gnu_unwind_execute (_Unwind_Context *, + __gnu_unwind_state *); + + /* Decode an R_ARM_TARGET2 relocation. */ + static inline _Unwind_Word + _Unwind_decode_target2 (_Unwind_Word ptr) + { + _Unwind_Word tmp; + + tmp = *(_Unwind_Word *) ptr; + /* Zero values are always NULL. */ + if (!tmp) + return 0; + +#if defined(linux) || defined(__NetBSD__) + /* Pc-relative indirect. */ + tmp += ptr; + tmp = *(_Unwind_Word *) tmp; +#elif defined(__symbian__) + /* Absolute pointer. Nothing more to do. */ +#else + /* Pc-relative pointer. */ + tmp += ptr; +#endif + return tmp; + } + + static inline _Unwind_Word + _Unwind_GetGR (_Unwind_Context *context, int regno) + { + _uw val; + _Unwind_VRS_Get (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val); + return val; + } + + /* Return the address of the instruction, not the actual IP value. */ +#define _Unwind_GetIP(context) \ + (_Unwind_GetGR (context, 15) & ~(_Unwind_Word)1) + + static inline void + _Unwind_SetGR (_Unwind_Context *context, int regno, _Unwind_Word val) + { + _Unwind_VRS_Set (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val); + } + + /* The dwarf unwinder doesn't understand arm/thumb state. We assume the + landing pad uses the same instruction set as the call site. */ +#define _Unwind_SetIP(context, val) \ + _Unwind_SetGR (context, 15, val | (_Unwind_GetGR (context, 15) & 1)) + +typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) + (struct _Unwind_Context *, void *); + +extern _Unwind_Reason_Code _Unwind_Backtrace (_Unwind_Trace_Fn, void *); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* defined UNWIND_ARM_H */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/vfork.S new file mode 100644 index 000000000..935a4e904 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/vfork.S @@ -0,0 +1,39 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <tcb-offsets.h> + +/* Save the PID value. */ +#define SAVE_PID \ + str lr, [sp, #-4]!; /* Save LR. */ \ + mov r0, #0xffff0fff; /* Point to the high page. */ \ + mov lr, pc; /* Save our return address. */ \ + sub pc, r0, #31; /* Jump to the TLS entry. */ \ + ldr lr, [sp], #4; /* Restore LR. */ \ + mov r2, r0; /* Save the TLS addr in r2. */ \ + ldr r3, [r2, #PID_OFFSET]; /* Load the saved PID. */ \ + rsbs r0, r3, #0; /* Negate it. */ \ + moveq r0, #0x80000000; /* Use 0x80000000 if it was 0. */ \ + str r0, [r2, #PID_OFFSET] /* Store the temporary PID. */ + +/* Restore the old PID value in the parent. */ +#define RESTORE_PID \ + cmp r0, #0; /* If we are the parent... */ \ + strne r3, [r2, #PID_OFFSET] /* ... restore the saved PID. */ + +#include "../../../../../../../libc/sysdeps/linux/arm/vfork.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h b/libpthread/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h new file mode 100644 index 000000000..8f0df4f92 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h @@ -0,0 +1,100 @@ +/* Minimum guaranteed maximum values for system limits. Linux version. + Copyright (C) 1993-1998,2000,2002-2004,2008 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 +#ifndef ARG_MAX +# define __undef_ARG_MAX +#endif + +/* The kernel sources contain a file with all the needed information. */ +#include <linux/limits.h> + +/* 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 +/* Have to remove ARG_MAX? */ +#ifdef __undef_ARG_MAX +# undef ARG_MAX +# undef __undef_ARG_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. We are free to choose a reasonable value. */ +#define PTHREAD_STACK_MIN 16384 + +/* 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/libpthread/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h b/libpthread/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h new file mode 100644 index 000000000..2550355cd --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h @@ -0,0 +1,192 @@ +/* Define POSIX options for Linux. + Copyright (C) 1996-2004, 2006, 2008, 2009 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. */ + +#ifndef _BITS_POSIX_OPT_H +#define _BITS_POSIX_OPT_H 1 + +/* Job control is supported. */ +#define _POSIX_JOB_CONTROL 1 + +/* Processes have a saved set-user-ID and a saved set-group-ID. */ +#define _POSIX_SAVED_IDS 1 + +/* Priority scheduling is supported. */ +#define _POSIX_PRIORITY_SCHEDULING 200809L + +/* Synchronizing file data is supported. */ +#define _POSIX_SYNCHRONIZED_IO 200809L + +/* The fsync function is present. */ +#define _POSIX_FSYNC 200809L + +/* Mapping of files to memory is supported. */ +#define _POSIX_MAPPED_FILES 200809L + +/* Locking of all memory is supported. */ +#define _POSIX_MEMLOCK 200809L + +/* Locking of ranges of memory is supported. */ +#define _POSIX_MEMLOCK_RANGE 200809L + +/* Setting of memory protections is supported. */ +#define _POSIX_MEMORY_PROTECTION 200809L + +/* Some filesystems allow all users to change file ownership. */ +#define _POSIX_CHOWN_RESTRICTED 0 + +/* `c_cc' member of 'struct termios' structure can be disabled by + using the value _POSIX_VDISABLE. */ +#define _POSIX_VDISABLE '\0' + +/* Filenames are not silently truncated. */ +#define _POSIX_NO_TRUNC 1 + +/* X/Open realtime support is available. */ +#define _XOPEN_REALTIME 1 + +/* X/Open thread realtime support is available. */ +#define _XOPEN_REALTIME_THREADS 1 + +/* XPG4.2 shared memory is supported. */ +#define _XOPEN_SHM 1 + +/* Tell we have POSIX threads. */ +#define _POSIX_THREADS 200809L + +/* We have the reentrant functions described in POSIX. */ +#define _POSIX_REENTRANT_FUNCTIONS 1 +#define _POSIX_THREAD_SAFE_FUNCTIONS 200809L + +/* We provide priority scheduling for threads. */ +#define _POSIX_THREAD_PRIORITY_SCHEDULING 200809L + +/* We support user-defined stack sizes. */ +#define _POSIX_THREAD_ATTR_STACKSIZE 200809L + +/* We support user-defined stacks. */ +#define _POSIX_THREAD_ATTR_STACKADDR 200809L + +/* We support priority inheritence. */ +#define _POSIX_THREAD_PRIO_INHERIT 200809L + +/* We support priority protection, though only for non-robust + mutexes. */ +#define _POSIX_THREAD_PRIO_PROTECT 200809L + +#ifdef __USE_XOPEN2K8 +/* We support priority inheritence for robust mutexes. */ +# define _POSIX_THREAD_ROBUST_PRIO_INHERIT 200809L + +/* We do not support priority protection for robust mutexes. */ +# define _POSIX_THREAD_ROBUST_PRIO_PROTECT -1 +#endif + +/* We support POSIX.1b semaphores. */ +#define _POSIX_SEMAPHORES 200809L + +/* Real-time signals are supported. */ +#define _POSIX_REALTIME_SIGNALS 200809L + +/* We support asynchronous I/O. */ +#define _POSIX_ASYNCHRONOUS_IO 200809L +#define _POSIX_ASYNC_IO 1 +/* Alternative name for Unix98. */ +#define _LFS_ASYNCHRONOUS_IO 1 +/* Support for prioritization is also available. */ +#define _POSIX_PRIORITIZED_IO 200809L + +/* The LFS support in asynchronous I/O is also available. */ +#define _LFS64_ASYNCHRONOUS_IO 1 + +/* The rest of the LFS is also available. */ +#define _LFS_LARGEFILE 1 +#define _LFS64_LARGEFILE 1 +#define _LFS64_STDIO 1 + +/* POSIX shared memory objects are implemented. */ +#define _POSIX_SHARED_MEMORY_OBJECTS 200809L + +/* CPU-time clocks support needs to be checked at runtime. */ +#define _POSIX_CPUTIME 0 + +/* Clock support in threads must be also checked at runtime. */ +#define _POSIX_THREAD_CPUTIME 0 + +/* GNU libc provides regular expression handling. */ +#define _POSIX_REGEXP 1 + +/* Reader/Writer locks are available. */ +#define _POSIX_READER_WRITER_LOCKS 200809L + +/* We have a POSIX shell. */ +#define _POSIX_SHELL 1 + +/* We support the Timeouts option. */ +#define _POSIX_TIMEOUTS 200809L + +/* We support spinlocks. */ +#define _POSIX_SPIN_LOCKS 200809L + +/* The `spawn' function family is supported. */ +#define _POSIX_SPAWN 200809L + +/* We have POSIX timers. */ +#define _POSIX_TIMERS 200809L + +/* The barrier functions are available. */ +#define _POSIX_BARRIERS 200809L + +/* POSIX message queues are available. */ +#define _POSIX_MESSAGE_PASSING 200809L + +/* Thread process-shared synchronization is supported. */ +#define _POSIX_THREAD_PROCESS_SHARED 200809L + +/* The monotonic clock might be available. */ +#define _POSIX_MONOTONIC_CLOCK 0 + +/* The clock selection interfaces are available. */ +#define _POSIX_CLOCK_SELECTION 200809L + +/* Advisory information interfaces are available. */ +#define _POSIX_ADVISORY_INFO 200809L + +/* IPv6 support is available. */ +#define _POSIX_IPV6 200809L + +/* Raw socket support is available. */ +#define _POSIX_RAW_SOCKETS 200809L + +/* We have at least one terminal. */ +#define _POSIX2_CHAR_TERM 200809L + +/* Neither process nor thread sporadic server interfaces is available. */ +#define _POSIX_SPORADIC_SERVER -1 +#define _POSIX_THREAD_SPORADIC_SERVER -1 + +/* trace.h is not available. */ +#define _POSIX_TRACE -1 +#define _POSIX_TRACE_EVENT_FILTER -1 +#define _POSIX_TRACE_INHERIT -1 +#define _POSIX_TRACE_LOG -1 + +/* Typed memory objects are not available. */ +#define _POSIX_TYPED_MEMORY_OBJECTS -1 + +#endif /* bits/posix_opt.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/close.S b/libpthread/nptl/sysdeps/unix/sysv/linux/close.S new file mode 100644 index 000000000..cf50a1eae --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/close.S @@ -0,0 +1,21 @@ +#include <sysdep-cancel.h> + +/* +extern int __close_nocancel (int) attribute_hidden; +*/ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + + +PSEUDO (__libc_close, close, 1) +ret +PSEUDO_END(__libc_close) + +libc_hidden_def (__close_nocancel) +libc_hidden_def (__libc_close) +weak_alias (__libc_close, __close) +libc_hidden_weak (__close) +weak_alias (__libc_close, close) +libc_hidden_weak (close) + + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/connect.S b/libpthread/nptl/sysdeps/unix/sysv/linux/connect.S new file mode 100644 index 000000000..441843fa0 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/connect.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_connect +#error Missing definition of NR_connect needed for cancellation. +#endif +PSEUDO (__libc_connect, connect, 3) +ret +PSEUDO_END(__libc_connect) +libc_hidden_def (__libc_connect) +weak_alias (__libc_connect, __connect) +libc_hidden_weak (__connect) +weak_alias (__libc_connect, connect) +libc_hidden_weak (connect) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/creat.S b/libpthread/nptl/sysdeps/unix/sysv/linux/creat.S new file mode 100644 index 000000000..cd0e1b879 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/creat.S @@ -0,0 +1,7 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_creat, creat, 2) +ret +PSEUDO_END(__libc_creat) +libc_hidden_def (__libc_creat) +weak_alias (__libc_creat, creat) +libc_hidden_weak (creat) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/createthread.c b/libpthread/nptl/sysdeps/unix/sysv/linux/createthread.c new file mode 100644 index 000000000..9149efe58 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/createthread.c @@ -0,0 +1,24 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>. + + 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. */ + +/* Value passed to 'clone' for initialization of the thread register. */ +#define TLS_VALUE pd + +/* Get the real implementation. */ +#include <sysdeps/pthread/createthread.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/exit-thread.S b/libpthread/nptl/sysdeps/unix/sysv/linux/exit-thread.S new file mode 100644 index 000000000..bb996fecf --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/exit-thread.S @@ -0,0 +1,23 @@ +/* Copyright (C) 1991,92,97,99,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> + +PSEUDO (__exit_thread, exit, 1) + /* Shouldn't get here. */ +PSEUDO_END(__exit_thread) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c new file mode 100644 index 000000000..2d4cae224 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c @@ -0,0 +1,229 @@ +/* Copyright (C) 2002, 2003, 2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> +#include <sysdep.h> +#include <tls.h> +#include "fork.h" +#include <hp-timing.h> +#include <ldsodefs.h> +#include <atomic.h> +#include <errno.h> + +unsigned long int *__fork_generation_pointer; + + + +/* The single linked list of all currently registered for handlers. */ +struct fork_handler *__fork_handlers; + + +static void +fresetlockfiles (void) +{ + FILE *fp; +#ifdef __USE_STDIO_FUTEXES__ + for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen) + STDIO_INIT_MUTEX(fp->__lock); +#else + pthread_mutexattr_t attr; + + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP); + + for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen) + pthread_mutex_init(&fp->__lock, &attr); + + pthread_mutexattr_destroy(&attr); +#endif +} + + +pid_t +__libc_fork (void) +{ + pid_t pid; + struct used_handler + { + struct fork_handler *handler; + struct used_handler *next; + } *allp = NULL; + + /* Run all the registered preparation handlers. In reverse order. + While doing this we build up a list of all the entries. */ + struct fork_handler *runp; + while ((runp = __fork_handlers) != NULL) + { + /* Make sure we read from the current RUNP pointer. */ + atomic_full_barrier (); + + unsigned int oldval = runp->refcntr; + + if (oldval == 0) + /* This means some other thread removed the list just after + the pointer has been loaded. Try again. Either the list + is empty or we can retry it. */ + continue; + + /* Bump the reference counter. */ + if (atomic_compare_and_exchange_bool_acq (&__fork_handlers->refcntr, + oldval + 1, oldval)) + /* The value changed, try again. */ + continue; + + /* We bumped the reference counter for the first entry in the + list. That means that none of the following entries will + just go away. The unloading code works in the order of the + list. + + While executing the registered handlers we are building a + list of all the entries so that we can go backward later on. */ + while (1) + { + /* Execute the handler if there is one. */ + if (runp->prepare_handler != NULL) + runp->prepare_handler (); + + /* Create a new element for the list. */ + struct used_handler *newp + = (struct used_handler *) alloca (sizeof (*newp)); + newp->handler = runp; + newp->next = allp; + allp = newp; + + /* Advance to the next handler. */ + runp = runp->next; + if (runp == NULL) + break; + + /* Bump the reference counter for the next entry. */ + atomic_increment (&runp->refcntr); + } + + /* We are done. */ + break; + } + + __UCLIBC_IO_MUTEX_LOCK_CANCEL_UNSAFE(_stdio_openlist_add_lock); + +#ifndef NDEBUG + pid_t ppid = THREAD_GETMEM (THREAD_SELF, tid); +#endif + + /* We need to prevent the getpid() code to update the PID field so + that, if a signal arrives in the child very early and the signal + handler uses getpid(), the value returned is correct. */ + pid_t parentpid = THREAD_GETMEM (THREAD_SELF, pid); + THREAD_SETMEM (THREAD_SELF, pid, -parentpid); + +#ifdef ARCH_FORK + pid = ARCH_FORK (); +#else +# error "ARCH_FORK must be defined so that the CLONE_SETTID flag is used" + pid = INLINE_SYSCALL (fork, 0); +#endif + + + if (pid == 0) + { + struct pthread *self = THREAD_SELF; + + assert (THREAD_GETMEM (self, tid) != ppid); + + if (__fork_generation_pointer != NULL) + *__fork_generation_pointer += 4; + + /* Adjust the PID field for the new process. */ + THREAD_SETMEM (self, pid, THREAD_GETMEM (self, tid)); + +#if HP_TIMING_AVAIL + /* The CPU clock of the thread and process have to be set to zero. */ + hp_timing_t now; + HP_TIMING_NOW (now); + THREAD_SETMEM (self, cpuclock_offset, now); + GL(dl_cpuclock_offset) = now; +#endif + + /* Reset the file list. These are recursive mutexes. */ + fresetlockfiles (); + + /* Reset locks in the I/O code. */ + STDIO_INIT_MUTEX(_stdio_openlist_add_lock); + + /* XXX reset any locks in dynamic loader */ + + /* Run the handlers registered for the child. */ + while (allp != NULL) + { + if (allp->handler->child_handler != NULL) + allp->handler->child_handler (); + + /* Note that we do not have to wake any possible waiter. + This is the only thread in the new process. The count + may have been bumped up by other threads doing a fork. + We reset it to 1, to avoid waiting for non-existing + thread(s) to release the count. */ + allp->handler->refcntr = 1; + + /* XXX We could at this point look through the object pool + and mark all objects not on the __fork_handlers list as + unused. This is necessary in case the fork() happened + while another thread called dlclose() and that call had + to create a new list. */ + + allp = allp->next; + } + + /* Initialize the fork lock. */ + __fork_lock = LLL_LOCK_INITIALIZER; + } + else + { + assert (THREAD_GETMEM (THREAD_SELF, tid) == ppid); + + /* Restore the PID value. */ + THREAD_SETMEM (THREAD_SELF, pid, parentpid); + + /* We execute this even if the 'fork' call failed. */ + __UCLIBC_IO_MUTEX_UNLOCK_CANCEL_UNSAFE(_stdio_openlist_add_lock); + + /* Run the handlers registered for the parent. */ + while (allp != NULL) + { + if (allp->handler->parent_handler != NULL) + allp->handler->parent_handler (); + + if (atomic_decrement_and_test (&allp->handler->refcntr) + && allp->handler->need_signal) + lll_futex_wake (allp->handler->refcntr, 1, LLL_PRIVATE); + + allp = allp->next; + } + } + + return pid; +} +weak_alias(__libc_fork,__fork) +libc_hidden_proto(fork) +weak_alias(__libc_fork,fork) +libc_hidden_weak(fork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/fork.h b/libpthread/nptl/sysdeps/unix/sysv/linux/fork.h new file mode 100644 index 000000000..a00cfabe2 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/fork.h @@ -0,0 +1,60 @@ +/* Copyright (C) 2002, 2003, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <lowlevellock.h> + +/* The fork generation counter, defined in libpthread. */ +extern unsigned long int __fork_generation attribute_hidden; + +/* Pointer to the fork generation counter in the thread library. */ +extern unsigned long int *__fork_generation_pointer attribute_hidden; + +/* Lock to protect allocation and deallocation of fork handlers. */ +extern int __fork_lock attribute_hidden; + +/* Elements of the fork handler lists. */ +struct fork_handler +{ + struct fork_handler *next; + void (*prepare_handler) (void); + void (*parent_handler) (void); + void (*child_handler) (void); + void *dso_handle; + unsigned int refcntr; + int need_signal; +}; + +/* The single linked list of all currently registered for handlers. */ +extern struct fork_handler *__fork_handlers attribute_hidden; + + +/* Function to call to unregister fork handlers. */ +extern void __unregister_atfork (void *dso_handle) attribute_hidden; +#define UNREGISTER_ATFORK(dso_handle) __unregister_atfork (dso_handle) + + +/* C library side function to register new fork handlers. */ +extern int __register_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void), + void *dso_handle); +libc_hidden_proto (__register_atfork) + +/* Add a new element to the fork list. */ +extern void __linkin_atfork (struct fork_handler *newp) attribute_hidden; diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/getpid.c b/libpthread/nptl/sysdeps/unix/sysv/linux/getpid.c new file mode 100644 index 000000000..96e2bf439 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/getpid.c @@ -0,0 +1,64 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 <unistd.h> +#include <tls.h> +#include <sysdep.h> + + +#ifndef NOT_IN_libc +static inline __attribute__((always_inline)) pid_t really_getpid (pid_t oldval); + +static inline __attribute__((always_inline)) pid_t +really_getpid (pid_t oldval) +{ + if (__builtin_expect (oldval == 0, 1)) + { + pid_t selftid = THREAD_GETMEM (THREAD_SELF, tid); + if (__builtin_expect (selftid != 0, 1)) + return selftid; + } + + INTERNAL_SYSCALL_DECL (err); + pid_t result = INTERNAL_SYSCALL (getpid, err, 0); + + /* We do not set the PID field in the TID here since we might be + called from a signal handler while the thread executes fork. */ + if (oldval == 0) + THREAD_SETMEM (THREAD_SELF, tid, result); + return result; +} +#endif + +pid_t +__getpid (void) +{ +#ifdef NOT_IN_libc + INTERNAL_SYSCALL_DECL (err); + pid_t result = INTERNAL_SYSCALL (getpid, err, 0); +#else + pid_t result = THREAD_GETMEM (THREAD_SELF, pid); + if (__builtin_expect (result <= 0, 0)) + result = really_getpid (result); +#endif + return result; +} +libc_hidden_proto(getpid) +weak_alias(__getpid, getpid) +libc_hidden_weak(getpid) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/Makefile new file mode 100644 index 000000000..43a6fad84 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../../../../ +top_builddir=../../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/Makefile.arch b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/Makefile.arch new file mode 100644 index 000000000..570aa560e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/Makefile.arch @@ -0,0 +1,71 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# +LINUX_ARCH_DIR:=$(top_srcdir)libpthread/nptl/sysdeps/unix/sysv/linux/i386 +LINUX_ARCH_OUT:=$(top_builddir)libpthread/nptl/sysdeps/unix/sysv/linux/i386 + +ASFLAGS += -DUSE___THREAD + +libpthread_SSRC = pt-vfork.S clone.S pthread_spin_unlock.S pthread_once.S +libpthread_CSRC = pthread_spin_init.c pt-__syscall_error.c + +libc_a_CSRC = fork.c +libc_a_SSRC = clone.S vfork.S + +libpthread_SSRC += i486/lowlevellock.S i486/pthread_barrier_wait.S i486/pthread_cond_signal.S i486/pthread_cond_broadcast.S \ + i486/lowlevelrobustlock.S i486/sem_post.S i486/sem_timedwait.S \ + i486/sem_trywait.S i486/sem_wait.S i486/pthread_rwlock_rdlock.S i486/pthread_rwlock_wrlock.S \ + i486/pthread_rwlock_timedrdlock.S i486/pthread_rwlock_timedwrlock.S i486/pthread_rwlock_unlock.S +#i486/pthread_cond_timedwait.S i486/pthread_cond_wait.S + +libc_a_SSRC += i486/libc-lowlevellock.S + + +CFLAGS-OMIT-fork.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-pt-__syscall_error.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y) +CFLAGS-fork.c = -D__USE_STDIO_FUTEXES__ +endif + +ASFLAGS-pt-vfork.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT +ASFLAGS-lowlevellock.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT +ASFLAGS-lowlevelrobustlock.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT +ASFLAGS-pthread_once.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT +ASFLAGS-pthread_spin_unlock.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT + + +ASFLAGS-clone.S = -D_LIBC_REENTRANT +ASFLAGS-vfork.S = -D_LIBC_REENTRANT +ASFLAGS-libc-lowlevellock.S = -D_LIBC_REENTRANT + +CFLAGS += $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +LINUX_ARCH_OBJ:=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libpthread_SSRC)) +LINUX_ARCH_OBJ+=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libpthread_CSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(LINUX_ARCH_OBJ:.o=.os) +else +libpthread-a-y += $(LINUX_ARCH_OBJ) +endif +libpthread-so-y += $(LINUX_ARCH_OBJ:.o=.oS) + +libpthread-nomulti-y+=$(LINUX_ARCH_OBJS) + +LIBC_LINUX_ARCH_OBJ:=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libc_a_CSRC)) +LIBC_LINUX_ARCH_OBJ+=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libc_a_SSRC)) + +libc-static-y+=$(LIBC_LINUX_ARCH_OBJ) +libc-shared-y+=$(LIBC_LINUX_ARCH_OBJ:.o=.oS) + +libc-nomulti-y+=$(LIBC_LINUX_ARCH_OBJ) + +objclean-y+=nptl_linux_arch_clean + +nptl_linux_arch_clean: + $(do_rm) $(addprefix $(LINUX_ARCH_OUT)/*., o os oS) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h new file mode 100644 index 000000000..9e3e016fb --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h @@ -0,0 +1,173 @@ +/* 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 + 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. */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#define __SIZEOF_PTHREAD_ATTR_T 36 +#define __SIZEOF_PTHREAD_MUTEX_T 24 +#define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +#define __SIZEOF_PTHREAD_COND_T 48 +#define __SIZEOF_PTHREAD_COND_COMPAT_T 12 +#define __SIZEOF_PTHREAD_CONDATTR_T 4 +#define __SIZEOF_PTHREAD_RWLOCK_T 32 +#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +#define __SIZEOF_PTHREAD_BARRIER_T 20 +#define __SIZEOF_PTHREAD_BARRIERATTR_T 4 + + +/* Thread identifiers. The structure of the attribute type is not + exposed on purpose. */ +typedef unsigned long int pthread_t; + + +typedef union +{ + char __size[__SIZEOF_PTHREAD_ATTR_T]; + long int __align; +} pthread_attr_t; + + +typedef struct __pthread_internal_slist +{ + struct __pthread_internal_slist *__next; +} __pthread_slist_t; + + +/* Data structures for mutex handling. The structure of the attribute + type is not exposed on purpose. */ +typedef union +{ + struct __pthread_mutex_s + { + int __lock; + unsigned int __count; + int __owner; + /* KIND must stay at this position in the structure to maintain + binary compatibility. */ + int __kind; + unsigned int __nusers; + __extension__ union + { + int __spins; + __pthread_slist_t __list; + }; + } __data; + char __size[__SIZEOF_PTHREAD_MUTEX_T]; + long int __align; +} pthread_mutex_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; + long int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling. The structure of + the attribute type is not exposed on purpose. */ +typedef union +{ + struct + { + int __lock; + unsigned int __futex; + __extension__ unsigned long long int __total_seq; + __extension__ unsigned long long int __wakeup_seq; + __extension__ unsigned long long int __woken_seq; + void *__mutex; + unsigned int __nwaiters; + unsigned int __broadcast_seq; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_CONDATTR_T]; + long int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling. The + structure of the attribute type is not exposed on purpose. */ +typedef union +{ + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; + unsigned char __shared; + unsigned char __pad1; + unsigned char __pad2; + int __writer; + } __data; + char __size[__SIZEOF_PTHREAD_RWLOCK_T]; + long int __align; +} pthread_rwlock_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; + long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type. The structure of the type is + deliberately not exposed. */ +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIER_T]; + long int __align; +} pthread_barrier_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; + int __align; +} pthread_barrierattr_t; +#endif + + +/* Extra attributes for the cleanup functions. */ +#define __cleanup_fct_attribute __attribute__ ((__regparm__ (1))) + +#endif /* bits/pthreadtypes.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h new file mode 100644 index 000000000..934493c30 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SEMAPHORE_H +# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." +#endif + + +#define __SIZEOF_SEM_T 16 + + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + + +typedef union +{ + char __size[__SIZEOF_SEM_T]; + long int __align; +} sem_t; diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/clone.S new file mode 100644 index 000000000..9c7c46467 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <libc/sysdeps/linux/i386/clone.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/createthread.c b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/createthread.c new file mode 100644 index 000000000..35719be96 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/createthread.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The "thread register" gets initialized from a segment descriptor. + Initialize such a descriptor first. */ +#define PREPARE_CREATE \ + union user_desc_init desc; \ + \ + /* Describe the thread-local storage segment. */ \ + \ + /* The 'entry_number' field. The first three bits of the segment \ + register value select the GDT, ignore them. We get the index \ + from the value of the %gs register in the current thread. */ \ + desc.vals[0] = TLS_GET_GS () >> 3; \ + /* The 'base_addr' field. Pointer to the TCB. */ \ + desc.vals[1] = (unsigned long int) pd; \ + /* The 'limit' field. We use 4GB which is 0xfffff pages. */ \ + desc.vals[2] = 0xfffff; \ + /* Collapsed value of the bitfield: \ + .seg_32bit = 1 \ + .contents = 0 \ + .read_exec_only = 0 \ + .limit_in_pages = 1 \ + .seg_not_present = 0 \ + .useable = 1 */ \ + desc.vals[3] = 0x51 + +/* Value passed to 'clone' for initialization of the thread register. */ +#define TLS_VALUE &desc.desc + + +/* Get the real implementation. */ +#include <sysdeps/pthread/createthread.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/fork.c new file mode 100644 index 000000000..813e5299a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/fork.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sched.h> +#include <signal.h> +#include <sysdep.h> +#include <tls.h> + + +#define ARCH_FORK() \ + INLINE_SYSCALL (clone, 5, \ + CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0, \ + NULL, NULL, &THREAD_SELF->tid) + +#include "../fork.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S new file mode 100644 index 000000000..ce8ad27aa --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "lowlevellock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S new file mode 100644 index 000000000..00f8b56f9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S @@ -0,0 +1,459 @@ +/* Copyright (C) 2002-2004, 2006, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include <bits/kernel-features.h> +#include <lowlevellock.h> +#include <tcb-offsets.h> + + .text + +#ifdef __ASSUME_PRIVATE_FUTEX +# define LOAD_PRIVATE_FUTEX_WAIT(reg) \ + movl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg +# define LOAD_PRIVATE_FUTEX_WAKE(reg) \ + movl $(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg +# define LOAD_FUTEX_WAIT(reg) \ + xorl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg +# define LOAD_FUTEX_WAIT_ABS(reg) \ + xorl $(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME), reg +# define LOAD_FUTEX_WAKE(reg) \ + xorl $(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg +#else +# if FUTEX_WAIT == 0 +# define LOAD_PRIVATE_FUTEX_WAIT(reg) \ + movl %gs:PRIVATE_FUTEX, reg +# else +# define LOAD_PRIVATE_FUTEX_WAIT(reg) \ + movl %gs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAIT, reg +# endif +# define LOAD_PRIVATE_FUTEX_WAKE(reg) \ + movl %gs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAKE, reg +# if FUTEX_WAIT == 0 +# define LOAD_FUTEX_WAIT(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %gs:PRIVATE_FUTEX, reg +# else +# define LOAD_FUTEX_WAIT(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %gs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAIT, reg +# endif +# define LOAD_FUTEX_WAIT_ABS(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %gs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME, reg +# define LOAD_FUTEX_WAKE(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %gs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAKE, reg +#endif + + .globl __lll_lock_wait_private + .type __lll_lock_wait_private,@function + .hidden __lll_lock_wait_private + .align 16 +__lll_lock_wait_private: + cfi_startproc + pushl %edx + cfi_adjust_cfa_offset(4) + pushl %ebx + cfi_adjust_cfa_offset(4) + pushl %esi + cfi_adjust_cfa_offset(4) + cfi_offset(%edx, -8) + cfi_offset(%ebx, -12) + cfi_offset(%esi, -16) + + movl $2, %edx + movl %ecx, %ebx + xorl %esi, %esi /* No timeout. */ + LOAD_PRIVATE_FUTEX_WAIT (%ecx) + + cmpl %edx, %eax /* NB: %edx == 2 */ + jne 2f + +1: movl $SYS_futex, %eax + ENTER_KERNEL + +2: movl %edx, %eax + xchgl %eax, (%ebx) /* NB: lock is implied */ + + testl %eax, %eax + jnz 1b + + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %edx + cfi_adjust_cfa_offset(-4) + cfi_restore(%edx) + ret + cfi_endproc + .size __lll_lock_wait_private,.-__lll_lock_wait_private + +#ifdef NOT_IN_libc + .globl __lll_lock_wait + .type __lll_lock_wait,@function + .hidden __lll_lock_wait + .align 16 +__lll_lock_wait: + cfi_startproc + pushl %edx + cfi_adjust_cfa_offset(4) + pushl %ebx + cfi_adjust_cfa_offset(4) + pushl %esi + cfi_adjust_cfa_offset(4) + cfi_offset(%edx, -8) + cfi_offset(%ebx, -12) + cfi_offset(%esi, -16) + + movl %edx, %ebx + movl $2, %edx + xorl %esi, %esi /* No timeout. */ + LOAD_FUTEX_WAIT (%ecx) + + cmpl %edx, %eax /* NB: %edx == 2 */ + jne 2f + +1: movl $SYS_futex, %eax + ENTER_KERNEL + +2: movl %edx, %eax + xchgl %eax, (%ebx) /* NB: lock is implied */ + + testl %eax, %eax + jnz 1b + + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %edx + cfi_adjust_cfa_offset(-4) + cfi_restore(%edx) + ret + cfi_endproc + .size __lll_lock_wait,.-__lll_lock_wait + + /* %ecx: futex + %esi: flags + %edx: timeout + %eax: futex value + */ + .globl __lll_timedlock_wait + .type __lll_timedlock_wait,@function + .hidden __lll_timedlock_wait + .align 16 +__lll_timedlock_wait: + cfi_startproc + pushl %ebp + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%ebp, 0) + pushl %ebx + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%ebx, 0) + +# ifndef __ASSUME_FUTEX_CLOCK_REALTIME +# ifdef __PIC__ + LOAD_PIC_REG (bx) + cmpl $0, __have_futex_clock_realtime@GOTOFF(%ebx) +# else + cmpl $0, __have_futex_clock_realtime +# endif + je .Lreltmo +# endif + + movl %ecx, %ebx + movl %esi, %ecx + movl %edx, %esi + movl $0xffffffff, %ebp + LOAD_FUTEX_WAIT_ABS (%ecx) + + movl $2, %edx + cmpl %edx, %eax + jne 2f + +1: movl $SYS_futex, %eax + movl $2, %edx + ENTER_KERNEL + +2: xchgl %edx, (%ebx) /* NB: lock is implied */ + + testl %edx, %edx + jz 3f + + cmpl $-ETIMEDOUT, %eax + je 4f + cmpl $-EINVAL, %eax + jne 1b +4: movl %eax, %edx + negl %edx + +3: movl %edx, %eax +7: popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %ebp + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebp) + ret + +# ifndef __ASSUME_FUTEX_CLOCK_REALTIME +.Lreltmo: + /* Check for a valid timeout value. */ + cmpl $1000000000, 4(%edx) + jae 3f + + pushl %esi + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%esi, 0) + pushl %edi + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%edi, 0) + + /* Stack frame for the timespec and timeval structs. */ + subl $8, %esp + cfi_adjust_cfa_offset(8) + + movl %ecx, %ebp + movl %edx, %edi + + movl $2, %edx + xchgl %edx, (%ebp) + + test %edx, %edx + je 6f + +1: + /* Get current time. */ + movl %esp, %ebx + xorl %ecx, %ecx + movl $__NR_gettimeofday, %eax + ENTER_KERNEL + + /* Compute relative timeout. */ + movl 4(%esp), %eax + movl $1000, %edx + mul %edx /* Milli seconds to nano seconds. */ + movl (%edi), %ecx + movl 4(%edi), %edx + subl (%esp), %ecx + subl %eax, %edx + jns 4f + addl $1000000000, %edx + subl $1, %ecx +4: testl %ecx, %ecx + js 2f /* Time is already up. */ + + /* Store relative timeout. */ + movl %ecx, (%esp) + movl %edx, 4(%esp) + + /* Futex call. */ + movl %ebp, %ebx + movl $2, %edx + movl %esp, %esi + movl 16(%esp), %ecx + LOAD_FUTEX_WAIT (%ecx) + movl $SYS_futex, %eax + ENTER_KERNEL + + /* NB: %edx == 2 */ + xchgl %edx, (%ebp) + + testl %edx, %edx + je 6f + + cmpl $-ETIMEDOUT, %eax + jne 1b +2: movl $ETIMEDOUT, %edx + +6: addl $8, %esp + cfi_adjust_cfa_offset(-8) + popl %edi + cfi_adjust_cfa_offset(-4) + cfi_restore(%edi) + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) +7: popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %ebp + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebp) + movl %edx, %eax + ret + +3: movl $EINVAL, %edx + jmp 7b +# endif + cfi_endproc + .size __lll_timedlock_wait,.-__lll_timedlock_wait +#endif + + .globl __lll_unlock_wake_private + .type __lll_unlock_wake_private,@function + .hidden __lll_unlock_wake_private + .align 16 +__lll_unlock_wake_private: + cfi_startproc + pushl %ebx + cfi_adjust_cfa_offset(4) + pushl %ecx + cfi_adjust_cfa_offset(4) + pushl %edx + cfi_adjust_cfa_offset(4) + cfi_offset(%ebx, -8) + cfi_offset(%ecx, -12) + cfi_offset(%edx, -16) + + movl %eax, %ebx + movl $0, (%eax) + LOAD_PRIVATE_FUTEX_WAKE (%ecx) + movl $1, %edx /* Wake one thread. */ + movl $SYS_futex, %eax + ENTER_KERNEL + + popl %edx + cfi_adjust_cfa_offset(-4) + cfi_restore(%edx) + popl %ecx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ecx) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + ret + cfi_endproc + .size __lll_unlock_wake_private,.-__lll_unlock_wake_private + +#ifdef NOT_IN_libc + .globl __lll_unlock_wake + .type __lll_unlock_wake,@function + .hidden __lll_unlock_wake + .align 16 +__lll_unlock_wake: + cfi_startproc + pushl %ebx + cfi_adjust_cfa_offset(4) + pushl %ecx + cfi_adjust_cfa_offset(4) + pushl %edx + cfi_adjust_cfa_offset(4) + cfi_offset(%ebx, -8) + cfi_offset(%ecx, -12) + cfi_offset(%edx, -16) + + movl %eax, %ebx + movl $0, (%eax) + LOAD_FUTEX_WAKE (%ecx) + movl $1, %edx /* Wake one thread. */ + movl $SYS_futex, %eax + ENTER_KERNEL + + popl %edx + cfi_adjust_cfa_offset(-4) + cfi_restore(%edx) + popl %ecx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ecx) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + ret + cfi_endproc + .size __lll_unlock_wake,.-__lll_unlock_wake + + .globl __lll_timedwait_tid + .type __lll_timedwait_tid,@function + .hidden __lll_timedwait_tid + .align 16 +__lll_timedwait_tid: + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + movl %eax, %ebp + movl %edx, %edi + subl $8, %esp + + /* Get current time. */ +2: movl %esp, %ebx + xorl %ecx, %ecx + movl $__NR_gettimeofday, %eax + ENTER_KERNEL + + /* Compute relative timeout. */ + movl 4(%esp), %eax + movl $1000, %edx + mul %edx /* Milli seconds to nano seconds. */ + movl (%edi), %ecx + movl 4(%edi), %edx + subl (%esp), %ecx + subl %eax, %edx + jns 5f + addl $1000000000, %edx + subl $1, %ecx +5: testl %ecx, %ecx + js 6f /* Time is already up. */ + + movl %ecx, (%esp) /* Store relative timeout. */ + movl %edx, 4(%esp) + + movl (%ebp), %edx + testl %edx, %edx + jz 4f + + movl %esp, %esi + /* XXX The kernel so far uses global futex for the wakeup at + all times. */ + xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */ + movl %ebp, %ebx + movl $SYS_futex, %eax + ENTER_KERNEL + + cmpl $0, (%ebx) + jne 1f +4: xorl %eax, %eax + +3: addl $8, %esp + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + +1: cmpl $-ETIMEDOUT, %eax + jne 2b +6: movl $ETIMEDOUT, %eax + jmp 3b + .size __lll_timedwait_tid,.-__lll_timedwait_tid +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S new file mode 100644 index 000000000..1d038001c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S @@ -0,0 +1,234 @@ +/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include <lowlevellock.h> +#include <lowlevelrobustlock.h> +#include <bits/kernel-features.h> +#include <tls.h> + + .text + +#define FUTEX_WAITERS 0x80000000 +#define FUTEX_OWNER_DIED 0x40000000 + +#ifdef __ASSUME_PRIVATE_FUTEX +# define LOAD_FUTEX_WAIT(reg) \ + xorl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg +#else +# if FUTEX_WAIT == 0 +# define LOAD_FUTEX_WAIT(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %gs:PRIVATE_FUTEX, reg +# else +# define LOAD_FUTEX_WAIT(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %gs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAIT, reg +# endif +#endif + + .globl __lll_robust_lock_wait + .type __lll_robust_lock_wait,@function + .hidden __lll_robust_lock_wait + .align 16 +__lll_robust_lock_wait: + cfi_startproc + pushl %edx + cfi_adjust_cfa_offset(4) + pushl %ebx + cfi_adjust_cfa_offset(4) + pushl %esi + cfi_adjust_cfa_offset(4) + cfi_offset(%edx, -8) + cfi_offset(%ebx, -12) + cfi_offset(%esi, -16) + + movl %edx, %ebx + xorl %esi, %esi /* No timeout. */ + LOAD_FUTEX_WAIT (%ecx) + +4: movl %eax, %edx + orl $FUTEX_WAITERS, %edx + + testl $FUTEX_OWNER_DIED, %eax + jnz 3f + + cmpl %edx, %eax /* NB: %edx == 2 */ + je 1f + + LOCK + cmpxchgl %edx, (%ebx) + jnz 2f + +1: movl $SYS_futex, %eax + ENTER_KERNEL + + movl (%ebx), %eax + +2: test %eax, %eax + jne 4b + + movl %gs:TID, %edx + orl $FUTEX_WAITERS, %edx + LOCK + cmpxchgl %edx, (%ebx) + jnz 4b + /* NB: %eax == 0 */ + +3: popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %edx + cfi_adjust_cfa_offset(-4) + cfi_restore(%edx) + ret + cfi_endproc + .size __lll_robust_lock_wait,.-__lll_robust_lock_wait + + + .globl __lll_robust_timedlock_wait + .type __lll_robust_timedlock_wait,@function + .hidden __lll_robust_timedlock_wait + .align 16 +__lll_robust_timedlock_wait: + cfi_startproc + /* Check for a valid timeout value. */ + cmpl $1000000000, 4(%edx) + jae 3f + + pushl %edi + cfi_adjust_cfa_offset(4) + pushl %esi + cfi_adjust_cfa_offset(4) + pushl %ebx + cfi_adjust_cfa_offset(4) + pushl %ebp + cfi_adjust_cfa_offset(4) + cfi_offset(%edi, -8) + cfi_offset(%esi, -12) + cfi_offset(%ebx, -16) + cfi_offset(%ebp, -20) + + /* Stack frame for the timespec and timeval structs. */ + subl $12, %esp + cfi_adjust_cfa_offset(12) + + movl %ecx, %ebp + movl %edx, %edi + +1: movl %eax, 8(%esp) + + /* Get current time. */ + movl %esp, %ebx + xorl %ecx, %ecx + movl $__NR_gettimeofday, %eax + ENTER_KERNEL + + /* Compute relative timeout. */ + movl 4(%esp), %eax + movl $1000, %edx + mul %edx /* Milli seconds to nano seconds. */ + movl (%edi), %ecx + movl 4(%edi), %edx + subl (%esp), %ecx + subl %eax, %edx + jns 4f + addl $1000000000, %edx + subl $1, %ecx +4: testl %ecx, %ecx + js 8f /* Time is already up. */ + + /* Store relative timeout. */ + movl %ecx, (%esp) + movl %edx, 4(%esp) + + movl %ebp, %ebx + + movl 8(%esp), %edx + movl %edx, %eax + orl $FUTEX_WAITERS, %edx + + testl $FUTEX_OWNER_DIED, %eax + jnz 6f + + cmpl %eax, %edx + je 2f + + LOCK + cmpxchgl %edx, (%ebx) + movl $0, %ecx /* Must use mov to avoid changing cc. */ + jnz 5f + +2: + /* Futex call. */ + movl %esp, %esi + movl 20(%esp), %ecx + LOAD_FUTEX_WAIT (%ecx) + movl $SYS_futex, %eax + ENTER_KERNEL + movl %eax, %ecx + + movl (%ebx), %eax + +5: testl %eax, %eax + jne 7f + + movl %gs:TID, %edx + orl $FUTEX_WAITERS, %edx + LOCK + cmpxchgl %edx, (%ebx) + jnz 7f + +6: addl $12, %esp + cfi_adjust_cfa_offset(-12) + popl %ebp + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebp) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + popl %edi + cfi_adjust_cfa_offset(-4) + cfi_restore(%edi) + ret + +3: movl $EINVAL, %eax + ret + + cfi_adjust_cfa_offset(28) + cfi_offset(%edi, -8) + cfi_offset(%esi, -12) + cfi_offset(%ebx, -16) + cfi_offset(%ebp, -20) + /* Check whether the time expired. */ +7: cmpl $-ETIMEDOUT, %ecx + jne 1b + +8: movl $ETIMEDOUT, %eax + jmp 6b + cfi_endproc + .size __lll_robust_timedlock_wait,.-__lll_robust_timedlock_wait diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S new file mode 100644 index 000000000..040d7f8c3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S @@ -0,0 +1,187 @@ +/* Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelbarrier.h> + + .text + + .globl pthread_barrier_wait + .type pthread_barrier_wait,@function + .align 16 +pthread_barrier_wait: + cfi_startproc + pushl %ebx + cfi_adjust_cfa_offset(4) + cfi_offset(%ebx, -8) + + movl 8(%esp), %ebx + + /* Get the mutex. */ + movl $1, %edx + xorl %eax, %eax + LOCK + cmpxchgl %edx, MUTEX(%ebx) + jnz 1f + + /* One less waiter. If this was the last one needed wake + everybody. */ +2: subl $1, LEFT(%ebx) + je 3f + + /* There are more threads to come. */ + pushl %esi + cfi_adjust_cfa_offset(4) + cfi_offset(%esi, -12) + +#if CURR_EVENT == 0 + movl (%ebx), %edx +#else + movl CURR_EVENT(%ebx), %edx +#endif + + /* Release the mutex. */ + LOCK + subl $1, MUTEX(%ebx) + jne 6f + + /* Wait for the remaining threads. The call will return immediately + if the CURR_EVENT memory has meanwhile been changed. */ +7: +#if FUTEX_WAIT == 0 + movl PRIVATE(%ebx), %ecx +#else + movl $FUTEX_WAIT, %ecx + orl PRIVATE(%ebx), %ecx +#endif + xorl %esi, %esi +8: movl $SYS_futex, %eax + ENTER_KERNEL + + /* Don't return on spurious wakeups. The syscall does not change + any register except %eax so there is no need to reload any of + them. */ +#if CURR_EVENT == 0 + cmpl %edx, (%ebx) +#else + cmpl %edx, CURR_EVENT(%ebx) +#endif + je 8b + + /* Increment LEFT. If this brings the count back to the + initial count unlock the object. */ + movl $1, %edx + movl INIT_COUNT(%ebx), %ecx + LOCK + xaddl %edx, LEFT(%ebx) + subl $1, %ecx + cmpl %ecx, %edx + jne 10f + + /* Release the mutex. We cannot release the lock before + waking the waiting threads since otherwise a new thread might + arrive and gets waken up, too. */ + LOCK + subl $1, MUTEX(%ebx) + jne 9f + + /* Note: %esi is still zero. */ +10: movl %esi, %eax /* != PTHREAD_BARRIER_SERIAL_THREAD */ + + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + ret + + cfi_adjust_cfa_offset(4) + cfi_offset(%ebx, -8) + + /* The necessary number of threads arrived. */ +3: +#if CURR_EVENT == 0 + addl $1, (%ebx) +#else + addl $1, CURR_EVENT(%ebx) +#endif + + /* Wake up all waiters. The count is a signed number in the kernel + so 0x7fffffff is the highest value. */ + movl $0x7fffffff, %edx + movl $FUTEX_WAKE, %ecx + orl PRIVATE(%ebx), %ecx + movl $SYS_futex, %eax + ENTER_KERNEL + + /* Increment LEFT. If this brings the count back to the + initial count unlock the object. */ + movl $1, %edx + movl INIT_COUNT(%ebx), %ecx + LOCK + xaddl %edx, LEFT(%ebx) + subl $1, %ecx + cmpl %ecx, %edx + jne 5f + + /* Release the mutex. We cannot release the lock before + waking the waiting threads since otherwise a new thread might + arrive and gets waken up, too. */ + LOCK + subl $1, MUTEX(%ebx) + jne 4f + +5: orl $-1, %eax /* == PTHREAD_BARRIER_SERIAL_THREAD */ + + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + ret + + cfi_adjust_cfa_offset(4) + cfi_offset(%ebx, -8) +1: movl PRIVATE(%ebx), %ecx + leal MUTEX(%ebx), %edx + xorl $LLL_SHARED, %ecx + call __lll_lock_wait + jmp 2b + +4: movl PRIVATE(%ebx), %ecx + leal MUTEX(%ebx), %eax + xorl $LLL_SHARED, %ecx + call __lll_unlock_wake + jmp 5b + + cfi_adjust_cfa_offset(4) + cfi_offset(%esi, -12) +6: movl PRIVATE(%ebx), %ecx + leal MUTEX(%ebx), %eax + xorl $LLL_SHARED, %ecx + call __lll_unlock_wake + jmp 7b + +9: movl PRIVATE(%ebx), %ecx + leal MUTEX(%ebx), %eax + xorl $LLL_SHARED, %ecx + call __lll_unlock_wake + jmp 10b + cfi_endproc + .size pthread_barrier_wait,.-pthread_barrier_wait diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S new file mode 100644 index 000000000..37dd9daea --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S @@ -0,0 +1,239 @@ +/* Copyright (C) 2002,2003,2004,2006,2007,2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelcond.h> +#include <bits/kernel-features.h> +#include <pthread-pi-defines.h> +#include <pthread-errnos.h> +#include <tls.h> + + .text + + /* int pthread_cond_broadcast (pthread_cond_t *cond) */ + .globl __pthread_cond_broadcast + .type __pthread_cond_broadcast, @function + .hidden __pthread_cond_broadcast + .align 16 +__pthread_cond_broadcast: + cfi_startproc + pushl %ebx + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%ebx, 0) + pushl %esi + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%esi, 0) + pushl %edi + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%edi, 0) + pushl %ebp + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%ebp, 0) + cfi_remember_state + + movl 20(%esp), %ebx + + /* Get internal lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, cond_lock(%ebx) +#endif + jnz 1f + +2: addl $cond_futex, %ebx + movl total_seq+4-cond_futex(%ebx), %eax + movl total_seq-cond_futex(%ebx), %ebp + cmpl wakeup_seq+4-cond_futex(%ebx), %eax + ja 3f + jb 4f + cmpl wakeup_seq-cond_futex(%ebx), %ebp + jna 4f + + /* Cause all currently waiting threads to recognize they are + woken up. */ +3: movl %ebp, wakeup_seq-cond_futex(%ebx) + movl %eax, wakeup_seq-cond_futex+4(%ebx) + movl %ebp, woken_seq-cond_futex(%ebx) + movl %eax, woken_seq-cond_futex+4(%ebx) + addl %ebp, %ebp + addl $1, broadcast_seq-cond_futex(%ebx) + movl %ebp, (%ebx) + + /* Get the address of the mutex used. */ + movl dep_mutex-cond_futex(%ebx), %edi + + /* Unlock. */ + LOCK + subl $1, cond_lock-cond_futex(%ebx) + jne 7f + + /* Don't use requeue for pshared condvars. */ +8: cmpl $-1, %edi + je 9f + + /* Do not use requeue for pshared condvars. */ + testl $PS_BIT, MUTEX_KIND(%edi) + jne 9f + + /* Requeue to a non-robust PI mutex if the PI bit is set and + the robust bit is not set. */ + movl MUTEX_KIND(%edi), %eax + andl $(ROBUST_BIT|PI_BIT), %eax + cmpl $PI_BIT, %eax + je 81f + + /* Wake up all threads. */ +#ifdef __ASSUME_PRIVATE_FUTEX + movl $(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), %ecx +#else + movl %gs:PRIVATE_FUTEX, %ecx + orl $FUTEX_CMP_REQUEUE, %ecx +#endif + movl $SYS_futex, %eax + movl $0x7fffffff, %esi + movl $1, %edx + /* Get the address of the futex involved. */ +# if MUTEX_FUTEX != 0 + addl $MUTEX_FUTEX, %edi +# endif +/* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for sysenter. + ENTER_KERNEL */ + int $0x80 + + /* For any kind of error, which mainly is EAGAIN, we try again + with WAKE. The general test also covers running on old + kernels. */ + cmpl $0xfffff001, %eax + jae 9f + +6: xorl %eax, %eax + popl %ebp + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebp) + popl %edi + cfi_adjust_cfa_offset(-4) + cfi_restore(%edi) + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + ret + + cfi_restore_state + +81: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx + movl $SYS_futex, %eax + movl $0x7fffffff, %esi + movl $1, %edx + /* Get the address of the futex involved. */ +# if MUTEX_FUTEX != 0 + addl $MUTEX_FUTEX, %edi +# endif + int $0x80 + + /* For any kind of error, which mainly is EAGAIN, we try again + with WAKE. The general test also covers running on old + kernels. */ + cmpl $0xfffff001, %eax + jb 6b + jmp 9f + + /* Initial locking failed. */ +1: +#if cond_lock == 0 + movl %ebx, %edx +#else + leal cond_lock(%ebx), %edx +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_lock_wait + jmp 2b + + .align 16 + /* Unlock. */ +4: LOCK + subl $1, cond_lock-cond_futex(%ebx) + je 6b + + /* Unlock in loop requires wakeup. */ +5: leal cond_lock-cond_futex(%ebx), %eax +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex-cond_futex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_unlock_wake + jmp 6b + + /* Unlock in loop requires wakeup. */ +7: leal cond_lock-cond_futex(%ebx), %eax +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex-cond_futex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_unlock_wake + jmp 8b + +9: /* The futex requeue functionality is not available. */ + movl $0x7fffffff, %edx +#if FUTEX_PRIVATE_FLAG > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex-cond_futex(%ebx) + sete %cl + subl $1, %ecx +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %ecx +#else + andl %gs:PRIVATE_FUTEX, %ecx +#endif + addl $FUTEX_WAKE, %ecx + movl $SYS_futex, %eax + ENTER_KERNEL + jmp 6b + cfi_endproc + .size __pthread_cond_broadcast, .-__pthread_cond_broadcast +weak_alias(__pthread_cond_broadcast, pthread_cond_broadcast) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S new file mode 100644 index 000000000..64d309dd3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S @@ -0,0 +1,216 @@ +/* Copyright (C) 2002,2003,2004,2005,2007,2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelcond.h> +#include <bits/kernel-features.h> +#include <pthread-pi-defines.h> +#include <pthread-errnos.h> +#include <tls.h> + + + .text + + /* int pthread_cond_signal (pthread_cond_t *cond) */ + .globl __pthread_cond_signal + .type __pthread_cond_signal, @function + .hidden __pthread_cond_signal + .align 16 +__pthread_cond_signal: + + cfi_startproc + pushl %ebx + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%ebx, 0) + pushl %edi + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%edi, 0) + cfi_remember_state + + movl 12(%esp), %edi + + /* Get internal lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %edx, (%edi) +#else + cmpxchgl %edx, cond_lock(%edi) +#endif + jnz 1f + +2: leal cond_futex(%edi), %ebx + movl total_seq+4(%edi), %eax + movl total_seq(%edi), %ecx + cmpl wakeup_seq+4(%edi), %eax +#if cond_lock != 0 + /* Must use leal to preserve the flags. */ + leal cond_lock(%edi), %edi +#endif + ja 3f + jb 4f + cmpl wakeup_seq-cond_futex(%ebx), %ecx + jbe 4f + + /* Bump the wakeup number. */ +3: addl $1, wakeup_seq-cond_futex(%ebx) + adcl $0, wakeup_seq-cond_futex+4(%ebx) + addl $1, (%ebx) + + /* Wake up one thread. */ + pushl %esi + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%esi, 0) + pushl %ebp + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%ebp, 0) + +#if FUTEX_PRIVATE_FLAG > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex-cond_futex(%ebx) + sete %cl + je 8f + + movl dep_mutex-cond_futex(%ebx), %edx + /* Requeue to a non-robust PI mutex if the PI bit is set and + the robust bit is not set. */ + movl MUTEX_KIND(%edx), %eax + andl $(ROBUST_BIT|PI_BIT), %eax + cmpl $PI_BIT, %eax + je 9f + +8: subl $1, %ecx +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %ecx +#else + andl %gs:PRIVATE_FUTEX, %ecx +#endif + addl $FUTEX_WAKE_OP, %ecx + movl $SYS_futex, %eax + movl $1, %edx + movl $1, %esi + movl $FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, %ebp + /* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for + sysenter. + ENTER_KERNEL */ + int $0x80 + popl %ebp + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebp) + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + + /* For any kind of error, we try again with WAKE. + The general test also covers running on old kernels. */ + cmpl $-4095, %eax + jae 7f + +6: xorl %eax, %eax + popl %edi + cfi_adjust_cfa_offset(-4) + cfi_restore(%edi) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + ret + + cfi_restore_state + +9: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx + movl $SYS_futex, %eax + movl $1, %edx + xorl %esi, %esi + movl dep_mutex-cond_futex(%ebx), %edi + movl (%ebx), %ebp + /* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for + sysenter. + ENTER_KERNEL */ + int $0x80 + popl %ebp + popl %esi + + leal -cond_futex(%ebx), %edi + + /* For any kind of error, we try again with WAKE. + The general test also covers running on old kernels. */ + cmpl $-4095, %eax + jb 4f + +7: +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %ecx +#else + andl %gs:PRIVATE_FUTEX, %ecx +#endif + orl $FUTEX_WAKE, %ecx + + xorl $(FUTEX_WAKE ^ FUTEX_WAKE_OP), %ecx + movl $SYS_futex, %eax + /* %edx should be 1 already from $FUTEX_WAKE_OP syscall. + movl $1, %edx */ + ENTER_KERNEL + + /* Unlock. Note that at this point %edi always points to + cond_lock. */ +4: LOCK + subl $1, (%edi) + je 6b + + /* Unlock in loop requires wakeup. */ +5: movl %edi, %eax +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex-cond_futex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_unlock_wake + jmp 6b + + /* Initial locking failed. */ +1: +#if cond_lock == 0 + movl %edi, %edx +#else + leal cond_lock(%edi), %edx +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%edi) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_lock_wait + jmp 2b + + cfi_endproc + .size __pthread_cond_signal, .-__pthread_cond_signal +weak_alias(__pthread_cond_signal, pthread_cond_signal) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S new file mode 100644 index 000000000..6646c8a72 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S @@ -0,0 +1,694 @@ +/* Copyright (C) 2002-2004,2006-2007,2009,2010 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelcond.h> +#include <pthread-errnos.h> +#include <pthread-pi-defines.h> +#include <bits/kernel-features.h> + + + .text + +/* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime) */ + .globl __pthread_cond_timedwait + .type __pthread_cond_timedwait, @function + .hidden __pthread_cond_timedwait + .align 16 +__pthread_cond_timedwait: +.LSTARTCODE: + cfi_startproc +#ifdef SHARED + cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect, + DW.ref.__gcc_personality_v0) + cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART) +#else + cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0) + cfi_lsda(DW_EH_PE_udata4, .LexceptSTART) +#endif + + pushl %ebp + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%ebp, 0) + pushl %edi + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%edi, 0) + pushl %esi + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%esi, 0) + pushl %ebx + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%ebx, 0) + + movl 20(%esp), %ebx + movl 28(%esp), %ebp + + cmpl $1000000000, 4(%ebp) + movl $EINVAL, %eax + jae 18f + + /* Get internal lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, cond_lock(%ebx) +#endif + jnz 1f + + /* Store the reference to the mutex. If there is already a + different value in there this is a bad user bug. */ +2: cmpl $-1, dep_mutex(%ebx) + movl 24(%esp), %eax + je 17f + movl %eax, dep_mutex(%ebx) + + /* Unlock the mutex. */ +17: xorl %edx, %edx + call __pthread_mutex_unlock_usercnt + + testl %eax, %eax + jne 16f + + addl $1, total_seq(%ebx) + adcl $0, total_seq+4(%ebx) + addl $1, cond_futex(%ebx) + addl $(1 << nwaiters_shift), cond_nwaiters(%ebx) + +#define FRAME_SIZE 32 + subl $FRAME_SIZE, %esp + cfi_adjust_cfa_offset(FRAME_SIZE) + cfi_remember_state + + /* Get and store current wakeup_seq value. */ + movl wakeup_seq(%ebx), %edi + movl wakeup_seq+4(%ebx), %edx + movl broadcast_seq(%ebx), %eax + movl %edi, 12(%esp) + movl %edx, 16(%esp) + movl %eax, 20(%esp) + + /* Reset the pi-requeued flag. */ +8: movl $0, 24(%esp) + /* Get the current time. */ + movl %ebx, %edx +#ifdef __NR_clock_gettime + /* Get the clock number. */ + movl cond_nwaiters(%ebx), %ebx + andl $((1 << nwaiters_shift) - 1), %ebx + /* Only clocks 0 and 1 are allowed so far. Both are handled in the + kernel. */ + leal 4(%esp), %ecx + movl $__NR_clock_gettime, %eax + ENTER_KERNEL +# ifndef __ASSUME_POSIX_TIMERS + cmpl $-ENOSYS, %eax + je 19f +# endif + movl %edx, %ebx + + /* Compute relative timeout. */ + movl (%ebp), %ecx + movl 4(%ebp), %edx + subl 4(%esp), %ecx + subl 8(%esp), %edx +#else + /* Get the current time. */ + leal 4(%esp), %ebx + xorl %ecx, %ecx + movl $__NR_gettimeofday, %eax + ENTER_KERNEL + movl %edx, %ebx + + /* Compute relative timeout. */ + movl 8(%esp), %eax + movl $1000, %edx + mul %edx /* Milli seconds to nano seconds. */ + movl (%ebp), %ecx + movl 4(%ebp), %edx + subl 4(%esp), %ecx + subl %eax, %edx +#endif + jns 12f + addl $1000000000, %edx + subl $1, %ecx +12: testl %ecx, %ecx + movl $-ETIMEDOUT, %esi + js 6f + + /* Store relative timeout. */ +21: movl %ecx, 4(%esp) + movl %edx, 8(%esp) + + movl cond_futex(%ebx), %edi + movl %edi, 28(%esp) + + /* Unlock. */ + LOCK +#if cond_lock == 0 + subl $1, (%ebx) +#else + subl $1, cond_lock(%ebx) +#endif + jne 3f + +.LcleanupSTART: +4: call __pthread_enable_asynccancel + movl %eax, (%esp) + +#if FUTEX_PRIVATE_FLAG > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + sete %cl + je 40f + + movl dep_mutex(%ebx), %edi + /* Requeue to a non-robust PI mutex if the PI bit is set and + the robust bit is not set. */ + movl MUTEX_KIND(%edi), %eax + andl $(ROBUST_BIT|PI_BIT), %eax + cmpl $PI_BIT, %eax + jne 40f + + movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx + /* The following only works like this because we only support + two clocks, represented using a single bit. */ + testl $1, cond_nwaiters(%ebx) + /* XXX Need to implement using sete instead of a jump. */ + jne 42f + orl $FUTEX_CLOCK_REALTIME, %ecx + + /* Requeue-PI uses absolute timeout */ +42: leal (%ebp), %esi + movl 28(%esp), %edx + addl $cond_futex, %ebx + movl $SYS_futex, %eax + ENTER_KERNEL + subl $cond_futex, %ebx + movl %eax, %esi + /* Set the pi-requeued flag only if the kernel has returned 0. The + kernel does not hold the mutex on ETIMEDOUT or any other error. */ + cmpl $0, %eax + sete 24(%esp) + je 41f + + /* Normal and PI futexes dont mix. Use normal futex functions only + if the kernel does not support the PI futex functions. */ + cmpl $-ENOSYS, %eax + jne 41f + xorl %ecx, %ecx + +40: subl $1, %ecx +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %ecx +#else + andl %gs:PRIVATE_FUTEX, %ecx +#endif +#if FUTEX_WAIT != 0 + addl $FUTEX_WAIT, %ecx +#endif + leal 4(%esp), %esi + movl 28(%esp), %edx + addl $cond_futex, %ebx +.Ladd_cond_futex: + movl $SYS_futex, %eax + ENTER_KERNEL + subl $cond_futex, %ebx +.Lsub_cond_futex: + movl %eax, %esi + +41: movl (%esp), %eax + call __pthread_disable_asynccancel +.LcleanupEND: + + /* Lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, cond_lock(%ebx) +#endif + jnz 5f + +6: movl broadcast_seq(%ebx), %eax + cmpl 20(%esp), %eax + jne 23f + + movl woken_seq(%ebx), %eax + movl woken_seq+4(%ebx), %ecx + + movl wakeup_seq(%ebx), %edi + movl wakeup_seq+4(%ebx), %edx + + cmpl 16(%esp), %edx + jne 7f + cmpl 12(%esp), %edi + je 15f + +7: cmpl %ecx, %edx + jne 9f + cmp %eax, %edi + jne 9f + +15: cmpl $-ETIMEDOUT, %esi + jne 8b + + addl $1, wakeup_seq(%ebx) + adcl $0, wakeup_seq+4(%ebx) + addl $1, cond_futex(%ebx) + movl $ETIMEDOUT, %esi + jmp 14f + +23: xorl %esi, %esi + jmp 24f + +9: xorl %esi, %esi +14: addl $1, woken_seq(%ebx) + adcl $0, woken_seq+4(%ebx) + +24: subl $(1 << nwaiters_shift), cond_nwaiters(%ebx) + + /* Wake up a thread which wants to destroy the condvar object. */ + movl total_seq(%ebx), %eax + andl total_seq+4(%ebx), %eax + cmpl $0xffffffff, %eax + jne 25f + movl cond_nwaiters(%ebx), %eax + andl $~((1 << nwaiters_shift) - 1), %eax + jne 25f + + addl $cond_nwaiters, %ebx + movl $SYS_futex, %eax +#if FUTEX_PRIVATE_FLAG > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex-cond_nwaiters(%ebx) + sete %cl + subl $1, %ecx +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %ecx +#else + andl %gs:PRIVATE_FUTEX, %ecx +#endif + addl $FUTEX_WAKE, %ecx + movl $1, %edx + ENTER_KERNEL + subl $cond_nwaiters, %ebx + +25: LOCK +#if cond_lock == 0 + subl $1, (%ebx) +#else + subl $1, cond_lock(%ebx) +#endif + jne 10f + +11: movl 24+FRAME_SIZE(%esp), %eax + /* With requeue_pi, the mutex lock is held in the kernel. */ + movl 24(%esp), %ecx + testl %ecx, %ecx + jnz 27f + + call __pthread_mutex_cond_lock +26: addl $FRAME_SIZE, %esp + cfi_adjust_cfa_offset(-FRAME_SIZE); + + /* We return the result of the mutex_lock operation if it failed. */ + testl %eax, %eax +#ifdef HAVE_CMOV + cmovel %esi, %eax +#else + jne 22f + movl %esi, %eax +22: +#endif + +18: popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + popl %edi + cfi_adjust_cfa_offset(-4) + cfi_restore(%edi) + popl %ebp + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebp) + + ret + + cfi_restore_state + +27: call __pthread_mutex_cond_lock_adjust + xorl %eax, %eax + jmp 26b + + cfi_adjust_cfa_offset(-FRAME_SIZE); + /* Initial locking failed. */ +1: +#if cond_lock == 0 + movl %ebx, %edx +#else + leal cond_lock(%ebx), %edx +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_lock_wait + jmp 2b + + /* The initial unlocking of the mutex failed. */ +16: + LOCK +#if cond_lock == 0 + subl $1, (%ebx) +#else + subl $1, cond_lock(%ebx) +#endif + jne 18b + + movl %eax, %esi +#if cond_lock == 0 + movl %ebx, %eax +#else + leal cond_lock(%ebx), %eax +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_unlock_wake + + movl %esi, %eax + jmp 18b + + cfi_adjust_cfa_offset(FRAME_SIZE) + + /* Unlock in loop requires wakeup. */ +3: +#if cond_lock == 0 + movl %ebx, %eax +#else + leal cond_lock(%ebx), %eax +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_unlock_wake + jmp 4b + + /* Locking in loop failed. */ +5: +#if cond_lock == 0 + movl %ebx, %edx +#else + leal cond_lock(%ebx), %edx +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_lock_wait + jmp 6b + + /* Unlock after loop requires wakeup. */ +10: +#if cond_lock == 0 + movl %ebx, %eax +#else + leal cond_lock(%ebx), %eax +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_unlock_wake + jmp 11b + +#if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS + /* clock_gettime not available. */ +19: leal 4(%esp), %ebx + xorl %ecx, %ecx + movl $__NR_gettimeofday, %eax + ENTER_KERNEL + movl %edx, %ebx + + /* Compute relative timeout. */ + movl 8(%esp), %eax + movl $1000, %edx + mul %edx /* Milli seconds to nano seconds. */ + movl (%ebp), %ecx + movl 4(%ebp), %edx + subl 4(%esp), %ecx + subl %eax, %edx + jns 20f + addl $1000000000, %edx + subl $1, %ecx +20: testl %ecx, %ecx + movl $-ETIMEDOUT, %esi + js 6b + jmp 21b +#endif + .size __pthread_cond_timedwait, .-__pthread_cond_timedwait +weak_alias(__pthread_cond_timedwait, pthread_cond_timedwait) + + + .type __condvar_tw_cleanup2, @function +__condvar_tw_cleanup2: + subl $cond_futex, %ebx + .size __condvar_tw_cleanup2, .-__condvar_tw_cleanup2 + .type __condvar_tw_cleanup, @function +__condvar_tw_cleanup: + movl %eax, %esi + + /* Get internal lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, cond_lock(%ebx) +#endif + jz 1f + +#if cond_lock == 0 + movl %ebx, %edx +#else + leal cond_lock(%ebx), %edx +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_lock_wait + +1: movl broadcast_seq(%ebx), %eax + cmpl 20(%esp), %eax + jne 3f + + /* We increment the wakeup_seq counter only if it is lower than + total_seq. If this is not the case the thread was woken and + then canceled. In this case we ignore the signal. */ + movl total_seq(%ebx), %eax + movl total_seq+4(%ebx), %edi + cmpl wakeup_seq+4(%ebx), %edi + jb 6f + ja 7f + cmpl wakeup_seq(%ebx), %eax + jbe 7f + +6: addl $1, wakeup_seq(%ebx) + adcl $0, wakeup_seq+4(%ebx) + addl $1, cond_futex(%ebx) + +7: addl $1, woken_seq(%ebx) + adcl $0, woken_seq+4(%ebx) + +3: subl $(1 << nwaiters_shift), cond_nwaiters(%ebx) + + /* Wake up a thread which wants to destroy the condvar object. */ + xorl %edi, %edi + movl total_seq(%ebx), %eax + andl total_seq+4(%ebx), %eax + cmpl $0xffffffff, %eax + jne 4f + movl cond_nwaiters(%ebx), %eax + andl $~((1 << nwaiters_shift) - 1), %eax + jne 4f + + addl $cond_nwaiters, %ebx + movl $SYS_futex, %eax +#if FUTEX_PRIVATE_FLAG > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex-cond_nwaiters(%ebx) + sete %cl + subl $1, %ecx +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %ecx +#else + andl %gs:PRIVATE_FUTEX, %ecx +#endif + addl $FUTEX_WAKE, %ecx + movl $1, %edx + ENTER_KERNEL + subl $cond_nwaiters, %ebx + movl $1, %edi + +4: LOCK +#if cond_lock == 0 + subl $1, (%ebx) +#else + subl $1, cond_lock(%ebx) +#endif + je 2f + +#if cond_lock == 0 + movl %ebx, %eax +#else + leal cond_lock(%ebx), %eax +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_unlock_wake + + /* Wake up all waiters to make sure no signal gets lost. */ +2: testl %edi, %edi + jnz 5f + addl $cond_futex, %ebx +#if FUTEX_PRIVATE_FLAG > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex-cond_futex(%ebx) + sete %cl + subl $1, %ecx +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %ecx +#else + andl %gs:PRIVATE_FUTEX, %ecx +#endif + addl $FUTEX_WAKE, %ecx + movl $SYS_futex, %eax + movl $0x7fffffff, %edx + ENTER_KERNEL + +5: movl 24+FRAME_SIZE(%esp), %eax + call __pthread_mutex_cond_lock + + movl %esi, (%esp) +.LcallUR: + call _Unwind_Resume + hlt +.LENDCODE: + cfi_endproc + .size __condvar_tw_cleanup, .-__condvar_tw_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte DW_EH_PE_omit # @LPStart format (omit) + .byte DW_EH_PE_omit # @TType format (omit) + .byte DW_EH_PE_sdata4 # call-site format + # DW_EH_PE_sdata4 + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .long .LcleanupSTART-.LSTARTCODE + .long .Ladd_cond_futex-.LcleanupSTART + .long __condvar_tw_cleanup-.LSTARTCODE + .uleb128 0 + .long .Ladd_cond_futex-.LSTARTCODE + .long .Lsub_cond_futex-.Ladd_cond_futex + .long __condvar_tw_cleanup2-.LSTARTCODE + .uleb128 0 + .long .Lsub_cond_futex-.LSTARTCODE + .long .LcleanupEND-.Lsub_cond_futex + .long __condvar_tw_cleanup-.LSTARTCODE + .uleb128 0 + .long .LcallUR-.LSTARTCODE + .long .LENDCODE-.LcallUR + .long 0 + .uleb128 0 +.Lcstend: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 4 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: + .long __gcc_personality_v0 +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S new file mode 100644 index 000000000..137d576af --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S @@ -0,0 +1,591 @@ +/* Copyright (C) 2002-2004,2006-2007,2009,2010 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelcond.h> +#include <tcb-offsets.h> +#include <pthread-errnos.h> +#include <pthread-pi-defines.h> +#include <bits/kernel-features.h> + + + .text + +/* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */ + .globl __pthread_cond_wait + .type __pthread_cond_wait, @function + .hidden __pthread_cond_wait + .align 16 +__pthread_cond_wait: +.LSTARTCODE: + cfi_startproc +#ifdef SHARED + cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect, + DW.ref.__gcc_personality_v0) + cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART) +#else + cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0) + cfi_lsda(DW_EH_PE_udata4, .LexceptSTART) +#endif + + pushl %ebp + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%ebp, 0) + pushl %edi + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%edi, 0) + pushl %esi + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%esi, 0) + pushl %ebx + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%ebx, 0) + + xorl %esi, %esi + movl 20(%esp), %ebx + + /* Get internal lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, cond_lock(%ebx) +#endif + jnz 1f + + /* Store the reference to the mutex. If there is already a + different value in there this is a bad user bug. */ +2: cmpl $-1, dep_mutex(%ebx) + movl 24(%esp), %eax + je 15f + movl %eax, dep_mutex(%ebx) + + /* Unlock the mutex. */ +15: xorl %edx, %edx + call __pthread_mutex_unlock_usercnt + + testl %eax, %eax + jne 12f + + addl $1, total_seq(%ebx) + adcl $0, total_seq+4(%ebx) + addl $1, cond_futex(%ebx) + addl $(1 << nwaiters_shift), cond_nwaiters(%ebx) + +#define FRAME_SIZE 20 + subl $FRAME_SIZE, %esp + cfi_adjust_cfa_offset(FRAME_SIZE) + cfi_remember_state + + /* Get and store current wakeup_seq value. */ + movl wakeup_seq(%ebx), %edi + movl wakeup_seq+4(%ebx), %edx + movl broadcast_seq(%ebx), %eax + movl %edi, 4(%esp) + movl %edx, 8(%esp) + movl %eax, 12(%esp) + + /* Reset the pi-requeued flag. */ +8: movl $0, 16(%esp) + movl cond_futex(%ebx), %ebp + + /* Unlock. */ + LOCK +#if cond_lock == 0 + subl $1, (%ebx) +#else + subl $1, cond_lock(%ebx) +#endif + jne 3f + +.LcleanupSTART: +4: call __pthread_enable_asynccancel + movl %eax, (%esp) + + xorl %ecx, %ecx + cmpl $-1, dep_mutex(%ebx) + sete %cl + je 18f + + movl dep_mutex(%ebx), %edi + /* Requeue to a non-robust PI mutex if the PI bit is set and + the robust bit is not set. */ + movl MUTEX_KIND(%edi), %eax + andl $(ROBUST_BIT|PI_BIT), %eax + cmpl $PI_BIT, %eax + jne 18f + + movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx + movl %ebp, %edx + xorl %esi, %esi + addl $cond_futex, %ebx + movl $SYS_futex, %eax + ENTER_KERNEL + subl $cond_futex, %ebx + /* Set the pi-requeued flag only if the kernel has returned 0. The + kernel does not hold the mutex on error. */ + cmpl $0, %eax + sete 16(%esp) + je 19f + + /* Normal and PI futexes dont mix. Use normal futex functions only + if the kernel does not support the PI futex functions. */ + cmpl $-ENOSYS, %eax + jne 19f + xorl %ecx, %ecx + +18: subl $1, %ecx +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %ecx +#else + andl %gs:PRIVATE_FUTEX, %ecx +#endif +#if FUTEX_WAIT != 0 + addl $FUTEX_WAIT, %ecx +#endif + movl %ebp, %edx + addl $cond_futex, %ebx +.Ladd_cond_futex: + movl $SYS_futex, %eax + ENTER_KERNEL + subl $cond_futex, %ebx +.Lsub_cond_futex: + +19: movl (%esp), %eax + call __pthread_disable_asynccancel +.LcleanupEND: + + /* Lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, cond_lock(%ebx) +#endif + jnz 5f + +6: movl broadcast_seq(%ebx), %eax + cmpl 12(%esp), %eax + jne 16f + + movl woken_seq(%ebx), %eax + movl woken_seq+4(%ebx), %ecx + + movl wakeup_seq(%ebx), %edi + movl wakeup_seq+4(%ebx), %edx + + cmpl 8(%esp), %edx + jne 7f + cmpl 4(%esp), %edi + je 8b + +7: cmpl %ecx, %edx + jne 9f + cmp %eax, %edi + je 8b + +9: addl $1, woken_seq(%ebx) + adcl $0, woken_seq+4(%ebx) + + /* Unlock */ +16: subl $(1 << nwaiters_shift), cond_nwaiters(%ebx) + + /* Wake up a thread which wants to destroy the condvar object. */ + movl total_seq(%ebx), %eax + andl total_seq+4(%ebx), %eax + cmpl $0xffffffff, %eax + jne 17f + movl cond_nwaiters(%ebx), %eax + andl $~((1 << nwaiters_shift) - 1), %eax + jne 17f + + addl $cond_nwaiters, %ebx + movl $SYS_futex, %eax +#if FUTEX_PRIVATE_FLAG > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex-cond_nwaiters(%ebx) + sete %cl + subl $1, %ecx +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %ecx +#else + andl %gs:PRIVATE_FUTEX, %ecx +#endif + addl $FUTEX_WAKE, %ecx + movl $1, %edx + ENTER_KERNEL + subl $cond_nwaiters, %ebx + +17: LOCK +#if cond_lock == 0 + subl $1, (%ebx) +#else + subl $1, cond_lock(%ebx) +#endif + jne 10f + + /* With requeue_pi, the mutex lock is held in the kernel. */ +11: movl 24+FRAME_SIZE(%esp), %eax + movl 16(%esp), %ecx + testl %ecx, %ecx + jnz 21f + + call __pthread_mutex_cond_lock +20: addl $FRAME_SIZE, %esp + cfi_adjust_cfa_offset(-FRAME_SIZE); + +14: popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + popl %edi + cfi_adjust_cfa_offset(-4) + cfi_restore(%edi) + popl %ebp + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebp) + + /* We return the result of the mutex_lock operation. */ + ret + + cfi_restore_state + +21: call __pthread_mutex_cond_lock_adjust + xorl %eax, %eax + jmp 20b + + cfi_adjust_cfa_offset(-FRAME_SIZE); + /* Initial locking failed. */ +1: +#if cond_lock == 0 + movl %ebx, %edx +#else + leal cond_lock(%ebx), %edx +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_lock_wait + jmp 2b + + /* The initial unlocking of the mutex failed. */ +12: + LOCK +#if cond_lock == 0 + subl $1, (%ebx) +#else + subl $1, cond_lock(%ebx) +#endif + jne 14b + + movl %eax, %esi +#if cond_lock == 0 + movl %ebx, %eax +#else + leal cond_lock(%ebx), %eax +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_unlock_wake + + movl %esi, %eax + jmp 14b + + cfi_adjust_cfa_offset(FRAME_SIZE) + + /* Unlock in loop requires wakeup. */ +3: +#if cond_lock == 0 + movl %ebx, %eax +#else + leal cond_lock(%ebx), %eax +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_unlock_wake + jmp 4b + + /* Locking in loop failed. */ +5: +#if cond_lock == 0 + movl %ebx, %edx +#else + leal cond_lock(%ebx), %edx +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_lock_wait + jmp 6b + + /* Unlock after loop requires wakeup. */ +10: +#if cond_lock == 0 + movl %ebx, %eax +#else + leal cond_lock(%ebx), %eax +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_unlock_wake + jmp 11b + .size __pthread_cond_wait, .-__pthread_cond_wait +weak_alias(__pthread_cond_wait, pthread_cond_wait) + + + .type __condvar_w_cleanup2, @function +__condvar_w_cleanup2: + subl $cond_futex, %ebx + .size __condvar_w_cleanup2, .-__condvar_w_cleanup2 +.LSbl4: + .type __condvar_w_cleanup, @function +__condvar_w_cleanup: + movl %eax, %esi + + /* Get internal lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, cond_lock(%ebx) +#endif + jz 1f + +#if cond_lock == 0 + movl %ebx, %edx +#else + leal cond_lock(%ebx), %edx +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_lock_wait + +1: movl broadcast_seq(%ebx), %eax + cmpl 12(%esp), %eax + jne 3f + + /* We increment the wakeup_seq counter only if it is lower than + total_seq. If this is not the case the thread was woken and + then canceled. In this case we ignore the signal. */ + movl total_seq(%ebx), %eax + movl total_seq+4(%ebx), %edi + cmpl wakeup_seq+4(%ebx), %edi + jb 6f + ja 7f + cmpl wakeup_seq(%ebx), %eax + jbe 7f + +6: addl $1, wakeup_seq(%ebx) + adcl $0, wakeup_seq+4(%ebx) + addl $1, cond_futex(%ebx) + +7: addl $1, woken_seq(%ebx) + adcl $0, woken_seq+4(%ebx) + +3: subl $(1 << nwaiters_shift), cond_nwaiters(%ebx) + + /* Wake up a thread which wants to destroy the condvar object. */ + xorl %edi, %edi + movl total_seq(%ebx), %eax + andl total_seq+4(%ebx), %eax + cmpl $0xffffffff, %eax + jne 4f + movl cond_nwaiters(%ebx), %eax + andl $~((1 << nwaiters_shift) - 1), %eax + jne 4f + + addl $cond_nwaiters, %ebx + movl $SYS_futex, %eax +#if FUTEX_PRIVATE_FLAG > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex-cond_nwaiters(%ebx) + sete %cl + subl $1, %ecx +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %ecx +#else + andl %gs:PRIVATE_FUTEX, %ecx +#endif + addl $FUTEX_WAKE, %ecx + movl $1, %edx + ENTER_KERNEL + subl $cond_nwaiters, %ebx + movl $1, %edi + +4: LOCK +#if cond_lock == 0 + subl $1, (%ebx) +#else + subl $1, cond_lock(%ebx) +#endif + je 2f + +#if cond_lock == 0 + movl %ebx, %eax +#else + leal cond_lock(%ebx), %eax +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_unlock_wake + + /* Wake up all waiters to make sure no signal gets lost. */ +2: testl %edi, %edi + jnz 5f + addl $cond_futex, %ebx +#if FUTEX_PRIVATE_FLAG > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex-cond_futex(%ebx) + sete %cl + subl $1, %ecx +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %ecx +#else + andl %gs:PRIVATE_FUTEX, %ecx +#endif + addl $FUTEX_WAKE, %ecx + movl $SYS_futex, %eax + movl $0x7fffffff, %edx + ENTER_KERNEL + +5: movl 24+FRAME_SIZE(%esp), %eax + call __pthread_mutex_cond_lock + + movl %esi, (%esp) +.LcallUR: + call _Unwind_Resume + hlt +.LENDCODE: + cfi_endproc + .size __condvar_w_cleanup, .-__condvar_w_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte DW_EH_PE_omit # @LPStart format (omit) + .byte DW_EH_PE_omit # @TType format (omit) + .byte DW_EH_PE_sdata4 # call-site format + # DW_EH_PE_sdata4 + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .long .LcleanupSTART-.LSTARTCODE + .long .Ladd_cond_futex-.LcleanupSTART + .long __condvar_w_cleanup-.LSTARTCODE + .uleb128 0 + .long .Ladd_cond_futex-.LSTARTCODE + .long .Lsub_cond_futex-.Ladd_cond_futex + .long __condvar_w_cleanup2-.LSTARTCODE + .uleb128 0 + .long .Lsub_cond_futex-.LSTARTCODE + .long .LcleanupEND-.Lsub_cond_futex + .long __condvar_w_cleanup-.LSTARTCODE + .uleb128 0 + .long .LcallUR-.LSTARTCODE + .long .LENDCODE-.LcallUR + .long 0 + .uleb128 0 +.Lcstend: + +#ifdef __PIC__ + .section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits + .globl __i686.get_pc_thunk.cx + .hidden __i686.get_pc_thunk.cx + .type __i686.get_pc_thunk.cx,@function +__i686.get_pc_thunk.cx: + movl (%esp), %ecx; + ret + .size __i686.get_pc_thunk.cx,.-__i686.get_pc_thunk.cx +#endif + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 4 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: + .long __gcc_personality_v0 +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S new file mode 100644 index 000000000..570771394 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S @@ -0,0 +1,195 @@ +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <bits/kernel-features.h> +#include <tls.h> + + + .text + + .globl __pthread_rwlock_rdlock + .type __pthread_rwlock_rdlock,@function + .hidden __pthread_rwlock_rdlock + .align 16 +__pthread_rwlock_rdlock: + cfi_startproc + pushl %esi + cfi_adjust_cfa_offset(4) + pushl %ebx + cfi_adjust_cfa_offset(4) + cfi_offset(%esi, -8) + cfi_offset(%ebx, -12) + + xorl %esi, %esi + movl 12(%esp), %ebx + + /* Get the lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, MUTEX(%ebx) +#endif + jnz 1f + +2: movl WRITER(%ebx), %eax + testl %eax, %eax + jne 14f + cmpl $0, WRITERS_QUEUED(%ebx) + je 5f + cmpb $0, FLAGS(%ebx) + je 5f + +3: addl $1, READERS_QUEUED(%ebx) + je 4f + + movl READERS_WAKEUP(%ebx), %edx + + LOCK +#if MUTEX == 0 + subl $1, (%ebx) +#else + subl $1, MUTEX(%ebx) +#endif + jne 10f + +11: +#ifdef __ASSUME_PRIVATE_FUTEX + movzbl PSHARED(%ebx), %ecx + xorl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %ecx +#else + movzbl PSHARED(%ebx), %ecx +# if FUTEX_WAIT != 0 + orl $FUTEX_WAIT, %ecx +# endif + xorl %gs:PRIVATE_FUTEX, %ecx +#endif + addl $READERS_WAKEUP, %ebx + movl $SYS_futex, %eax + ENTER_KERNEL + + subl $READERS_WAKEUP, %ebx + + /* Reget the lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, MUTEX(%ebx) +#endif + jnz 12f + +13: subl $1, READERS_QUEUED(%ebx) + jmp 2b + +5: xorl %edx, %edx + addl $1, NR_READERS(%ebx) + je 8f +9: LOCK +#if MUTEX == 0 + subl $1, (%ebx) +#else + subl $1, MUTEX(%ebx) +#endif + jne 6f +7: + + movl %edx, %eax + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + ret + + cfi_adjust_cfa_offset(8) + cfi_offset(%esi, -8) + cfi_offset(%ebx, -12) +1: +#if MUTEX == 0 + movl %ebx, %edx +#else + leal MUTEX(%ebx), %edx +#endif + movzbl PSHARED(%ebx), %ecx + call __lll_lock_wait + jmp 2b + +14: cmpl %gs:TID, %eax + jne 3b + /* Deadlock detected. */ + movl $EDEADLK, %edx + jmp 9b + +6: +#if MUTEX == 0 + movl %ebx, %eax +#else + leal MUTEX(%ebx), %eax +#endif + movzbl PSHARED(%ebx), %ecx + call __lll_unlock_wake + jmp 7b + + /* Overflow. */ +8: subl $1, NR_READERS(%ebx) + movl $EAGAIN, %edx + jmp 9b + + /* Overflow. */ +4: subl $1, READERS_QUEUED(%ebx) + movl $EAGAIN, %edx + jmp 9b + +10: +#if MUTEX == 0 + movl %ebx, %eax +#else + leal MUTEX(%ebx), %eax +#endif + movzbl PSHARED(%ebx), %ecx + call __lll_unlock_wake + jmp 11b + +12: +#if MUTEX == 0 + movl %ebx, %edx +#else + leal MUTEX(%ebx), %edx +#endif + movzbl PSHARED(%ebx), %ecx + call __lll_lock_wait + jmp 13b + cfi_endproc + .size __pthread_rwlock_rdlock,.-__pthread_rwlock_rdlock + + .globl pthread_rwlock_rdlock +pthread_rwlock_rdlock = __pthread_rwlock_rdlock + + .globl __pthread_rwlock_rdlock_internal +__pthread_rwlock_rdlock_internal = __pthread_rwlock_rdlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S new file mode 100644 index 000000000..be4530e13 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S @@ -0,0 +1,245 @@ +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <bits/kernel-features.h> +#include <tls.h> + + + .text + + .globl pthread_rwlock_timedrdlock + .type pthread_rwlock_timedrdlock,@function + .align 16 +pthread_rwlock_timedrdlock: + cfi_startproc + pushl %esi + cfi_adjust_cfa_offset(4) + pushl %edi + cfi_adjust_cfa_offset(4) + pushl %ebx + cfi_adjust_cfa_offset(4) + pushl %ebp + cfi_adjust_cfa_offset(4) + cfi_offset(%esi, -8) + cfi_offset(%edi, -12) + cfi_offset(%ebx, -16) + cfi_offset(%ebp, -20) + subl $8, %esp + cfi_adjust_cfa_offset(8) + + movl 28(%esp), %ebp + movl 32(%esp), %edi + + /* Get the lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %edx, (%ebp) +#else + cmpxchgl %edx, MUTEX(%ebp) +#endif + jnz 1f + +2: movl WRITER(%ebp), %eax + testl %eax, %eax + jne 14f + cmpl $0, WRITERS_QUEUED(%ebp) + je 5f + cmpb $0, FLAGS(%ebp) + je 5f + + /* Check the value of the timeout parameter. */ +3: cmpl $1000000000, 4(%edi) + jae 19f + + addl $1, READERS_QUEUED(%ebp) + je 4f + + movl READERS_WAKEUP(%ebp), %esi + + LOCK +#if MUTEX == 0 + subl $1, (%ebp) +#else + subl $1, MUTEX(%ebp) +#endif + jne 10f + + /* Get current time. */ +11: movl %esp, %ebx + xorl %ecx, %ecx + movl $__NR_gettimeofday, %eax + ENTER_KERNEL + + /* Compute relative timeout. */ + movl 4(%esp), %eax + movl $1000, %edx + mul %edx /* Milli seconds to nano seconds. */ + movl (%edi), %ecx + movl 4(%edi), %edx + subl (%esp), %ecx + subl %eax, %edx + jns 15f + addl $1000000000, %edx + subl $1, %ecx +15: testl %ecx, %ecx + js 16f /* Time is already up. */ + + /* Futex call. */ + movl %ecx, (%esp) /* Store relative timeout. */ + movl %edx, 4(%esp) + + movl %esi, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movzbl PSHARED(%ebp), %ecx + xorl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %ecx +#else + movzbl PSHARED(%ebp), %ecx +# if FUTEX_WAIT != 0 + orl $FUTEX_WAIT, %ecx +# endif + xorl %gs:PRIVATE_FUTEX, %ecx +#endif + movl %esp, %esi + leal READERS_WAKEUP(%ebp), %ebx + movl $SYS_futex, %eax + ENTER_KERNEL + movl %eax, %esi +17: + + /* Reget the lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %edx, (%ebp) +#else + cmpxchgl %edx, MUTEX(%ebp) +#endif + jnz 12f + +13: subl $1, READERS_QUEUED(%ebp) + cmpl $-ETIMEDOUT, %esi + jne 2b + +18: movl $ETIMEDOUT, %edx + jmp 9f + + +5: xorl %edx, %edx + addl $1, NR_READERS(%ebp) + je 8f +9: LOCK +#if MUTEX == 0 + subl $1, (%ebp) +#else + subl $1, MUTEX(%ebp) +#endif + jne 6f + +7: movl %edx, %eax + + addl $8, %esp + cfi_adjust_cfa_offset(-8) + popl %ebp + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebp) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %edi + cfi_adjust_cfa_offset(-4) + cfi_restore(%edi) + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + ret + + cfi_adjust_cfa_offset(24) + cfi_offset(%esi, -8) + cfi_offset(%edi, -12) + cfi_offset(%ebx, -16) + cfi_offset(%ebp, -20) +1: +#if MUTEX == 0 + movl %ebp, %edx +#else + leal MUTEX(%ebp), %edx +#endif + movzbl PSHARED(%ebp), %ecx + call __lll_lock_wait + jmp 2b + +14: cmpl %gs:TID, %eax + jne 3b + movl $EDEADLK, %edx + jmp 9b + +6: +#if MUTEX == 0 + movl %ebp, %eax +#else + leal MUTEX(%ebp), %eax +#endif + movzbl PSHARED(%ebp), %ecx + call __lll_unlock_wake + jmp 7b + + /* Overflow. */ +8: subl $1, NR_READERS(%ebp) + movl $EAGAIN, %edx + jmp 9b + + /* Overflow. */ +4: subl $1, READERS_QUEUED(%ebp) + movl $EAGAIN, %edx + jmp 9b + +10: +#if MUTEX == 0 + movl %ebp, %eax +#else + leal MUTEX(%ebp), %eax +#endif + movzbl PSHARED(%ebp), %ecx + call __lll_unlock_wake + jmp 11b + +12: +#if MUTEX == 0 + movl %ebp, %edx +#else + leal MUTEX(%ebp), %edx +#endif + movzbl PSHARED(%ebp), %ecx + call __lll_lock_wait + jmp 13b + +16: movl $-ETIMEDOUT, %esi + jmp 17b + +19: movl $EINVAL, %edx + jmp 9b + cfi_endproc + .size pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S new file mode 100644 index 000000000..61431ab71 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S @@ -0,0 +1,238 @@ +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <bits/kernel-features.h> +#include <tls.h> + + + .text + + .globl pthread_rwlock_timedwrlock + .type pthread_rwlock_timedwrlock,@function + .align 16 +pthread_rwlock_timedwrlock: + cfi_startproc + pushl %esi + cfi_adjust_cfa_offset(4) + pushl %edi + cfi_adjust_cfa_offset(4) + pushl %ebx + cfi_adjust_cfa_offset(4) + pushl %ebp + cfi_adjust_cfa_offset(4) + cfi_offset(%esi, -8) + cfi_offset(%edi, -12) + cfi_offset(%ebx, -16) + cfi_offset(%ebp, -20) + subl $8, %esp + cfi_adjust_cfa_offset(8) + + movl 28(%esp), %ebp + movl 32(%esp), %edi + + /* Get the lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %edx, (%ebp) +#else + cmpxchgl %edx, MUTEX(%ebp) +#endif + jnz 1f + +2: movl WRITER(%ebp), %eax + testl %eax, %eax + jne 14f + cmpl $0, NR_READERS(%ebp) + je 5f + + /* Check the value of the timeout parameter. */ +3: cmpl $1000000000, 4(%edi) + jae 19f + + addl $1, WRITERS_QUEUED(%ebp) + je 4f + + movl WRITERS_WAKEUP(%ebp), %esi + + LOCK +#if MUTEX == 0 + subl $1, (%ebp) +#else + subl $1, MUTEX(%ebp) +#endif + jne 10f + + /* Get current time. */ +11: movl %esp, %ebx + xorl %ecx, %ecx + movl $__NR_gettimeofday, %eax + ENTER_KERNEL + + /* Compute relative timeout. */ + movl 4(%esp), %eax + movl $1000, %edx + mul %edx /* Milli seconds to nano seconds. */ + movl (%edi), %ecx + movl 4(%edi), %edx + subl (%esp), %ecx + subl %eax, %edx + jns 15f + addl $1000000000, %edx + subl $1, %ecx +15: testl %ecx, %ecx + js 16f /* Time is already up. */ + + /* Futex call. */ + movl %ecx, (%esp) /* Store relative timeout. */ + movl %edx, 4(%esp) + + movl %esi, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movzbl PSHARED(%ebp), %ecx + xorl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %ecx +#else + movzbl PSHARED(%ebp), %ecx +# if FUTEX_WAIT != 0 + orl $FUTEX_WAIT, %ecx +# endif + xorl %gs:PRIVATE_FUTEX, %ecx +#endif + movl %esp, %esi + leal WRITERS_WAKEUP(%ebp), %ebx + movl $SYS_futex, %eax + ENTER_KERNEL + movl %eax, %esi +17: + + /* Reget the lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %edx, (%ebp) +#else + cmpxchgl %edx, MUTEX(%ebp) +#endif + jnz 12f + +13: subl $1, WRITERS_QUEUED(%ebp) + cmpl $-ETIMEDOUT, %esi + jne 2b + +18: movl $ETIMEDOUT, %edx + jmp 9f + + +5: xorl %edx, %edx + movl %gs:TID, %eax + movl %eax, WRITER(%ebp) +9: LOCK +#if MUTEX == 0 + subl $1, (%ebp) +#else + subl $1, MUTEX(%ebp) +#endif + jne 6f + +7: movl %edx, %eax + + addl $8, %esp + cfi_adjust_cfa_offset(-8) + popl %ebp + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebp) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %edi + cfi_adjust_cfa_offset(-4) + cfi_restore(%edi) + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + ret + + cfi_adjust_cfa_offset(24) + cfi_offset(%esi, -8) + cfi_offset(%edi, -12) + cfi_offset(%ebx, -16) + cfi_offset(%ebp, -20) +1: +#if MUTEX == 0 + movl %ebp, %edx +#else + leal MUTEX(%ebp), %edx +#endif + movzbl PSHARED(%ebp), %ecx + call __lll_lock_wait + jmp 2b + +14: cmpl %gs:TID, %eax + jne 3b +20: movl $EDEADLK, %edx + jmp 9b + +6: +#if MUTEX == 0 + movl %ebp, %eax +#else + leal MUTEX(%ebp), %eax +#endif + movzbl PSHARED(%ebp), %ecx + call __lll_unlock_wake + jmp 7b + + /* Overflow. */ +4: subl $1, WRITERS_QUEUED(%ebp) + movl $EAGAIN, %edx + jmp 9b + +10: +#if MUTEX == 0 + movl %ebp, %eax +#else + leal MUTEX(%ebp), %eax +#endif + movzbl PSHARED(%ebp), %ecx + call __lll_unlock_wake + jmp 11b + +12: +#if MUTEX == 0 + movl %ebp, %edx +#else + leal MUTEX(%ebp), %edx +#endif + movzbl PSHARED(%ebp), %ecx + call __lll_lock_wait + jmp 13b + +16: movl $-ETIMEDOUT, %esi + jmp 17b + +19: movl $EINVAL, %edx + jmp 9b + cfi_endproc + .size pthread_rwlock_timedwrlock,.-pthread_rwlock_timedwrlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S new file mode 100644 index 000000000..72563018d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S @@ -0,0 +1,157 @@ +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelrwlock.h> +#include <bits/kernel-features.h> +#include <tls.h> + + + .text + + .globl __pthread_rwlock_unlock + .type __pthread_rwlock_unlock,@function + .hidden __pthread_rwlock_unlock + .align 16 +__pthread_rwlock_unlock: + cfi_startproc + pushl %ebx + cfi_adjust_cfa_offset(4) + pushl %edi + cfi_adjust_cfa_offset(4) + cfi_offset(%ebx, -8) + cfi_offset(%edi, -12) + + movl 12(%esp), %edi + + /* Get the lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %edx, (%edi) +#else + cmpxchgl %edx, MUTEX(%edi) +#endif + jnz 1f + +2: cmpl $0, WRITER(%edi) + jne 5f + subl $1, NR_READERS(%edi) + jnz 6f + +5: movl $0, WRITER(%edi) + + movl $1, %edx + leal WRITERS_WAKEUP(%edi), %ebx + cmpl $0, WRITERS_QUEUED(%edi) + jne 0f + + /* If also no readers waiting nothing to do. */ + cmpl $0, READERS_QUEUED(%edi) + je 6f + + movl $0x7fffffff, %edx + leal READERS_WAKEUP(%edi), %ebx + +0: addl $1, (%ebx) + LOCK +#if MUTEX == 0 + subl $1, (%edi) +#else + subl $1, MUTEX(%edi) +#endif + jne 7f + +8: +#ifdef __ASSUME_PRIVATE_FUTEX + movzbl PSHARED(%edi), %ecx + xorl $FUTEX_PRIVATE_FLAG|FUTEX_WAKE, %ecx +#else + movzbl PSHARED(%edi), %ecx + orl $FUTEX_WAKE, %ecx + xorl %gs:PRIVATE_FUTEX, %ecx +#endif + movl $SYS_futex, %eax + ENTER_KERNEL + + xorl %eax, %eax + popl %edi + cfi_adjust_cfa_offset(-4) + cfi_restore(%edi) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + ret + + cfi_adjust_cfa_offset(8) + cfi_offset(%ebx, -8) + cfi_offset(%edi, -12) + .align 16 +6: LOCK +#if MUTEX == 0 + subl $1, (%edi) +#else + subl $1, MUTEX(%edi) +#endif + jne 3f + +4: xorl %eax, %eax + popl %edi + popl %ebx + ret + +1: +#if MUTEX == 0 + movl %edi, %edx +#else + leal MUTEX(%edi), %edx +#endif + movzbl PSHARED(%edi), %ecx + call __lll_lock_wait + jmp 2b + +3: +#if MUTEX == 0 + movl %edi, %eax +#else + leal MUTEX(%edi), %eax +#endif + movzbl PSHARED(%edi), %ecx + call __lll_unlock_wake + jmp 4b + +7: +#if MUTEX == 0 + movl %edi, %eax +#else + leal MUTEX(%edi), %eax +#endif + movzbl PSHARED(%edi), %ecx + call __lll_unlock_wake + jmp 8b + cfi_endproc + .size __pthread_rwlock_unlock,.-__pthread_rwlock_unlock + + .globl pthread_rwlock_unlock +pthread_rwlock_unlock = __pthread_rwlock_unlock + + .globl __pthread_rwlock_unlock_internal +__pthread_rwlock_unlock_internal = __pthread_rwlock_unlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S new file mode 100644 index 000000000..8ff7dfa56 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S @@ -0,0 +1,186 @@ +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <bits/kernel-features.h> +#include <tls.h> + + + .text + + .globl __pthread_rwlock_wrlock + .type __pthread_rwlock_wrlock,@function + .hidden __pthread_rwlock_wrlock + .align 16 +__pthread_rwlock_wrlock: + cfi_startproc + pushl %esi + cfi_adjust_cfa_offset(4) + pushl %ebx + cfi_adjust_cfa_offset(4) + cfi_offset(%esi, -8) + cfi_offset(%ebx, -12) + + xorl %esi, %esi + movl 12(%esp), %ebx + + /* Get the lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, MUTEX(%ebx) +#endif + jnz 1f + +2: movl WRITER(%ebx), %eax + testl %eax, %eax + jne 14f + cmpl $0, NR_READERS(%ebx) + je 5f + +3: addl $1, WRITERS_QUEUED(%ebx) + je 4f + + movl WRITERS_WAKEUP(%ebx), %edx + + LOCK +#if MUTEX == 0 + subl $1, (%ebx) +#else + subl $1, MUTEX(%ebx) +#endif + jne 10f + +11: +#ifdef __ASSUME_PRIVATE_FUTEX + movzbl PSHARED(%ebx), %ecx + xorl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %ecx +#else + movzbl PSHARED(%ebx), %ecx +# if FUTEX_WAIT != 0 + orl $FUTEX_WAIT, %ecx +# endif + xorl %gs:PRIVATE_FUTEX, %ecx +#endif + addl $WRITERS_WAKEUP, %ebx + movl $SYS_futex, %eax + ENTER_KERNEL + + subl $WRITERS_WAKEUP, %ebx + + /* Reget the lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, MUTEX(%ebx) +#endif + jnz 12f + +13: subl $1, WRITERS_QUEUED(%ebx) + jmp 2b + +5: xorl %edx, %edx + movl %gs:TID, %eax + movl %eax, WRITER(%ebx) +9: LOCK +#if MUTEX == 0 + subl $1, (%ebx) +#else + subl $1, MUTEX(%ebx) +#endif + jne 6f +7: + + movl %edx, %eax + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + ret + + cfi_adjust_cfa_offset(8) + cfi_offset(%esi, -8) + cfi_offset(%ebx, -12) +1: +#if MUTEX == 0 + movl %ebx, %edx +#else + leal MUTEX(%ebx), %edx +#endif + movzbl PSHARED(%ebx), %ecx + call __lll_lock_wait + jmp 2b + +14: cmpl %gs:TID , %eax + jne 3b + movl $EDEADLK, %edx + jmp 9b + +6: +#if MUTEX == 0 + movl %ebx, %eax +#else + leal MUTEX(%ebx), %eax +#endif + movzbl PSHARED(%ebx), %ecx + call __lll_unlock_wake + jmp 7b + +4: subl $1, WRITERS_QUEUED(%ebx) + movl $EAGAIN, %edx + jmp 9b + +10: +#if MUTEX == 0 + movl %ebx, %eax +#else + leal MUTEX(%ebx), %eax +#endif + movzbl PSHARED(%ebx), %ecx + call __lll_unlock_wake + jmp 11b + +12: +#if MUTEX == 0 + movl %ebx, %edx +#else + leal MUTEX(%ebx), %edx +#endif + movzbl PSHARED(%ebx), %ecx + call __lll_lock_wait + jmp 13b + cfi_endproc + .size __pthread_rwlock_wrlock,.-__pthread_rwlock_wrlock + + .globl pthread_rwlock_wrlock +pthread_rwlock_wrlock = __pthread_rwlock_wrlock + + .globl __pthread_rwlock_wrlock_internal +__pthread_rwlock_wrlock_internal = __pthread_rwlock_wrlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S new file mode 100644 index 000000000..b077a20ca --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S @@ -0,0 +1,142 @@ +/* Copyright (C) 2002, 2003, 2005, 2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include <structsem.h> +#include <lowlevellock.h> + + + .text + + .globl __new_sem_post + .type __new_sem_post,@function + .align 16 +__new_sem_post: + cfi_startproc + pushl %ebx + cfi_adjust_cfa_offset(4) + cfi_offset(%ebx, -8) + + movl 8(%esp), %ebx + +#if VALUE == 0 + movl (%ebx), %eax +#else + movl VALUE(%ebx), %eax +#endif +0: cmpl $SEM_VALUE_MAX, %eax + je 3f + leal 1(%eax), %edx + LOCK +#if VALUE == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, VALUE(%ebx) +#endif + jnz 0b + + cmpl $0, NWAITERS(%ebx) + je 2f + + movl $FUTEX_WAKE, %ecx + orl PRIVATE(%ebx), %ecx + movl $1, %edx + movl $SYS_futex, %eax + ENTER_KERNEL + + testl %eax, %eax + js 1f + +2: xorl %eax, %eax + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + ret + + cfi_adjust_cfa_offset(4) + cfi_offset(%ebx, -8) +1: +#ifdef __PIC__ + call __x86.get_pc_thunk.bx +#else + movl $4f, %ebx +4: +#endif + addl $_GLOBAL_OFFSET_TABLE_, %ebx +#if USE___THREAD +# ifdef NO_TLS_DIRECT_SEG_REFS + movl errno@gotntpoff(%ebx), %edx + addl %gs:0, %edx + movl $EINVAL, (%edx) +# else + movl errno@gotntpoff(%ebx), %edx + movl $EINVAL, %gs:(%edx) +# endif +#else + call __errno_location@plt + movl $EINVAL, (%eax) +#endif + + orl $-1, %eax + popl %ebx + ret + +3: +#ifdef __PIC__ + call __x86.get_pc_thunk.bx +#else + movl $5f, %ebx +5: +#endif + addl $_GLOBAL_OFFSET_TABLE_, %ebx +#if USE___THREAD +# ifdef NO_TLS_DIRECT_SEG_REFS + movl errno@gotntpoff(%ebx), %edx + addl %gs:0, %edx + movl $EOVERFLOW, (%edx) +# else + movl errno@gotntpoff(%ebx), %edx + movl $EOVERFLOW, %gs:(%edx) +# endif +#else + call __errno_location@plt + movl $EOVERFLOW, (%eax) +#endif + + orl $-1, %eax + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + ret + cfi_endproc + .size __new_sem_post,.-__new_sem_post +weak_alias(__new_sem_post, sem_post) + + +#ifdef __PIC__ + .section .gnu.linkonce.t.__x86.get_pc_thunk.bx,"ax",@progbits + .globl __x86.get_pc_thunk.bx + .hidden __x86.get_pc_thunk.bx + .type __x86.get_pc_thunk.bx,@function +__x86.get_pc_thunk.bx: + movl (%esp), %ebx; + ret + .size __x86.get_pc_thunk.bx,.-__x86.get_pc_thunk.bx +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S new file mode 100644 index 000000000..a1e3225cb --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S @@ -0,0 +1,329 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include <structsem.h> +#include <lowlevellock.h> + + +#if VALUE != 0 +# error "code needs to be rewritten for VALUE != 0" +#endif + + + .text + + .globl sem_timedwait + .type sem_timedwait,@function + .align 16 +sem_timedwait: +.LSTARTCODE: + movl 4(%esp), %ecx + + movl (%ecx), %eax +2: testl %eax, %eax + je 1f + + leal -1(%eax), %edx + LOCK + cmpxchgl %edx, (%ecx) + jne 2b + + xorl %eax, %eax + ret + + /* Check whether the timeout value is valid. */ +1: pushl %esi +.Lpush_esi: + pushl %edi +.Lpush_edi: + pushl %ebx +.Lpush_ebx: + subl $12, %esp +.Lsub_esp: + + movl 32(%esp), %edi + + /* Check for invalid nanosecond field. */ + cmpl $1000000000, 4(%edi) + movl $EINVAL, %esi + jae 6f + + LOCK + incl NWAITERS(%ecx) + +7: xorl %ecx, %ecx + movl %esp, %ebx + movl %ecx, %edx + movl $__NR_gettimeofday, %eax + ENTER_KERNEL + + /* Compute relative timeout. */ + movl 4(%esp), %eax + movl $1000, %edx + mul %edx /* Milli seconds to nano seconds. */ + movl (%edi), %ecx + movl 4(%edi), %edx + subl (%esp), %ecx + subl %eax, %edx + jns 5f + addl $1000000000, %edx + subl $1, %ecx +5: testl %ecx, %ecx + movl $ETIMEDOUT, %esi + js 6f /* Time is already up. */ + + movl %ecx, (%esp) /* Store relative timeout. */ + movl %edx, 4(%esp) + +.LcleanupSTART: + call __pthread_enable_asynccancel + movl %eax, 8(%esp) + + movl 28(%esp), %ebx /* Load semaphore address. */ +#if FUTEX_WAIT == 0 + movl PRIVATE(%ebx), %ecx +#else + movl $FUTEX_WAIT, %ecx + orl PRIVATE(%ebx), %ecx +#endif + movl %esp, %esi + xorl %edx, %edx + movl $SYS_futex, %eax + ENTER_KERNEL + movl %eax, %esi + + movl 8(%esp), %eax + call __pthread_disable_asynccancel +.LcleanupEND: + + testl %esi, %esi + je 9f + cmpl $-EWOULDBLOCK, %esi + jne 3f + +9: movl (%ebx), %eax +8: testl %eax, %eax + je 7b + + leal -1(%eax), %ecx + LOCK + cmpxchgl %ecx, (%ebx) + jne 8b + + xorl %eax, %eax + + LOCK + decl NWAITERS(%ebx) + +10: addl $12, %esp +.Ladd_esp: + popl %ebx +.Lpop_ebx: + popl %edi +.Lpop_edi: + popl %esi +.Lpop_esi: + ret + +.Lafter_ret: +3: negl %esi +6: +#ifdef __PIC__ + call __x86.get_pc_thunk.bx +#else + movl $4f, %ebx +4: +#endif + addl $_GLOBAL_OFFSET_TABLE_, %ebx +#if USE___THREAD +# ifdef NO_TLS_DIRECT_SEG_REFS + movl errno@gotntpoff(%ebx), %edx + addl %gs:0, %edx + movl %esi, (%edx) +# else + movl errno@gotntpoff(%ebx), %edx + movl %esi, %gs:(%edx) +# endif +#else + call __errno_location@plt + movl %esi, (%eax) +#endif + + movl 28(%esp), %ebx /* Load semaphore address. */ + orl $-1, %eax + jmp 10b + .size sem_timedwait,.-sem_timedwait + + + .type sem_wait_cleanup,@function +sem_wait_cleanup: + LOCK + decl NWAITERS(%ebx) + movl %eax, (%esp) +.LcallUR: + call _Unwind_Resume@PLT + hlt +.LENDCODE: + .size sem_wait_cleanup,.-sem_wait_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte 0xff # @LPStart format (omit) + .byte 0xff # @TType format (omit) + .byte 0x01 # call-site format + # DW_EH_PE_uleb128 + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 sem_wait_cleanup-.LSTARTCODE + .uleb128 0 + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +.Lcstend: + + + .section .eh_frame,"a",@progbits +.LSTARTFRAME: + .long .LENDCIE-.LSTARTCIE # Length of the CIE. +.LSTARTCIE: + .long 0 # CIE ID. + .byte 1 # Version number. +#ifdef SHARED + .string "zPLR" # NUL-terminated augmentation + # string. +#else + .string "zPL" # NUL-terminated augmentation + # string. +#endif + .uleb128 1 # Code alignment factor. + .sleb128 -4 # Data alignment factor. + .byte 8 # Return address register + # column. +#ifdef SHARED + .uleb128 7 # Augmentation value length. + .byte 0x9b # Personality: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4 + # + DW_EH_PE_indirect + .long DW.ref.__gcc_personality_v0-. + .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4. + .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4. +#else + .uleb128 6 # Augmentation value length. + .byte 0x0 # Personality: absolute + .long __gcc_personality_v0 + .byte 0x0 # LSDA Encoding: absolute +#endif + .byte 0x0c # DW_CFA_def_cfa + .uleb128 4 + .uleb128 4 + .byte 0x88 # DW_CFA_offset, column 0x10 + .uleb128 1 + .align 4 +.LENDCIE: + + .long .LENDFDE-.LSTARTFDE # Length of the FDE. +.LSTARTFDE: + .long .LSTARTFDE-.LSTARTFRAME # CIE pointer. +#ifdef SHARED + .long .LSTARTCODE-. # PC-relative start address + # of the code. +#else + .long .LSTARTCODE # Start address of the code. +#endif + .long .LENDCODE-.LSTARTCODE # Length of the code. + .uleb128 4 # Augmentation size +#ifdef SHARED + .long .LexceptSTART-. +#else + .long .LexceptSTART +#endif + + .byte 4 # DW_CFA_advance_loc4 + .long .Lpush_esi-.LSTARTCODE + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 8 + .byte 0x86 # DW_CFA_offset %esi + .uleb128 2 + .byte 4 # DW_CFA_advance_loc4 + .long .Lpush_edi-.Lpush_esi + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 12 + .byte 0x87 # DW_CFA_offset %edi + .uleb128 3 + .byte 4 # DW_CFA_advance_loc4 + .long .Lpush_ebx-.Lpush_edi + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 16 + .byte 0x83 # DW_CFA_offset %ebx + .uleb128 4 + .byte 4 # DW_CFA_advance_loc4 + .long .Lsub_esp-.Lpush_ebx + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 28 + .byte 4 # DW_CFA_advance_loc4 + .long .Ladd_esp-.Lsub_esp + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 16 + .byte 4 # DW_CFA_advance_loc4 + .long .Lpop_ebx-.Ladd_esp + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 12 + .byte 0xc3 # DW_CFA_restore %ebx + .byte 4 # DW_CFA_advance_loc4 + .long .Lpop_edi-.Lpop_ebx + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 8 + .byte 0xc7 # DW_CFA_restore %edi + .byte 4 # DW_CFA_advance_loc4 + .long .Lpop_esi-.Lpop_edi + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 4 + .byte 0xc6 # DW_CFA_restore %esi + .byte 4 # DW_CFA_advance_loc4 + .long .Lafter_ret-.Lpop_esi + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 28 + .byte 0x86 # DW_CFA_offset %esi + .uleb128 2 + .byte 0x87 # DW_CFA_offset %edi + .uleb128 3 + .byte 0x83 # DW_CFA_offset %ebx + .uleb128 4 + .align 4 +.LENDFDE: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 4 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: + .long __gcc_personality_v0 +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S new file mode 100644 index 000000000..dad96858f --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S @@ -0,0 +1,79 @@ +/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include <lowlevellock.h> + + .text + + .globl __new_sem_trywait + .type __new_sem_trywait,@function + .align 16 +__new_sem_trywait: + movl 4(%esp), %ecx + + movl (%ecx), %eax +2: testl %eax, %eax + jz 1f + + leal -1(%eax), %edx + LOCK + cmpxchgl %edx, (%ecx) + jne 2b + xorl %eax, %eax + ret + +1: +#ifdef __PIC__ + call __x86.get_pc_thunk.cx +#else + movl $3f, %ecx +3: +#endif + addl $_GLOBAL_OFFSET_TABLE_, %ecx +#if USE___THREAD +# ifdef NO_TLS_DIRECT_SEG_REFS + movl errno@gotntpoff(%ecx), %edx + addl %gs:0, %edx + movl $EAGAIN, (%edx) +# else + movl errno@gotntpoff(%ecx), %edx + movl $EAGAIN, %gs:(%edx) +# endif +#else + call __errno_location@plt + movl $EAGAIN, (%eax) +#endif + orl $-1, %eax + ret + .size __new_sem_trywait,.-__new_sem_trywait +weak_alias(__new_sem_trywait, sem_trywait) + + +#ifdef __PIC__ + .section .gnu.linkonce.t.__x86.get_pc_thunk.cx,"ax",@progbits + .globl __x86.get_pc_thunk.cx + .hidden __x86.get_pc_thunk.cx + .type __x86.get_pc_thunk.cx,@function +__x86.get_pc_thunk.cx: + movl (%esp), %ecx; + ret + .size __x86.get_pc_thunk.cx,.-__x86.get_pc_thunk.cx +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S new file mode 100644 index 000000000..b1c32ee4d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S @@ -0,0 +1,269 @@ +/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include <structsem.h> +#include <lowlevellock.h> + + +#if VALUE != 0 +# error "code needs to be rewritten for VALUE != 0" +#endif + + .text + + .globl __new_sem_wait + .type __new_sem_wait,@function + .align 16 +__new_sem_wait: +.LSTARTCODE: + pushl %ebx +.Lpush_ebx: + pushl %esi +.Lpush_esi: + subl $4, %esp +.Lsub_esp: + + movl 16(%esp), %ebx + + movl (%ebx), %eax +2: testl %eax, %eax + je 1f + + leal -1(%eax), %edx + LOCK + cmpxchgl %edx, (%ebx) + jne 2b +7: xorl %eax, %eax + +9: movl 4(%esp), %esi + movl 8(%esp), %ebx + addl $12, %esp +.Ladd_esp: + ret + +.Lafter_ret: +1: LOCK + incl NWAITERS(%ebx) + +.LcleanupSTART: +6: call __pthread_enable_asynccancel + movl %eax, (%esp) + +#if FUTEX_WAIT == 0 + movl PRIVATE(%ebx), %ecx +#else + movl $FUTEX_WAIT, %ecx + orl PRIVATE(%ebx), %ecx +#endif + xorl %esi, %esi + xorl %edx, %edx + movl $SYS_futex, %eax + ENTER_KERNEL + movl %eax, %esi + + movl (%esp), %eax + call __pthread_disable_asynccancel +.LcleanupEND: + + testl %esi, %esi + je 3f + cmpl $-EWOULDBLOCK, %esi + jne 4f + +3: + movl (%ebx), %eax +5: testl %eax, %eax + je 6b + + leal -1(%eax), %edx + LOCK + cmpxchgl %edx, (%ebx) + jne 5b + + LOCK + decl NWAITERS(%ebx) + jmp 7b + +4: LOCK + decl NWAITERS(%ebx) + + negl %esi +#ifdef __PIC__ + call __x86.get_pc_thunk.bx +#else + movl $8f, %ebx +8: +#endif + addl $_GLOBAL_OFFSET_TABLE_, %ebx +#if USE___THREAD +# ifdef NO_TLS_DIRECT_SEG_REFS + movl errno@gotntpoff(%ebx), %edx + addl %gs:0, %edx + movl %esi, (%edx) +# else + movl errno@gotntpoff(%ebx), %edx + movl %esi, %gs:(%edx) +# endif +#else + call __errno_location@plt + movl %esi, (%eax) +#endif + orl $-1, %eax + + jmp 9b + .size __new_sem_wait,.-__new_sem_wait +weak_alias(__new_sem_wait, sem_wait) + + + .type sem_wait_cleanup,@function +sem_wait_cleanup: + LOCK + decl NWAITERS(%ebx) + movl %eax, (%esp) +.LcallUR: + call _Unwind_Resume@PLT + hlt +.LENDCODE: + .size sem_wait_cleanup,.-sem_wait_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte 0xff # @LPStart format (omit) + .byte 0xff # @TType format (omit) + .byte 0x01 # call-site format + # DW_EH_PE_uleb128 + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 sem_wait_cleanup-.LSTARTCODE + .uleb128 0 + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +.Lcstend: + + + .section .eh_frame,"a",@progbits +.LSTARTFRAME: + .long .LENDCIE-.LSTARTCIE # Length of the CIE. +.LSTARTCIE: + .long 0 # CIE ID. + .byte 1 # Version number. +#ifdef SHARED + .string "zPLR" # NUL-terminated augmentation + # string. +#else + .string "zPL" # NUL-terminated augmentation + # string. +#endif + .uleb128 1 # Code alignment factor. + .sleb128 -4 # Data alignment factor. + .byte 8 # Return address register + # column. +#ifdef SHARED + .uleb128 7 # Augmentation value length. + .byte 0x9b # Personality: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4 + # + DW_EH_PE_indirect + .long DW.ref.__gcc_personality_v0-. + .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4. + .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4. +#else + .uleb128 6 # Augmentation value length. + .byte 0x0 # Personality: absolute + .long __gcc_personality_v0 + .byte 0x0 # LSDA Encoding: absolute +#endif + .byte 0x0c # DW_CFA_def_cfa + .uleb128 4 + .uleb128 4 + .byte 0x88 # DW_CFA_offset, column 0x10 + .uleb128 1 + .align 4 +.LENDCIE: + + .long .LENDFDE-.LSTARTFDE # Length of the FDE. +.LSTARTFDE: + .long .LSTARTFDE-.LSTARTFRAME # CIE pointer. +#ifdef SHARED + .long .LSTARTCODE-. # PC-relative start address + # of the code. +#else + .long .LSTARTCODE # Start address of the code. +#endif + .long .LENDCODE-.LSTARTCODE # Length of the code. + .uleb128 4 # Augmentation size +#ifdef SHARED + .long .LexceptSTART-. +#else + .long .LexceptSTART +#endif + + .byte 4 # DW_CFA_advance_loc4 + .long .Lpush_ebx-.LSTARTCODE + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 8 + .byte 0x83 # DW_CFA_offset %ebx + .uleb128 2 + .byte 4 # DW_CFA_advance_loc4 + .long .Lpush_esi-.Lpush_ebx + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 12 + .byte 0x86 # DW_CFA_offset %esi + .uleb128 3 + .byte 4 # DW_CFA_advance_loc4 + .long .Lsub_esp-.Lpush_esi + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 16 + .byte 4 # DW_CFA_advance_loc4 + .long .Ladd_esp-.Lsub_esp + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 4 + .byte 0xc3 # DW_CFA_restore %ebx + .byte 0xc6 # DW_CFA_restore %esi + .byte 4 # DW_CFA_advance_loc4 + .long .Lafter_ret-.Ladd_esp + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 16 + .byte 0x83 # DW_CFA_offset %ebx + .uleb128 2 + .byte 0x86 # DW_CFA_offset %esi + .uleb128 3 + .align 4 +.LENDFDE: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 4 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: + .long __gcc_personality_v0 +#endif + diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/libc-lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/libc-lowlevellock.S new file mode 100644 index 000000000..f567c1d6d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/libc-lowlevellock.S @@ -0,0 +1 @@ +#include "../i486/libc-lowlevellock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevellock.S new file mode 100644 index 000000000..e60dea89e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevellock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/lowlevellock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S new file mode 100644 index 000000000..f768e16a7 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/lowlevelrobustlock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_barrier_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_barrier_wait.S new file mode 100644 index 000000000..6d20b9a95 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_barrier_wait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/pthread_barrier_wait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_broadcast.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_broadcast.S new file mode 100644 index 000000000..5e1024eab --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_broadcast.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/pthread_cond_broadcast.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_signal.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_signal.S new file mode 100644 index 000000000..da4e8cbab --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_signal.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/pthread_cond_signal.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S new file mode 100644 index 000000000..c0131555b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/pthread_cond_timedwait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S new file mode 100644 index 000000000..9b57fbaca --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/pthread_cond_wait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_rdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_rdlock.S new file mode 100644 index 000000000..da2bc4704 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_rdlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/pthread_rwlock_rdlock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedrdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedrdlock.S new file mode 100644 index 000000000..0f2ec168b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedrdlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/pthread_rwlock_timedrdlock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedwrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedwrlock.S new file mode 100644 index 000000000..26501590a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedwrlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/pthread_rwlock_timedwrlock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_unlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_unlock.S new file mode 100644 index 000000000..5515e4895 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_unlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/pthread_rwlock_unlock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_wrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_wrlock.S new file mode 100644 index 000000000..04ac275f6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_wrlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/pthread_rwlock_wrlock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_post.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_post.S new file mode 100644 index 000000000..7317e1582 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_post.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/sem_post.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S new file mode 100644 index 000000000..f34539d56 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/sem_timedwait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S new file mode 100644 index 000000000..64145c2e3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/sem_trywait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_wait.S new file mode 100644 index 000000000..b3d462125 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_wait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/sem_wait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/libc-lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/libc-lowlevellock.S new file mode 100644 index 000000000..f567c1d6d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/libc-lowlevellock.S @@ -0,0 +1 @@ +#include "../i486/libc-lowlevellock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevellock.S new file mode 100644 index 000000000..e60dea89e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevellock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/lowlevellock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S new file mode 100644 index 000000000..f768e16a7 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/lowlevelrobustlock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_barrier_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_barrier_wait.S new file mode 100644 index 000000000..6d20b9a95 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_barrier_wait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/pthread_barrier_wait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_broadcast.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_broadcast.S new file mode 100644 index 000000000..5e1024eab --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_broadcast.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/pthread_cond_broadcast.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_signal.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_signal.S new file mode 100644 index 000000000..da4e8cbab --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_signal.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/pthread_cond_signal.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S new file mode 100644 index 000000000..07d481f37 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S @@ -0,0 +1,21 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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. */ + +#define HAVE_CMOV 1 +#include "../i486/pthread_cond_timedwait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S new file mode 100644 index 000000000..9b57fbaca --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/pthread_cond_wait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_rdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_rdlock.S new file mode 100644 index 000000000..da2bc4704 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_rdlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/pthread_rwlock_rdlock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedrdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedrdlock.S new file mode 100644 index 000000000..0f2ec168b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedrdlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/pthread_rwlock_timedrdlock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedwrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedwrlock.S new file mode 100644 index 000000000..26501590a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedwrlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/pthread_rwlock_timedwrlock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_unlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_unlock.S new file mode 100644 index 000000000..0894f0546 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_unlock.S @@ -0,0 +1,21 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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. */ + +#define HAVE_CMOV 1 +#include "../i486/pthread_rwlock_unlock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_wrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_wrlock.S new file mode 100644 index 000000000..04ac275f6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_wrlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/pthread_rwlock_wrlock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_post.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_post.S new file mode 100644 index 000000000..7317e1582 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_post.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/sem_post.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S new file mode 100644 index 000000000..f34539d56 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/sem_timedwait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S new file mode 100644 index 000000000..64145c2e3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/sem_trywait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_wait.S new file mode 100644 index 000000000..b3d462125 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_wait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 "../i486/sem_wait.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h new file mode 100644 index 000000000..55add8b8e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h @@ -0,0 +1,584 @@ +/* Copyright (C) 2002-2004, 2006-2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H 1 + +#ifndef __ASSEMBLER__ +# include <time.h> +# include <sys/param.h> +# include <bits/pthreadtypes.h> +# include <bits/kernel-features.h> +# include <tcb-offsets.h> + +# ifndef LOCK_INSTR +# ifdef UP +# define LOCK_INSTR /* nothing */ +# else +# define LOCK_INSTR "lock;" +# endif +# endif +#else +# ifndef LOCK +# ifdef UP +# define LOCK +# else +# define LOCK lock +# endif +# endif +#endif + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_CMP_REQUEUE 4 +#define FUTEX_WAKE_OP 5 +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 +#define FUTEX_WAIT_BITSET 9 +#define FUTEX_WAKE_BITSET 10 +#define FUTEX_WAIT_REQUEUE_PI 11 +#define FUTEX_CMP_REQUEUE_PI 12 +#define FUTEX_PRIVATE_FLAG 128 +#define FUTEX_CLOCK_REALTIME 256 + +#define FUTEX_BITSET_MATCH_ANY 0xffffffff + +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ({ unsigned int __fl = ((private) ^ FUTEX_PRIVATE_FLAG); \ + __asm__ ("andl %%gs:%P1, %0" : "+r" (__fl) \ + : "i" (offsetof (struct pthread, header.private_futex))); \ + __fl | (fl); })) +# endif +#endif + +#ifndef __ASSEMBLER__ + +/* Initializer for compatibility lock. */ +#define LLL_LOCK_INITIALIZER (0) +#define LLL_LOCK_INITIALIZER_LOCKED (1) +#define LLL_LOCK_INITIALIZER_WAITERS (2) + + +#ifdef __PIC__ +# define LLL_EBX_LOAD "xchgl %2, %%ebx\n" +# define LLL_EBX_REG "D" +#else +# define LLL_EBX_LOAD +# define LLL_EBX_REG "b" +#endif + +#ifdef I386_USE_SYSENTER +# ifdef SHARED +# define LLL_ENTER_KERNEL "call *%%gs:%P6\n\t" +# else +# define LLL_ENTER_KERNEL "call *_dl_sysinfo\n\t" +# endif +#else +# define LLL_ENTER_KERNEL "int $0x80\n\t" +#endif + +/* Delay in spinlock loop. */ +#define BUSY_WAIT_NOP __asm__ ("rep; nop") + + +#define LLL_STUB_UNWIND_INFO_START \ + ".section .eh_frame,\"a\",@progbits\n" \ +"5:\t" ".long 7f-6f # Length of Common Information Entry\n" \ +"6:\t" ".long 0x0 # CIE Identifier Tag\n\t" \ + ".byte 0x1 # CIE Version\n\t" \ + ".ascii \"zR\\0\" # CIE Augmentation\n\t" \ + ".uleb128 0x1 # CIE Code Alignment Factor\n\t" \ + ".sleb128 -4 # CIE Data Alignment Factor\n\t" \ + ".byte 0x8 # CIE RA Column\n\t" \ + ".uleb128 0x1 # Augmentation size\n\t" \ + ".byte 0x1b # FDE Encoding (pcrel sdata4)\n\t" \ + ".byte 0xc # DW_CFA_def_cfa\n\t" \ + ".uleb128 0x4\n\t" \ + ".uleb128 0x0\n\t" \ + ".align 4\n" \ +"7:\t" ".long 17f-8f # FDE Length\n" \ +"8:\t" ".long 8b-5b # FDE CIE offset\n\t" \ + ".long 1b-. # FDE initial location\n\t" \ + ".long 4b-1b # FDE address range\n\t" \ + ".uleb128 0x0 # Augmentation size\n\t" \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x8\n\t" \ + ".uleb128 10f-9f\n" \ +"9:\t" ".byte 0x78 # DW_OP_breg8\n\t" \ + ".sleb128 3b-1b\n" +#define LLL_STUB_UNWIND_INFO_END \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x8\n\t" \ + ".uleb128 12f-11f\n" \ +"11:\t" ".byte 0x78 # DW_OP_breg8\n\t" \ + ".sleb128 3b-2b\n" \ +"12:\t" ".byte 0x40 + (3b-2b-1) # DW_CFA_advance_loc\n\t" \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x8\n\t" \ + ".uleb128 16f-13f\n" \ +"13:\t" ".byte 0x78 # DW_OP_breg8\n\t" \ + ".sleb128 15f-14f\n\t" \ + ".byte 0x0d # DW_OP_const4s\n" \ +"14:\t" ".4byte 3b-.\n\t" \ + ".byte 0x1c # DW_OP_minus\n\t" \ + ".byte 0x0d # DW_OP_const4s\n" \ +"15:\t" ".4byte 18f-.\n\t" \ + ".byte 0x22 # DW_OP_plus\n" \ +"16:\t" ".align 4\n" \ +"17:\t" ".previous\n" + +/* Unwind info for + 1: lea ..., ... + 2: call ... + 3: jmp 18f + 4: + snippet. */ +#define LLL_STUB_UNWIND_INFO_3 \ +LLL_STUB_UNWIND_INFO_START \ +"10:\t" ".byte 0x40 + (2b-1b) # DW_CFA_advance_loc\n\t" \ +LLL_STUB_UNWIND_INFO_END + +/* Unwind info for + 1: lea ..., ... + 0: movl ..., ... + 2: call ... + 3: jmp 18f + 4: + snippet. */ +#define LLL_STUB_UNWIND_INFO_4 \ +LLL_STUB_UNWIND_INFO_START \ +"10:\t" ".byte 0x40 + (0b-1b) # DW_CFA_advance_loc\n\t" \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x8\n\t" \ + ".uleb128 20f-19f\n" \ +"19:\t" ".byte 0x78 # DW_OP_breg8\n\t" \ + ".sleb128 3b-0b\n" \ +"20:\t" ".byte 0x40 + (2b-0b) # DW_CFA_advance_loc\n\t" \ +LLL_STUB_UNWIND_INFO_END + + +#define lll_futex_wait(futex, val, private) \ + lll_futex_timed_wait (futex, val, NULL, private) + + +#define lll_futex_timed_wait(futex, val, timeout, private) \ + ({ \ + int __status; \ + register __typeof (val) _val __asm__ ("edx") = (val); \ + __asm__ __volatile (LLL_EBX_LOAD \ + LLL_ENTER_KERNEL \ + LLL_EBX_LOAD \ + : "=a" (__status) \ + : "0" (SYS_futex), LLL_EBX_REG (futex), "S" (timeout), \ + "c" (__lll_private_flag (FUTEX_WAIT, private)), \ + "d" (_val), "i" (offsetof (tcbhead_t, sysinfo)) \ + : "memory"); \ + __status; \ + }) + + +#define lll_futex_wake(futex, nr, private) \ + do { \ + int __ignore; \ + register __typeof (nr) _nr __asm__ ("edx") = (nr); \ + __asm__ __volatile (LLL_EBX_LOAD \ + LLL_ENTER_KERNEL \ + LLL_EBX_LOAD \ + : "=a" (__ignore) \ + : "0" (SYS_futex), LLL_EBX_REG (futex), \ + "c" (__lll_private_flag (FUTEX_WAKE, private)), \ + "d" (_nr), \ + "i" (0) /* phony, to align next arg's number */, \ + "i" (offsetof (tcbhead_t, sysinfo))); \ + } while (0) + + +/* NB: in the lll_trylock macro we simply return the value in %eax + after the cmpxchg instruction. In case the operation succeded this + value is zero. In case the operation failed, the cmpxchg instruction + has loaded the current value of the memory work which is guaranteed + to be nonzero. */ +#if defined NOT_IN_libc || defined UP +# define __lll_trylock_asm LOCK_INSTR "cmpxchgl %2, %1" +#else +# define __lll_trylock_asm "cmpl $0, %%gs:%P5\n\t" \ + "je 0f\n\t" \ + "lock\n" \ + "0:\tcmpxchgl %2, %1" +#endif + +#define lll_trylock(futex) \ + ({ int ret; \ + __asm__ __volatile (__lll_trylock_asm \ + : "=a" (ret), "=m" (futex) \ + : "r" (LLL_LOCK_INITIALIZER_LOCKED), "m" (futex), \ + "0" (LLL_LOCK_INITIALIZER), \ + "i" (MULTIPLE_THREADS_OFFSET) \ + : "memory"); \ + ret; }) + +#define lll_robust_trylock(futex, id) \ + ({ int ret; \ + __asm__ __volatile (LOCK_INSTR "cmpxchgl %2, %1" \ + : "=a" (ret), "=m" (futex) \ + : "r" (id), "m" (futex), \ + "0" (LLL_LOCK_INITIALIZER) \ + : "memory"); \ + ret; }) + + +#define lll_cond_trylock(futex) \ + ({ int ret; \ + __asm__ __volatile (LOCK_INSTR "cmpxchgl %2, %1" \ + : "=a" (ret), "=m" (futex) \ + : "r" (LLL_LOCK_INITIALIZER_WAITERS), \ + "m" (futex), "0" (LLL_LOCK_INITIALIZER) \ + : "memory"); \ + ret; }) + +#if defined NOT_IN_libc || defined UP +# define __lll_lock_asm_start LOCK_INSTR "cmpxchgl %1, %2\n\t" +#else +# define __lll_lock_asm_start "cmpl $0, %%gs:%P6\n\t" \ + "je 0f\n\t" \ + "lock\n" \ + "0:\tcmpxchgl %1, %2\n\t" +#endif + +#define lll_lock(futex, private) \ + (void) \ + ({ int ignore1, ignore2; \ + if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \ + __asm__ __volatile (__lll_lock_asm_start \ + "jnz _L_lock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_lock_%=,@function\n" \ + "_L_lock_%=:\n" \ + "1:\tleal %2, %%ecx\n" \ + "2:\tcall __lll_lock_wait_private\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_lock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_3 \ + "18:" \ + : "=a" (ignore1), "=c" (ignore2), "=m" (futex) \ + : "0" (0), "1" (1), "m" (futex), \ + "i" (MULTIPLE_THREADS_OFFSET) \ + : "memory"); \ + else \ + { \ + int ignore3; \ + __asm__ __volatile (__lll_lock_asm_start \ + "jnz _L_lock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_lock_%=,@function\n" \ + "_L_lock_%=:\n" \ + "1:\tleal %2, %%edx\n" \ + "0:\tmovl %8, %%ecx\n" \ + "2:\tcall __lll_lock_wait\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_lock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_4 \ + "18:" \ + : "=a" (ignore1), "=c" (ignore2), \ + "=m" (futex), "=&d" (ignore3) \ + : "1" (1), "m" (futex), \ + "i" (MULTIPLE_THREADS_OFFSET), "0" (0), \ + "g" ((int) (private)) \ + : "memory"); \ + } \ + }) + +#define lll_robust_lock(futex, id, private) \ + ({ int __result, ignore1, ignore2; \ + __asm__ __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t" \ + "jnz _L_robust_lock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_robust_lock_%=,@function\n" \ + "_L_robust_lock_%=:\n" \ + "1:\tleal %2, %%edx\n" \ + "0:\tmovl %7, %%ecx\n" \ + "2:\tcall __lll_robust_lock_wait\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_robust_lock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_4 \ + "18:" \ + : "=a" (__result), "=c" (ignore1), "=m" (futex), \ + "=&d" (ignore2) \ + : "0" (0), "1" (id), "m" (futex), "g" ((int) (private))\ + : "memory"); \ + __result; }) + + +/* Special version of lll_lock which causes the unlock function to + always wakeup waiters. */ +#define lll_cond_lock(futex, private) \ + (void) \ + ({ int ignore1, ignore2, ignore3; \ + __asm__ __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t" \ + "jnz _L_cond_lock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_cond_lock_%=,@function\n" \ + "_L_cond_lock_%=:\n" \ + "1:\tleal %2, %%edx\n" \ + "0:\tmovl %7, %%ecx\n" \ + "2:\tcall __lll_lock_wait\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_cond_lock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_4 \ + "18:" \ + : "=a" (ignore1), "=c" (ignore2), "=m" (futex), \ + "=&d" (ignore3) \ + : "0" (0), "1" (2), "m" (futex), "g" ((int) (private))\ + : "memory"); \ + }) + + +#define lll_robust_cond_lock(futex, id, private) \ + ({ int __result, ignore1, ignore2; \ + __asm__ __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t" \ + "jnz _L_robust_cond_lock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_robust_cond_lock_%=,@function\n" \ + "_L_robust_cond_lock_%=:\n" \ + "1:\tleal %2, %%edx\n" \ + "0:\tmovl %7, %%ecx\n" \ + "2:\tcall __lll_robust_lock_wait\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_robust_cond_lock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_4 \ + "18:" \ + : "=a" (__result), "=c" (ignore1), "=m" (futex), \ + "=&d" (ignore2) \ + : "0" (0), "1" (id | FUTEX_WAITERS), "m" (futex), \ + "g" ((int) (private)) \ + : "memory"); \ + __result; }) + + +#define lll_timedlock(futex, timeout, private) \ + ({ int __result, ignore1, ignore2, ignore3; \ + __asm__ __volatile (LOCK_INSTR "cmpxchgl %1, %3\n\t" \ + "jnz _L_timedlock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_timedlock_%=,@function\n" \ + "_L_timedlock_%=:\n" \ + "1:\tleal %3, %%ecx\n" \ + "0:\tmovl %8, %%edx\n" \ + "2:\tcall __lll_timedlock_wait\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_timedlock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_4 \ + "18:" \ + : "=a" (__result), "=c" (ignore1), "=&d" (ignore2), \ + "=m" (futex), "=S" (ignore3) \ + : "0" (0), "1" (1), "m" (futex), "m" (timeout), \ + "4" ((int) (private)) \ + : "memory"); \ + __result; }) + + +#define lll_robust_timedlock(futex, timeout, id, private) \ + ({ int __result, ignore1, ignore2, ignore3; \ + __asm__ __volatile (LOCK_INSTR "cmpxchgl %1, %3\n\t" \ + "jnz _L_robust_timedlock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_robust_timedlock_%=,@function\n" \ + "_L_robust_timedlock_%=:\n" \ + "1:\tleal %3, %%ecx\n" \ + "0:\tmovl %8, %%edx\n" \ + "2:\tcall __lll_robust_timedlock_wait\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_robust_timedlock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_4 \ + "18:" \ + : "=a" (__result), "=c" (ignore1), "=&d" (ignore2), \ + "=m" (futex), "=S" (ignore3) \ + : "0" (0), "1" (id), "m" (futex), "m" (timeout), \ + "4" ((int) (private)) \ + : "memory"); \ + __result; }) + +#if defined NOT_IN_libc || defined UP +# define __lll_unlock_asm LOCK_INSTR "subl $1, %0\n\t" +#else +# define __lll_unlock_asm "cmpl $0, %%gs:%P3\n\t" \ + "je 0f\n\t" \ + "lock\n" \ + "0:\tsubl $1,%0\n\t" +#endif + +#define lll_unlock(futex, private) \ + (void) \ + ({ int ignore; \ + if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \ + __asm__ __volatile (__lll_unlock_asm \ + "jne _L_unlock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_unlock_%=,@function\n" \ + "_L_unlock_%=:\n" \ + "1:\tleal %0, %%eax\n" \ + "2:\tcall __lll_unlock_wake_private\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_unlock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_3 \ + "18:" \ + : "=m" (futex), "=&a" (ignore) \ + : "m" (futex), "i" (MULTIPLE_THREADS_OFFSET) \ + : "memory"); \ + else \ + { \ + int ignore2; \ + __asm__ __volatile (__lll_unlock_asm \ + "jne _L_unlock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_unlock_%=,@function\n" \ + "_L_unlock_%=:\n" \ + "1:\tleal %0, %%eax\n" \ + "0:\tmovl %5, %%ecx\n" \ + "2:\tcall __lll_unlock_wake\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_unlock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_4 \ + "18:" \ + : "=m" (futex), "=&a" (ignore), "=&c" (ignore2) \ + : "i" (MULTIPLE_THREADS_OFFSET), "m" (futex), \ + "g" ((int) (private)) \ + : "memory"); \ + } \ + }) + +#define lll_robust_unlock(futex, private) \ + (void) \ + ({ int ignore, ignore2; \ + __asm__ __volatile (LOCK_INSTR "andl %3, %0\n\t" \ + "jne _L_robust_unlock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_robust_unlock_%=,@function\n" \ + "_L_robust_unlock_%=:\n\t" \ + "1:\tleal %0, %%eax\n" \ + "0:\tmovl %5, %%ecx\n" \ + "2:\tcall __lll_unlock_wake\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_robust_unlock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_4 \ + "18:" \ + : "=m" (futex), "=&a" (ignore), "=&c" (ignore2) \ + : "i" (FUTEX_WAITERS), "m" (futex), \ + "g" ((int) (private)) \ + : "memory"); \ + }) + + +#define lll_robust_dead(futex, private) \ + (void) \ + ({ int __ignore; \ + register int _nr __asm__ ("edx") = 1; \ + __asm__ __volatile (LOCK_INSTR "orl %5, (%2)\n\t" \ + LLL_EBX_LOAD \ + LLL_ENTER_KERNEL \ + LLL_EBX_LOAD \ + : "=a" (__ignore) \ + : "0" (SYS_futex), LLL_EBX_REG (&(futex)), \ + "c" (__lll_private_flag (FUTEX_WAKE, private)), \ + "d" (_nr), "i" (FUTEX_OWNER_DIED), \ + "i" (offsetof (tcbhead_t, sysinfo))); \ + }) + +#define lll_islocked(futex) \ + (futex != LLL_LOCK_INITIALIZER) + +/* The kernel notifies a process with uses CLONE_CLEARTID via futex + wakeup when the clone terminates. The memory location contains the + thread ID while the clone is running and is reset to zero + afterwards. + + The macro parameter must not have any side effect. */ +#define lll_wait_tid(tid) \ + do { \ + int __ignore; \ + register __typeof (tid) _tid __asm__ ("edx") = (tid); \ + if (_tid != 0) \ + __asm__ __volatile (LLL_EBX_LOAD \ + "1:\tmovl %1, %%eax\n\t" \ + LLL_ENTER_KERNEL \ + "cmpl $0, (%%ebx)\n\t" \ + "jne 1b\n\t" \ + LLL_EBX_LOAD \ + : "=&a" (__ignore) \ + : "i" (SYS_futex), LLL_EBX_REG (&tid), "S" (0), \ + "c" (FUTEX_WAIT), "d" (_tid), \ + "i" (offsetof (tcbhead_t, sysinfo)) \ + : "memory"); \ + } while (0) + +extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime) + __attribute__ ((regparm (2))) attribute_hidden; +#define lll_timedwait_tid(tid, abstime) \ + ({ \ + int __result = 0; \ + if (tid != 0) \ + { \ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) \ + __result = EINVAL; \ + else \ + __result = __lll_timedwait_tid (&tid, abstime); \ + } \ + __result; }) + +#endif /* !__ASSEMBLER__ */ + +#endif /* lowlevellock.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pt-__syscall_error.c b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pt-__syscall_error.c new file mode 100644 index 000000000..620640ad6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pt-__syscall_error.c @@ -0,0 +1 @@ +#include <../../../../../../../libc/sysdeps/linux/i386/__syscall_error.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S new file mode 100644 index 000000000..aff926a8f --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S @@ -0,0 +1,68 @@ +/* Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Schwab <schwab@gnu.org>. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#define _ERRNO_H 1 +#include <bits/errno.h> +#include <bits/kernel-features.h> +#include <tcb-offsets.h> + +/* Save the PID value. */ +#define SAVE_PID \ + movl %gs:PID, %edx; \ + movl %edx, %eax; \ + negl %eax; \ + movl %eax, %gs:PID + +/* Restore the old PID value in the parent. */ +#define RESTORE_PID \ + testl %eax, %eax; \ + je 1f; \ + movl %edx, %gs:PID; \ +1: + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + /* Pop the return PC value into ECX. */ + popl %ecx + + SAVE_PID + + /* Stuff the syscall number in EAX and enter into the kernel. */ + movl $SYS_ify (vfork), %eax + int $0x80 + + RESTORE_PID + + /* Jump to the return PC. Don't jump directly since this + disturbs the branch target cache. Instead push the return + address back on the stack. */ + pushl %ecx + + cmpl $-4095, %eax + jae SYSCALL_ERROR_LABEL /* Branch forward if it failed. */ +L(pseudo_end): + ret +PSEUDO_END (__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S new file mode 100644 index 000000000..a995709bf --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S @@ -0,0 +1,197 @@ +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <unwindbuf.h> +#include <sysdep.h> +#include <bits/kernel-features.h> +#include <lowlevellock.h> +#include <tls.h> + + + .comm __fork_generation, 4, 4 + + .text + + + .globl __pthread_once + .type __pthread_once,@function + .hidden __pthread_once + .align 16 + cfi_startproc +__pthread_once: + movl 4(%esp), %ecx + testl $2, (%ecx) + jz 1f + xorl %eax, %eax + ret + +1: pushl %ebx + cfi_adjust_cfa_offset (4) + cfi_rel_offset (3, 0) + pushl %esi + cfi_adjust_cfa_offset (4) + cfi_rel_offset (6, 0) + movl %ecx, %ebx + xorl %esi, %esi + + /* Not yet initialized or initialization in progress. + Get the fork generation counter now. */ +6: movl (%ebx), %eax +#ifdef __PIC__ + call __x86.get_pc_thunk.cx + addl $_GLOBAL_OFFSET_TABLE_, %ecx +#endif + +5: movl %eax, %edx + + testl $2, %eax + jnz 4f + + andl $3, %edx +#ifdef __PIC__ + orl __fork_generation@GOTOFF(%ecx), %edx +#else + orl __fork_generation, %edx +#endif + orl $1, %edx + + LOCK + cmpxchgl %edx, (%ebx) + jnz 5b + + /* Check whether another thread already runs the initializer. */ + testl $1, %eax + jz 3f /* No -> do it. */ + + /* Check whether the initializer execution was interrupted + by a fork. */ + xorl %edx, %eax + testl $0xfffffffc, %eax + jnz 3f /* Different for generation -> run initializer. */ + + /* Somebody else got here first. Wait. */ +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAIT|FUTEX_PRIVATE_FLAG, %ecx +#else +# if FUTEX_WAIT == 0 + movl %gs:PRIVATE_FUTEX, %ecx +# else + movl $FUTEX_WAIT, %ecx + orl %gs:PRIVATE_FUTEX, %ecx +# endif +#endif + movl $SYS_futex, %eax + ENTER_KERNEL + jmp 6b + +3: /* Call the initializer function after setting up the + cancellation handler. Note that it is not possible here + to use the unwind-based cleanup handling. This would require + that the user-provided function and all the code it calls + is compiled with exceptions. Unfortunately this cannot be + guaranteed. */ + subl $UNWINDBUFSIZE+8, %esp + cfi_adjust_cfa_offset (UNWINDBUFSIZE+8) + movl %ecx, %ebx /* PIC register value. */ + + leal 8+UWJMPBUF(%esp), %eax + movl $0, 4(%esp) + movl %eax, (%esp) + call __sigsetjmp@PLT + testl %eax, %eax + jne 7f + + leal 8(%esp), %eax + call HIDDEN_JUMPTARGET(__pthread_register_cancel) + + /* Call the user-provided initialization function. */ + call *24+UNWINDBUFSIZE(%esp) + + /* Pop the cleanup handler. */ + leal 8(%esp), %eax + call HIDDEN_JUMPTARGET(__pthread_unregister_cancel) + addl $UNWINDBUFSIZE+8, %esp + cfi_adjust_cfa_offset (-UNWINDBUFSIZE-8) + + /* Sucessful run of the initializer. Signal that we are done. */ + movl 12(%esp), %ebx + LOCK + addl $1, (%ebx) + + /* Wake up all other threads. */ + movl $0x7fffffff, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %ecx +#else + movl $FUTEX_WAKE, %ecx + orl %gs:PRIVATE_FUTEX, %ecx +#endif + movl $SYS_futex, %eax + ENTER_KERNEL + +4: popl %esi + cfi_adjust_cfa_offset (-4) + cfi_restore (6) + popl %ebx + cfi_adjust_cfa_offset (-4) + cfi_restore (3) + xorl %eax, %eax + ret + +7: /* __sigsetjmp returned for the second time. */ + movl 20+UNWINDBUFSIZE(%esp), %ebx + cfi_adjust_cfa_offset (UNWINDBUFSIZE+16) + cfi_offset (3, -8) + cfi_offset (6, -12) + movl $0, (%ebx) + + movl $0x7fffffff, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %ecx +#else + movl $FUTEX_WAKE, %ecx + orl %gs:PRIVATE_FUTEX, %ecx +#endif + movl $SYS_futex, %eax + ENTER_KERNEL + + leal 8(%esp), %eax + call HIDDEN_JUMPTARGET (__pthread_unwind_next) + /* NOTREACHED */ + hlt + cfi_endproc + .size __pthread_once,.-__pthread_once + + .globl __pthread_once_internal +__pthread_once_internal = __pthread_once + + .globl pthread_once +pthread_once = __pthread_once + + +#ifdef __PIC__ + .section .gnu.linkonce.t.__x86.get_pc_thunk.cx,"ax",@progbits + .globl __x86.get_pc_thunk.cx + .hidden __x86.get_pc_thunk.cx + .type __x86.get_pc_thunk.cx,@function +__x86.get_pc_thunk.cx: + movl (%esp), %ecx; + ret + .size __x86.get_pc_thunk.cx,.-__x86.get_pc_thunk.cx +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_spin_init.c b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_spin_init.c new file mode 100644 index 000000000..d36e5373d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_spin_init.c @@ -0,0 +1 @@ +#include <sysdeps/i386/pthread_spin_init.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_spin_unlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_spin_unlock.S new file mode 100644 index 000000000..8bae0fd31 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_spin_unlock.S @@ -0,0 +1 @@ +#include <sysdeps/i386/pthread_spin_unlock.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/smp.h b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/smp.h new file mode 100644 index 000000000..f68a0c075 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/smp.h @@ -0,0 +1,56 @@ +/* Determine whether the host has multiple processors. Linux version. + Copyright (C) 1996, 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 <errno.h> +#include <fcntl.h> +#include <string.h> +#include <sys/utsname.h> +#include <not-cancel.h> + +/* Test whether the machine has more than one processor. This is not the + best test but good enough. More complicated tests would require `malloc' + which is not available at that time. */ +static inline int +is_smp_system (void) +{ + union + { + struct utsname uts; + char buf[512]; + } u; + char *cp; + + /* Try reading the number using `sysctl' first. */ + if (uname (&u.uts) == 0) + cp = u.uts.version; + else + { + /* This was not successful. Now try reading the /proc filesystem. */ + int fd = open_not_cancel_2 ("/proc/sys/kernel/version", O_RDONLY); + if (__builtin_expect (fd, 0) == -1 + || read_not_cancel (fd, u.buf, sizeof (u.buf)) <= 0) + /* This also didn't work. We give up and say it's a UP machine. */ + u.buf[0] = '\0'; + + close_not_cancel_no_status (fd); + cp = u.buf; + } + + return strstr (cp, "SMP") != NULL; +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h new file mode 100644 index 000000000..cb8d6891c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h @@ -0,0 +1,155 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <pthreadP.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + cmpl $0, %gs:MULTIPLE_THREADS_OFFSET; \ + jne L(pseudo_cancel); \ + .type __##syscall_name##_nocancel,@function; \ + .globl __##syscall_name##_nocancel; \ + __##syscall_name##_nocancel: \ + DO_CALL (syscall_name, args); \ + cmpl $-4095, %eax; \ + jae SYSCALL_ERROR_LABEL; \ + ret; \ + .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ + L(pseudo_cancel): \ + CENABLE \ + SAVE_OLDTYPE_##args \ + PUSHCARGS_##args \ + DOCARGS_##args \ + movl $SYS_ify (syscall_name), %eax; \ + ENTER_KERNEL; \ + POPCARGS_##args; \ + POPSTATE_##args \ + cmpl $-4095, %eax; \ + jae SYSCALL_ERROR_LABEL; \ + L(pseudo_end): + +# define SAVE_OLDTYPE_0 movl %eax, %ecx; +# define SAVE_OLDTYPE_1 SAVE_OLDTYPE_0 +# define SAVE_OLDTYPE_2 pushl %eax; cfi_adjust_cfa_offset (4); +# 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. */ +# define POPCARGS_0 /* No arguments to pop. */ +# define _PUSHCARGS_0 /* No arguments to push. */ +# define _POPCARGS_0 /* No arguments to pop. */ + +# define PUSHCARGS_1 movl %ebx, %edx; cfi_register (ebx, edx); PUSHCARGS_0 +# define DOCARGS_1 _DOARGS_1 (4) +# define POPCARGS_1 POPCARGS_0; movl %edx, %ebx; cfi_restore (ebx); +# define _PUSHCARGS_1 pushl %ebx; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (ebx, 0); _PUSHCARGS_0 +# define _POPCARGS_1 _POPCARGS_0; popl %ebx; \ + cfi_adjust_cfa_offset (-4); cfi_restore (ebx); + +# define PUSHCARGS_2 PUSHCARGS_1 +# define DOCARGS_2 _DOARGS_2 (12) +# define POPCARGS_2 POPCARGS_1 +# define _PUSHCARGS_2 _PUSHCARGS_1 +# define _POPCARGS_2 _POPCARGS_1 + +# define PUSHCARGS_3 _PUSHCARGS_2 +# define DOCARGS_3 _DOARGS_3 (20) +# define POPCARGS_3 _POPCARGS_3 +# define _PUSHCARGS_3 _PUSHCARGS_2 +# define _POPCARGS_3 _POPCARGS_2 + +# define PUSHCARGS_4 _PUSHCARGS_4 +# define DOCARGS_4 _DOARGS_4 (28) +# define POPCARGS_4 _POPCARGS_4 +# define _PUSHCARGS_4 pushl %esi; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (esi, 0); _PUSHCARGS_3 +# define _POPCARGS_4 _POPCARGS_3; popl %esi; \ + cfi_adjust_cfa_offset (-4); cfi_restore (esi); + +# define PUSHCARGS_5 _PUSHCARGS_5 +# define DOCARGS_5 _DOARGS_5 (36) +# define POPCARGS_5 _POPCARGS_5 +# define _PUSHCARGS_5 pushl %edi; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (edi, 0); _PUSHCARGS_4 +# 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 +# elif !defined NOT_IN_libc +# define CENABLE call __libc_enable_asynccancel; +# define CDISABLE call __libc_disable_asynccancel +# elif defined IS_IN_librt +# define CENABLE call __librt_enable_asynccancel; +# define CDISABLE call __librt_disable_asynccancel +# else +# error Unsupported library +# endif +# define POPSTATE_0 \ + pushl %eax; cfi_adjust_cfa_offset (4); movl %ecx, %eax; \ + CDISABLE; popl %eax; cfi_adjust_cfa_offset (-4); +# define POPSTATE_1 POPSTATE_0 +# define POPSTATE_2 xchgl (%esp), %eax; CDISABLE; popl %eax; \ + cfi_adjust_cfa_offset (-4); +# 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 \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P cmpl $0, %gs:MULTIPLE_THREADS_OFFSET +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/i386/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/vfork.S new file mode 100644 index 000000000..b39099af5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/i386/vfork.S @@ -0,0 +1,38 @@ +/* Copyright (C) 1999,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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <tcb-offsets.h> + +/* Save the PID value. */ +#define SAVE_PID \ + movl %gs:PID, %edx; \ + movl %edx, %eax; \ + negl %eax; \ + jne 1f; \ + movl $0x80000000, %eax; \ +1: movl %eax, %gs:PID + +/* Restore the old PID value in the parent. */ +#define RESTORE_PID \ + testl %eax, %eax; \ + je 1f; \ + movl %edx, %gs:PID; \ +1: + + +#include <libc/sysdeps/linux/i386/vfork.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/internaltypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/internaltypes.h new file mode 100644 index 000000000..3466c7fe5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/internaltypes.h @@ -0,0 +1,162 @@ +/* Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _INTERNALTYPES_H +#define _INTERNALTYPES_H 1 + +#include <stdint.h> +#include <sched.h> + +struct pthread_attr +{ + /* Scheduler parameters and priority. */ + struct sched_param schedparam; + int schedpolicy; + /* Various flags like detachstate, scope, etc. */ + int flags; + /* Size of guard area. */ + size_t guardsize; + /* Stack handling. */ + void *stackaddr; + size_t stacksize; + /* Affinity map. */ + cpu_set_t *cpuset; + size_t cpusetsize; +}; + +#define ATTR_FLAG_DETACHSTATE 0x0001 +#define ATTR_FLAG_NOTINHERITSCHED 0x0002 +#define ATTR_FLAG_SCOPEPROCESS 0x0004 +#define ATTR_FLAG_STACKADDR 0x0008 +#define ATTR_FLAG_OLDATTR 0x0010 +#define ATTR_FLAG_SCHED_SET 0x0020 +#define ATTR_FLAG_POLICY_SET 0x0040 + + +/* Mutex attribute data structure. */ +struct pthread_mutexattr +{ + /* Identifier for the kind of mutex. + + Bit 31 is set if the mutex is to be shared between processes. + + Bit 0 to 30 contain one of the PTHREAD_MUTEX_ values to identify + the type of the mutex. */ + int mutexkind; +}; + + +/* Conditional variable attribute data structure. */ +struct pthread_condattr +{ + /* Combination of values: + + Bit 0 : flag whether coditional variable will be shareable between + processes. + + Bit 1-7: clock ID. */ + int value; +}; + + +/* The __NWAITERS field is used as a counter and to house the number + of bits for other purposes. COND_CLOCK_BITS is the number + of bits needed to represent the ID of the clock. COND_NWAITERS_SHIFT + is the number of bits reserved for other purposes like the clock. */ +#define COND_CLOCK_BITS 1 +#define COND_NWAITERS_SHIFT 1 + + +/* Read-write lock variable attribute data structure. */ +struct pthread_rwlockattr +{ + int lockkind; + int pshared; +}; + + +/* Barrier data structure. */ +struct pthread_barrier +{ + unsigned int curr_event; + int lock; + unsigned int left; + unsigned int init_count; + int private; +}; + + +/* Barrier variable attribute data structure. */ +struct pthread_barrierattr +{ + int pshared; +}; + + +/* Thread-local data handling. */ +struct pthread_key_struct +{ + /* Sequence numbers. Even numbers indicated vacant entries. Note + that zero is even. We use uintptr_t to not require padding on + 32- and 64-bit machines. On 64-bit machines it helps to avoid + wrapping, too. */ + uintptr_t seq; + + /* Destructor for the data. */ + void (*destr) (void *); +}; + +/* Check whether an entry is unused. */ +#define KEY_UNUSED(p) (((p) & 1) == 0) +/* Check whether a key is usable. We cannot reuse an allocated key if + the sequence counter would overflow after the next destroy call. + This would mean that we potentially free memory for a key with the + same sequence. This is *very* unlikely to happen, A program would + have to create and destroy a key 2^31 times (on 32-bit platforms, + on 64-bit platforms that would be 2^63). If it should happen we + simply don't use this specific key anymore. */ +#define KEY_USABLE(p) (((uintptr_t) (p)) < ((uintptr_t) ((p) + 2))) + + +/* Handling of read-write lock data. */ +// XXX For now there is only one flag. Maybe more in future. +#define RWLOCK_RECURSIVE(rwlock) ((rwlock)->__data.__flags != 0) + + +/* Semaphore variable structure. */ +struct new_sem +{ + unsigned int value; + int private; + unsigned long int nwaiters; +}; + +struct old_sem +{ + unsigned int value; +}; + + +/* Compatibility type for old conditional variable interfaces. */ +typedef struct +{ + pthread_cond_t *cond; +} pthread_cond_2_0_t; + +#endif /* internaltypes.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c b/libpthread/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c new file mode 100644 index 000000000..f2795510a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c @@ -0,0 +1,39 @@ +/* Clean up stack frames unwound by longjmp. Linux version. + Copyright (C) 1995, 1997, 2002, 2003, 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 + 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 <setjmp.h> +#include <stddef.h> +#include <pthreadP.h> + +extern void __pthread_cleanup_upto (__jmp_buf env, char *targetframe); +#pragma weak __pthread_cleanup_upto + + +void +_longjmp_unwind (jmp_buf env, int val) +{ +#ifdef SHARED + if (__libc_pthread_functions_init) + PTHFCT_CALL (ptr___pthread_cleanup_upto, (env->__jmpbuf, + CURRENT_STACK_FRAME)); +#else + if (__pthread_cleanup_upto != NULL) + __pthread_cleanup_upto (env->__jmpbuf, CURRENT_STACK_FRAME); +#endif +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h b/libpthread/nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h new file mode 100644 index 000000000..9be630268 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h @@ -0,0 +1 @@ +#include <../../../../../../librt/kernel-posix-timers.h> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c b/libpthread/nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c new file mode 100644 index 000000000..b19282281 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c @@ -0,0 +1,21 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras <paulus@au.ibm.com>, 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. */ + +/* No difference to lowlevellock.c, except we lose a couple of functions. */ +#include "lowlevellock.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/libc_multiple_threads.c b/libpthread/nptl/sysdeps/unix/sysv/linux/libc_multiple_threads.c new file mode 100644 index 000000000..a96f17490 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/libc_multiple_threads.c @@ -0,0 +1,26 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthreadP.h> + +#ifndef NOT_IN_libc +# ifndef TLS_MULTIPLE_THREADS_IN_TCB +int __libc_multiple_threads attribute_hidden; +# endif +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c b/libpthread/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c new file mode 100644 index 000000000..136b44595 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c @@ -0,0 +1,74 @@ +/* Copyright (C) 2002,2003,2005,2006,2007,2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <unistd.h> +#include <list.h> +#include <fork.h> +#include <dl-sysdep.h> +#include <tls.h> +#include <string.h> +#include <pthreadP.h> +#include <bits/libc-lock.h> +#include <sysdep.h> +#include <ldsodefs.h> + + +#ifdef TLS_MULTIPLE_THREADS_IN_TCB +void +#else +extern int __libc_multiple_threads attribute_hidden; + +int * +#endif +__libc_pthread_init ( + unsigned long int *ptr, + void (*reclaim) (void), + const struct pthread_functions *functions) +{ + /* Remember the pointer to the generation counter in libpthread. */ + __fork_generation_pointer = ptr; + + /* Called by a child after fork. */ + __register_atfork (NULL, NULL, reclaim, NULL); + +#ifdef SHARED + /* We copy the content of the variable pointed to by the FUNCTIONS + parameter to one in libc.so since this means access to the array + can be done with one memory access instead of two. + */ + memcpy (&__libc_pthread_functions, functions, + sizeof (__libc_pthread_functions)); + __libc_pthread_functions_init = 1; +#endif + +#ifndef TLS_MULTIPLE_THREADS_IN_TCB + return &__libc_multiple_threads; +#endif +} + +#ifdef SHARED +#if 0 +void +libc_freeres_fn (freeres_libptread) +{ + if (__libc_pthread_functions_init) + PTHFCT_CALL (ptr_freeres, ()); +} +#endif +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelbarrier.sym b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelbarrier.sym new file mode 100644 index 000000000..cfe22b089 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelbarrier.sym @@ -0,0 +1,12 @@ +#include <stddef.h> +#include <sched.h> +#include <bits/pthreadtypes.h> +#include "internaltypes.h" + +-- + +CURR_EVENT offsetof (struct pthread_barrier, curr_event) +MUTEX offsetof (struct pthread_barrier, lock) +LEFT offsetof (struct pthread_barrier, left) +INIT_COUNT offsetof (struct pthread_barrier, init_count) +PRIVATE offsetof (struct pthread_barrier, private) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym new file mode 100644 index 000000000..18e1adad4 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym @@ -0,0 +1,16 @@ +#include <stddef.h> +#include <sched.h> +#include <bits/pthreadtypes.h> +#include <internaltypes.h> + +-- + +cond_lock offsetof (pthread_cond_t, __data.__lock) +cond_futex offsetof (pthread_cond_t, __data.__futex) +cond_nwaiters offsetof (pthread_cond_t, __data.__nwaiters) +total_seq offsetof (pthread_cond_t, __data.__total_seq) +wakeup_seq offsetof (pthread_cond_t, __data.__wakeup_seq) +woken_seq offsetof (pthread_cond_t, __data.__woken_seq) +dep_mutex offsetof (pthread_cond_t, __data.__mutex) +broadcast_seq offsetof (pthread_cond_t, __data.__broadcast_seq) +nwaiters_shift COND_NWAITERS_SHIFT diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c new file mode 100644 index 000000000..e07d78819 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c @@ -0,0 +1,127 @@ +/* low level locking for pthread library. Generic futex-using version. + Copyright (C) 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras <paulus@au.ibm.com>, 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 <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <sys/time.h> +#include <tls.h> +#include <tcb-offsets.h> + + +void +__lll_lock_wait_private (int *futex) +{ + if (*futex == 2) + lll_futex_wait (futex, 2, LLL_PRIVATE); + + while (atomic_exchange_acq (futex, 2) != 0) + lll_futex_wait (futex, 2, LLL_PRIVATE); +} + + +/* These functions don't get included in libc.so */ +#ifdef IS_IN_libpthread +void +__lll_lock_wait (int *futex, int private) +{ + if (*futex == 2) + lll_futex_wait (futex, 2, private); + + while (atomic_exchange_acq (futex, 2) != 0) + lll_futex_wait (futex, 2, private); +} + + +int +__lll_timedlock_wait (int *futex, const struct timespec *abstime, int private) +{ + /* Reject invalid timeouts. */ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + /* Try locking. */ + while (atomic_exchange_acq (futex, 2) != 0) + { + struct timeval tv; + + /* Get the current time. */ + (void) gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + struct timespec rt; + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + + if (rt.tv_sec < 0) + return ETIMEDOUT; + + /* Wait. */ + lll_futex_timed_wait (futex, 2, &rt, private); + } + + return 0; +} + + +int +__lll_timedwait_tid (int *tidp, const struct timespec *abstime) +{ + int tid; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + /* Repeat until thread terminated. */ + while ((tid = *tidp) != 0) + { + struct timeval tv; + struct timespec rt; + + /* Get the current time. */ + (void) __gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + + /* Already timed out? */ + if (rt.tv_sec < 0) + return ETIMEDOUT; + + /* Wait until thread terminates. The kernel so far does not use + the private futex operations for this. */ + if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT) + return ETIMEDOUT; + } + + return 0; +} +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c new file mode 100644 index 000000000..3830f94da --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c @@ -0,0 +1,114 @@ +/* Copyright (C) 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2006. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <sys/time.h> +#include <pthreadP.h> + + +int +__lll_robust_lock_wait (int *futex, int private) +{ + int oldval = *futex; + int tid = THREAD_GETMEM (THREAD_SELF, tid); + + /* If the futex changed meanwhile try locking again. */ + if (oldval == 0) + goto try; + + do + { + if (__builtin_expect (oldval & FUTEX_OWNER_DIED, 0)) + return oldval; + + int newval = oldval | FUTEX_WAITERS; + if (oldval != newval + && atomic_compare_and_exchange_bool_acq (futex, newval, oldval)) + continue; + + lll_futex_wait (futex, newval, private); + + try: + ; + } + while ((oldval = atomic_compare_and_exchange_val_acq (futex, + tid | FUTEX_WAITERS, + 0)) != 0); + return 0; +} + + +int +__lll_robust_timedlock_wait (int *futex, const struct timespec *abstime, + int private) +{ + /* Reject invalid timeouts. */ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + int tid = THREAD_GETMEM (THREAD_SELF, tid); + int oldval = *futex; + + /* If the futex changed meanwhile try locking again. */ + if (oldval == 0) + goto try; + + do + { + struct timeval tv; + struct timespec rt; + + /* Get the current time. */ + (void) __gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + + /* Already timed out? */ + if (rt.tv_sec < 0) + return ETIMEDOUT; + + /* Wait. */ + if (__builtin_expect (oldval & FUTEX_OWNER_DIED, 0)) + return oldval; + + int newval = oldval | FUTEX_WAITERS; + if (oldval != newval + && atomic_compare_and_exchange_bool_acq (futex, newval, oldval)) + continue; + + lll_futex_timed_wait (futex, newval, &rt, private); + + try: + ; + } + while ((oldval = atomic_compare_and_exchange_val_acq (futex, + tid | FUTEX_WAITERS, + 0)) != 0); + + return 0; +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.sym b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.sym new file mode 100644 index 000000000..2f1e9da52 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.sym @@ -0,0 +1,6 @@ +#include <stddef.h> +#include <pthreadP.h> + +-- + +TID offsetof (struct pthread, tid) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrwlock.sym b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrwlock.sym new file mode 100644 index 000000000..f50b25bfb --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrwlock.sym @@ -0,0 +1,16 @@ +#include <stddef.h> +#include <stdio.h> +#include <bits/pthreadtypes.h> +#include <bits/wordsize.h> + +-- + +MUTEX offsetof (pthread_rwlock_t, __data.__lock) +NR_READERS offsetof (pthread_rwlock_t, __data.__nr_readers) +READERS_WAKEUP offsetof (pthread_rwlock_t, __data.__readers_wakeup) +WRITERS_WAKEUP offsetof (pthread_rwlock_t, __data.__writer_wakeup) +READERS_QUEUED offsetof (pthread_rwlock_t, __data.__nr_readers_queued) +WRITERS_QUEUED offsetof (pthread_rwlock_t, __data.__nr_writers_queued) +FLAGS offsetof (pthread_rwlock_t, __data.__flags) +WRITER offsetof (pthread_rwlock_t, __data.__writer) +PSHARED offsetof (pthread_rwlock_t, __data.__shared) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lseek.S b/libpthread/nptl/sysdeps/unix/sysv/linux/lseek.S new file mode 100644 index 000000000..70a920ba1 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lseek.S @@ -0,0 +1,7 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_lseek, lseek, 3) +ret +PSEUDO_END (__libc_lseek) +libc_hidden_def (__libc_lseek) +weak_alias (__libc_lseek, lseek) +libc_hidden_weak (lseek) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile new file mode 100644 index 000000000..43a6fad84 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../../../../ +top_builddir=../../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile.arch b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile.arch new file mode 100644 index 000000000..8e7917bb0 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile.arch @@ -0,0 +1,50 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_SSRC = pt-vfork.S +libpthread_CSRC = pthread_once.c pt-__syscall_rt_sigaction.c + +libc_a_CSRC = fork.c + +CFLAGS-OMIT-fork.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y) +CFLAGS-fork.c = -D__USE_STDIO_FUTEXES__ +endif +CFLAGS-pthread_once.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-pt-__syscall_rt_sigaction.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + +ASFLAGS-pt-vfork.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + +CFLAGS += $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +LINUX_ARCH_DIR:=$(top_srcdir)libpthread/nptl/sysdeps/unix/sysv/linux/mips +LINUX_ARCH_OUT:=$(top_builddir)libpthread/nptl/sysdeps/unix/sysv/linux/mips + +LINUX_ARCH_OBJ:=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libpthread_SSRC)) +LINUX_ARCH_OBJ+=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libpthread_CSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(LINUX_ARCH_OBJ:.o=.os) +else +libpthread-a-y += $(LINUX_ARCH_OBJ) +endif +libpthread-so-y += $(LINUX_ARCH_OBJ:.o=.oS) + +libpthread-nomulti-y+=$(LINUX_ARCH_OBJS) + +LIBC_LINUX_ARCH_OBJ:=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libc_a_CSRC)) + +libc-static-y+=$(LIBC_LINUX_ARCH_OBJ) +libc-shared-y+=$(LIBC_LINUX_ARCH_OBJ:.o=.oS) + +libc-nomulti-y+=$(LIBC_LINUX_ARCH_OBJ) + +objclean-y+=pthread_linux_arch_objclean + +pthread_linux_arch_objclean: + $(RM) $(LINUX_ARCH_OUT)/*.{o,os,oS} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/bits/pthreadtypes.h new file mode 100644 index 000000000..166a6c6ae --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/bits/pthreadtypes.h @@ -0,0 +1,229 @@ +/* Machine-specific pthread type layouts. MIPS version. + Copyright (C) 2005, 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#include <endian.h> + +#if _MIPS_SIM == _ABI64 +# define __SIZEOF_PTHREAD_ATTR_T 56 +# define __SIZEOF_PTHREAD_MUTEX_T 40 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 56 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 32 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#else +# define __SIZEOF_PTHREAD_ATTR_T 36 +# define __SIZEOF_PTHREAD_MUTEX_T 24 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 32 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 20 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#endif + + +/* Thread identifiers. The structure of the attribute type is + deliberately not exposed. */ +typedef unsigned long int pthread_t; + + +typedef union +{ + char __size[__SIZEOF_PTHREAD_ATTR_T]; + long int __align; +} pthread_attr_t; + + +#if _MIPS_SIM == _ABI64 +typedef struct __pthread_internal_list +{ + struct __pthread_internal_list *__prev; + struct __pthread_internal_list *__next; +} __pthread_list_t; +#else +typedef struct __pthread_internal_slist +{ + struct __pthread_internal_slist *__next; +} __pthread_slist_t; +#endif + + +/* Data structures for mutex handling. The structure of the attribute + type is deliberately not exposed. */ +typedef union +{ + struct __pthread_mutex_s + { + int __lock; + unsigned int __count; + int __owner; +#if _MIPS_SIM == _ABI64 + unsigned int __nusers; +#endif + /* KIND must stay at this position in the structure to maintain + binary compatibility. */ + int __kind; +#if _MIPS_SIM == _ABI64 + int __spins; + __pthread_list_t __list; +# define __PTHREAD_MUTEX_HAVE_PREV 1 +#else + unsigned int __nusers; + __extension__ union + { + int __spins; + __pthread_slist_t __list; + }; +#endif + } __data; + char __size[__SIZEOF_PTHREAD_MUTEX_T]; + long int __align; +} pthread_mutex_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; + int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling. The structure of + the attribute type is deliberately not exposed. */ +typedef union +{ + struct + { + int __lock; + unsigned int __futex; + __extension__ unsigned long long int __total_seq; + __extension__ unsigned long long int __wakeup_seq; + __extension__ unsigned long long int __woken_seq; + void *__mutex; + unsigned int __nwaiters; + unsigned int __broadcast_seq; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_CONDATTR_T]; + int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling. The + structure of the attribute type is deliberately not exposed. */ +typedef union +{ +# if _MIPS_SIM == _ABI64 + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + int __writer; + int __shared; + unsigned long int __pad1; + unsigned long int __pad2; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned int __flags; + } __data; +# else + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned char __pad1; + unsigned char __pad2; + unsigned char __shared; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; +#else + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; + unsigned char __shared; + unsigned char __pad1; + unsigned char __pad2; +#endif + int __writer; + } __data; +# endif + char __size[__SIZEOF_PTHREAD_RWLOCK_T]; + long int __align; +} pthread_rwlock_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; + long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type. The structure of the type is + deliberately not exposed. */ +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIER_T]; + long int __align; +} pthread_barrier_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; + int __align; +} pthread_barrierattr_t; +#endif + + +#endif /* bits/pthreadtypes.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/bits/semaphore.h new file mode 100644 index 000000000..af43a6048 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/bits/semaphore.h @@ -0,0 +1,37 @@ +/* Copyright (C) 2002, 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 + 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. */ + +#ifndef _SEMAPHORE_H +# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." +#endif + +#if _MIPS_SIM == _ABI64 +# define __SIZEOF_SEM_T 32 +#else +# define __SIZEOF_SEM_T 16 +#endif + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + + +typedef union +{ + char __size[__SIZEOF_SEM_T]; + long int __align; +} sem_t; diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/createthread.c b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/createthread.c new file mode 100644 index 000000000..d8a7c5539 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/createthread.c @@ -0,0 +1,24 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Value passed to 'clone' for initialization of the thread register. */ +#define TLS_VALUE ((void *) (pd) \ + + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE) + +/* Get the real implementation. */ +#include <sysdeps/pthread/createthread.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/fork.c new file mode 100644 index 000000000..06b7e1c69 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/fork.c @@ -0,0 +1 @@ +#include "../i386/fork.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/lowlevellock.h new file mode 100644 index 000000000..01bcf4120 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/lowlevellock.h @@ -0,0 +1,295 @@ +/* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, + 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H 1 + +#include <time.h> +#include <sys/param.h> +#include <bits/pthreadtypes.h> +#include <atomic.h> +#include <sysdep.h> +#include <bits/kernel-features.h> + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 +#define FUTEX_WAKE_OP 5 +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 +#define FUTEX_WAIT_BITSET 9 +#define FUTEX_WAKE_BITSET 10 +#define FUTEX_PRIVATE_FLAG 128 +#define FUTEX_CLOCK_REALTIME 256 + +#define FUTEX_BITSET_MATCH_ANY 0xffffffff + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \ + & THREAD_GETMEM (THREAD_SELF, header.private_futex)))) +# endif +#endif + + +#define lll_futex_wait(futexp, val, private) \ + lll_futex_timed_wait(futexp, val, NULL, private) + +#define lll_futex_timed_wait(futexp, val, timespec, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (long) (futexp), \ + __lll_private_flag (FUTEX_WAIT, private), \ + (val), (timespec)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \ + }) + +#define lll_futex_wake(futexp, nr, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (long) (futexp), \ + __lll_private_flag (FUTEX_WAKE, private), \ + (nr), 0); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \ + }) + +#define lll_robust_dead(futexv, private) \ + do \ + { \ + int *__futexp = &(futexv); \ + atomic_or (__futexp, FUTEX_OWNER_DIED); \ + lll_futex_wake (__futexp, 1, private); \ + } \ + while (0) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (long) (futexp), \ + __lll_private_flag (FUTEX_CMP_REQUEUE, private),\ + (nr_wake), (nr_move), (mutex), (val)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_WAKE_OP, private), \ + (nr_wake), (nr_wake2), (futexp2), \ + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + +static inline int __attribute__((always_inline)) +__lll_trylock(int *futex) +{ + return atomic_compare_and_exchange_val_acq (futex, 1, 0) != 0; +} +#define lll_trylock(lock) __lll_trylock (&(lock)) + + +static inline int __attribute__((always_inline)) +__lll_cond_trylock(int *futex) +{ + return atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0; +} +#define lll_cond_trylock(lock) __lll_cond_trylock (&(lock)) + + +static inline int __attribute__((always_inline)) +__lll_robust_trylock(int *futex, int id) +{ + return atomic_compare_and_exchange_val_acq (futex, id, 0) != 0; +} +#define lll_robust_trylock(lock, id) \ + __lll_robust_trylock (&(lock), id) + +extern void __lll_lock_wait_private (int *futex) attribute_hidden; +extern void __lll_lock_wait (int *futex, int private) attribute_hidden; +extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden; + +#define __lll_lock(futex, private) \ + ((void) ({ \ + int *__futex = (futex); \ + if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, \ + 1, 0), 0)) \ + { \ + if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \ + __lll_lock_wait_private (__futex); \ + else \ + __lll_lock_wait (__futex, private); \ + } \ + })) +#define lll_lock(futex, private) __lll_lock (&(futex), private) + + +#define __lll_robust_lock(futex, id, private) \ + ({ \ + int *__futex = (futex); \ + int __val = 0; \ + \ + if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \ + 0), 0)) \ + __val = __lll_robust_lock_wait (__futex, private); \ + __val; \ + }) +#define lll_robust_lock(futex, id, private) \ + __lll_robust_lock (&(futex), id, private) + + +static inline void __attribute__ ((always_inline)) +__lll_cond_lock (int *futex, int private) +{ + if (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0) + __lll_lock_wait (futex, private); +} +#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private) + + +#define lll_robust_cond_lock(futex, id, private) \ + __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private) + + +extern int __lll_timedlock_wait (int *futex, const struct timespec *, + int private) attribute_hidden; +extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *, + int private) attribute_hidden; + +static inline int __attribute__ ((always_inline)) +__lll_timedlock (int *futex, const struct timespec *abstime, int private) +{ + int result = 0; + if (atomic_compare_and_exchange_bool_acq (futex, 1, 0) != 0) + result = __lll_timedlock_wait (futex, abstime, private); + return result; +} +#define lll_timedlock(futex, abstime, private) \ + __lll_timedlock (&(futex), abstime, private) + + +static inline int __attribute__ ((always_inline)) +__lll_robust_timedlock (int *futex, const struct timespec *abstime, + int id, int private) +{ + int result = 0; + if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0) + result = __lll_robust_timedlock_wait (futex, abstime, private); + return result; +} +#define lll_robust_timedlock(futex, abstime, id, private) \ + __lll_robust_timedlock (&(futex), abstime, id, private) + + +#define __lll_unlock(futex, private) \ + ((void) ({ \ + int *__futex = (futex); \ + int __val = atomic_exchange_rel (__futex, 0); \ + \ + if (__builtin_expect (__val > 1, 0)) \ + lll_futex_wake (__futex, 1, private); \ + })) +#define lll_unlock(futex, private) __lll_unlock(&(futex), private) + + +#define __lll_robust_unlock(futex, private) \ + ((void) ({ \ + int *__futex = (futex); \ + int __val = atomic_exchange_rel (__futex, 0); \ + \ + if (__builtin_expect (__val & FUTEX_WAITERS, 0)) \ + lll_futex_wake (__futex, 1, private); \ + })) +#define lll_robust_unlock(futex, private) \ + __lll_robust_unlock(&(futex), private) + + +#define lll_islocked(futex) \ + (futex != 0) + + +/* Our internal lock implementation is identical to the binary-compatible + mutex implementation. */ + +/* Initializers for lock. */ +#define LLL_LOCK_INITIALIZER (0) +#define LLL_LOCK_INITIALIZER_LOCKED (1) + +/* The states of a lock are: + 0 - untaken + 1 - taken by one user + >1 - taken by more users */ + +/* The kernel notifies a process which uses CLONE_CLEARTID via futex + wakeup when the clone terminates. The memory location contains the + thread ID while the clone is running and is reset to zero + afterwards. */ +#define lll_wait_tid(tid) \ + do { \ + __typeof (tid) __tid; \ + while ((__tid = (tid)) != 0) \ + lll_futex_wait (&(tid), __tid, LLL_SHARED); \ + } while (0) + +extern int __lll_timedwait_tid (int *, const struct timespec *) + attribute_hidden; + +#define lll_timedwait_tid(tid, abstime) \ + ({ \ + int __res = 0; \ + if ((tid) != 0) \ + __res = __lll_timedwait_tid (&(tid), (abstime)); \ + __res; \ + }) + +#endif /* lowlevellock.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-__syscall_rt_sigaction.c b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-__syscall_rt_sigaction.c new file mode 100644 index 000000000..50137c84a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-__syscall_rt_sigaction.c @@ -0,0 +1 @@ +#include <../../../../../../../libc/sysdeps/linux/common/__syscall_rt_sigaction.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-clone.S new file mode 100644 index 000000000..add405523 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <../../../../../../../libc/sysdeps/linux/mips/clone.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-vfork.S new file mode 100644 index 000000000..c02ffca93 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-vfork.S @@ -0,0 +1,38 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <features.h> +#include <tls.h> + +/* Save the PID value. */ +#define SAVE_PID \ + READ_THREAD_POINTER(v1); /* Get the thread pointer. */ \ + lw a2, PID_OFFSET(v1); /* Load the saved PID. */ \ + subu a2, $0, a2; /* Negate it. */ \ + sw a2, PID_OFFSET(v1); /* Store the temporary PID. */ + +/* Restore the old PID value in the parent. */ +#define RESTORE_PID \ + beqz v0, 1f; /* If we are the parent... */ \ + READ_THREAD_POINTER(v1); /* Get the thread pointer. */ \ + lw a2, PID_OFFSET(v1); /* Load the saved PID. */ \ + subu a2, $0, a2; /* Re-negate it. */ \ + sw a2, PID_OFFSET(v1); /* Restore the PID. */ \ +1: + +#include <../../../../../../../libc/sysdeps/linux/mips/vfork.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pthread_once.c b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pthread_once.c new file mode 100644 index 000000000..f7b940f52 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pthread_once.c @@ -0,0 +1,95 @@ +/* Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 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 <lowlevellock.h> + + +unsigned long int __fork_generation attribute_hidden; + + +static void +clear_once_control (void *arg) +{ + pthread_once_t *once_control = (pthread_once_t *) arg; + + *once_control = 0; + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +} + + +int +attribute_hidden +__pthread_once (once_control, init_routine) + pthread_once_t *once_control; + void (*init_routine) (void); +{ + while (1) + { + int oldval, val, newval; + + val = *once_control; + do + { + /* Check if the initialized has already been done. */ + if ((val & 2) != 0) + return 0; + + oldval = val; + newval = (oldval & 3) | __fork_generation | 1; + val = atomic_compare_and_exchange_val_acq (once_control, newval, + oldval); + } + while (__builtin_expect (val != oldval, 0)); + + /* Check if another thread already runs the initializer. */ + if ((oldval & 1) != 0) + { + /* Check whether the initializer execution was interrupted + by a fork. */ + if (((oldval ^ newval) & -4) == 0) + { + /* Same generation, some other thread was faster. Wait. */ + lll_futex_wait (once_control, newval, LLL_PRIVATE); + continue; + } + } + + /* This thread is the first here. Do the initialization. + Register a cleanup handler so that in case the thread gets + interrupted the initialization can be restarted. */ + pthread_cleanup_push (clear_once_control, once_control); + + init_routine (); + + pthread_cleanup_pop (0); + + + /* Add one to *once_control. */ + atomic_increment (once_control); + + /* Wake up all other threads. */ + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); + break; + } + + return 0; +} +weak_alias (__pthread_once, pthread_once) +strong_alias (__pthread_once, __pthread_once_internal) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h new file mode 100644 index 000000000..1cf625f4e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h @@ -0,0 +1,188 @@ +/* Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <pthreadP.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# ifdef __PIC__ +# define PSEUDO_CPLOAD .cpload t9; +# define PSEUDO_ERRJMP la t9, __syscall_error; jr t9; +# define PSEUDO_SAVEGP sw gp, 32(sp); cfi_rel_offset (gp, 32); +# define PSEUDO_LOADGP lw gp, 32(sp); +# else +# define PSEUDO_CPLOAD +# define PSEUDO_ERRJMP j __syscall_error; +# define PSEUDO_SAVEGP +# define PSEUDO_LOADGP +# endif + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .align 2; \ + L(pseudo_start): \ + cfi_startproc; \ + 99: PSEUDO_ERRJMP \ + .type __##syscall_name##_nocancel, @function; \ + .globl __##syscall_name##_nocancel; \ + __##syscall_name##_nocancel: \ + .set noreorder; \ + PSEUDO_CPLOAD \ + li v0, SYS_ify(syscall_name); \ + syscall; \ + .set reorder; \ + bne a3, zero, 99b; \ + ret; \ + .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ + ENTRY (name) \ + .set noreorder; \ + PSEUDO_CPLOAD \ + .set reorder; \ + SINGLE_THREAD_P(v1); \ + bne zero, v1, L(pseudo_cancel); \ + .set noreorder; \ + li v0, SYS_ify(syscall_name); \ + syscall; \ + .set reorder; \ + bne a3, zero, 99b; \ + ret; \ + L(pseudo_cancel): \ + SAVESTK_##args; \ + sw ra, 28(sp); \ + cfi_rel_offset (ra, 28); \ + PSEUDO_SAVEGP \ + PUSHARGS_##args; /* save syscall args */ \ + CENABLE; \ + PSEUDO_LOADGP \ + sw v0, 44(sp); /* save mask */ \ + POPARGS_##args; /* restore syscall args */ \ + .set noreorder; \ + li v0, SYS_ify (syscall_name); \ + syscall; \ + .set reorder; \ + sw v0, 36(sp); /* save syscall result */ \ + sw a3, 40(sp); /* save syscall error flag */ \ + lw a0, 44(sp); /* pass mask as arg1 */ \ + CDISABLE; \ + PSEUDO_LOADGP \ + lw v0, 36(sp); /* restore syscall result */ \ + lw a3, 40(sp); /* restore syscall error flag */ \ + lw ra, 28(sp); /* restore return address */ \ + .set noreorder; \ + bne a3, zero, 99b; \ + RESTORESTK; \ + L(pseudo_end): \ + .set reorder; + +# undef PSEUDO_END +# define PSEUDO_END(sym) cfi_endproc; .end sym; .size sym,.-sym + +# define PUSHARGS_0 /* nothing to do */ +# define PUSHARGS_1 PUSHARGS_0 sw a0, 0(sp); cfi_rel_offset (a0, 0); +# define PUSHARGS_2 PUSHARGS_1 sw a1, 4(sp); cfi_rel_offset (a1, 4); +# define PUSHARGS_3 PUSHARGS_2 sw a2, 8(sp); cfi_rel_offset (a2, 8); +# define PUSHARGS_4 PUSHARGS_3 sw a3, 12(sp); cfi_rel_offset (a3, 12); +# define PUSHARGS_5 PUSHARGS_4 /* handled by SAVESTK_## */ +# define PUSHARGS_6 PUSHARGS_5 +# define PUSHARGS_7 PUSHARGS_6 + +# define POPARGS_0 /* nothing to do */ +# define POPARGS_1 POPARGS_0 lw a0, 0(sp); +# define POPARGS_2 POPARGS_1 lw a1, 4(sp); +# define POPARGS_3 POPARGS_2 lw a2, 8(sp); +# define POPARGS_4 POPARGS_3 lw a3, 12(sp); +# define POPARGS_5 POPARGS_4 /* args already in new stackframe */ +# define POPARGS_6 POPARGS_5 +# define POPARGS_7 POPARGS_6 + + +# define STKSPACE 48 +# define SAVESTK_0 subu sp, STKSPACE; cfi_adjust_cfa_offset(STKSPACE) +# define SAVESTK_1 SAVESTK_0 +# define SAVESTK_2 SAVESTK_1 +# define SAVESTK_3 SAVESTK_2 +# define SAVESTK_4 SAVESTK_3 +# define SAVESTK_5 lw t0, 16(sp); \ + SAVESTK_0; \ + sw t0, 16(sp) + +# define SAVESTK_6 lw t0, 16(sp); \ + lw t1, 20(sp); \ + SAVESTK_0; \ + sw t0, 16(sp); \ + sw t1, 20(sp) + +# define SAVESTK_7 lw t0, 16(sp); \ + lw t1, 20(sp); \ + lw t2, 24(sp); \ + SAVESTK_0; \ + sw t0, 16(sp); \ + sw t1, 20(sp); \ + sw t2, 24(sp) + +# define RESTORESTK addu sp, STKSPACE; cfi_adjust_cfa_offset(-STKSPACE) + + +# ifdef __PIC__ +/* We use jalr rather than jal. This means that the assembler will not + automatically restore $gp (in case libc has multiple GOTs) so we must + do it manually - which we have to do anyway since we don't use .cprestore. + It also shuts up the assembler warning about not using .cprestore. */ +# define PSEUDO_JMP(sym) la t9, sym; jalr t9; +# else +# define PSEUDO_JMP(sym) jal sym; +# endif + +# ifdef IS_IN_libpthread +# define CENABLE PSEUDO_JMP (__pthread_enable_asynccancel) +# define CDISABLE PSEUDO_JMP (__pthread_disable_asynccancel) +# elif defined IS_IN_librt +# define CENABLE PSEUDO_JMP (__librt_enable_asynccancel) +# define CDISABLE PSEUDO_JMP (__librt_disable_asynccancel) +# else +# define CENABLE PSEUDO_JMP (__libc_enable_asynccancel) +# define CDISABLE PSEUDO_JMP (__libc_disable_asynccancel) +# endif + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) \ + == 0, 1) +# else +# define SINGLE_THREAD_P(reg) \ + READ_THREAD_POINTER(reg); \ + lw reg, MULTIPLE_THREADS_OFFSET(reg) +#endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P 1 +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mq_notify.c b/libpthread/nptl/sysdeps/unix/sysv/linux/mq_notify.c new file mode 100644 index 000000000..188040ee8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mq_notify.c @@ -0,0 +1,286 @@ +/* Copyright (C) 2004, 2005, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contribute by Ulrich Drepper <drepper@redhat.com>, 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <mqueue.h> +#include <pthread.h> +#include <signal.h> +#include <stdlib.h> +#include <string.h> +#include <sysdep.h> +#include <unistd.h> +#include <sys/socket.h> +#include <not-cancel.h> +#include <bits/kernel-features.h> + + +#ifdef __NR_mq_notify + +/* Defined in the kernel headers: */ +#define NOTIFY_COOKIE_LEN 32 /* Length of the cookie used. */ +#define NOTIFY_WOKENUP 1 /* Code for notifcation. */ +#define NOTIFY_REMOVED 2 /* Code for closed message queue + of de-notifcation. */ + + +/* Data structure for the queued notification requests. */ +union notify_data +{ + struct + { + void (*fct) (union sigval); /* The function to run. */ + union sigval param; /* The parameter to pass. */ + pthread_attr_t *attr; /* Attributes to create the thread with. */ + /* NB: on 64-bit machines the struct as a size of 24 bytes. Which means + byte 31 can still be used for returning the status. */ + }; + char raw[NOTIFY_COOKIE_LEN]; +}; + + +/* Keep track of the initialization. */ +static pthread_once_t once = PTHREAD_ONCE_INIT; + + +/* The netlink socket. */ +static int netlink_socket = -1; + + +/* Barrier used to make sure data passed to the new thread is not + resused by the parent. */ +static pthread_barrier_t notify_barrier; + + +/* Modify the signal mask. We move this into a separate function so + that the stack space needed for sigset_t is not deducted from what + the thread can use. */ +static int +__attribute__ ((noinline)) +change_sigmask (int how, sigset_t *oss) +{ + sigset_t ss; + sigfillset (&ss); + return pthread_sigmask (how, &ss, oss); +} + + +/* The function used for the notification. */ +static void * +notification_function (void *arg) +{ + /* Copy the function and parameter so that the parent thread can go + on with its life. */ + volatile union notify_data *data = (volatile union notify_data *) arg; + void (*fct) (union sigval) = data->fct; + union sigval param = data->param; + + /* Let the parent go. */ + (void) pthread_barrier_wait (¬ify_barrier); + + /* Make the thread detached. */ + (void) pthread_detach (pthread_self ()); + + /* The parent thread has all signals blocked. This is probably a + bit surprising for this thread. So we unblock all of them. */ + (void) change_sigmask (SIG_UNBLOCK, NULL); + + /* Now run the user code. */ + fct (param); + + /* And we are done. */ + return NULL; +} + + +/* Helper thread. */ +static void * +helper_thread (void *arg) +{ + while (1) + { + union notify_data data; + + ssize_t n = recv (netlink_socket, &data, sizeof (data), + MSG_NOSIGNAL | MSG_WAITALL); + if (n < NOTIFY_COOKIE_LEN) + continue; + + if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_WOKENUP) + { + /* Just create the thread as instructed. There is no way to + report a problem with creating a thread. */ + pthread_t th; + if (__builtin_expect (pthread_create (&th, data.attr, + notification_function, &data) + == 0, 0)) + /* Since we passed a pointer to DATA to the new thread we have + to wait until it is done with it. */ + (void) pthread_barrier_wait (¬ify_barrier); + } + else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED) + /* The only state we keep is the copy of the thread attributes. */ + free (data.attr); + } + return NULL; +} + + +static void +reset_once (void) +{ + once = PTHREAD_ONCE_INIT; +} + + +static void +init_mq_netlink (void) +{ + /* This code might be called a second time after fork(). The file + descriptor is inherited from the parent. */ + if (netlink_socket == -1) + { + /* Just a normal netlink socket, not bound. */ + netlink_socket = socket (AF_NETLINK, SOCK_RAW, 0); + /* No need to do more if we have no socket. */ + if (netlink_socket == -1) + return; + + /* Make sure the descriptor is closed on exec. */ + if (fcntl (netlink_socket, F_SETFD, FD_CLOEXEC) != 0) + goto errout; + } + + int err = 1; + + /* Initialize the barrier. */ + if (__builtin_expect (pthread_barrier_init (¬ify_barrier, NULL, 2) == 0, + 0)) + { + /* Create the helper thread. */ + pthread_attr_t attr; + (void) pthread_attr_init (&attr); + (void) pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + /* We do not need much stack space, the bare minimum will be enough. */ + (void) pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN); + + /* Temporarily block all signals so that the newly created + thread inherits the mask. */ + sigset_t oss; + int have_no_oss = change_sigmask (SIG_BLOCK, &oss); + + pthread_t th; + err = pthread_create (&th, &attr, helper_thread, NULL); + + /* Reset the signal mask. */ + if (!have_no_oss) + pthread_sigmask (SIG_SETMASK, &oss, NULL); + + (void) pthread_attr_destroy (&attr); + + if (err == 0) + { + static int added_atfork; + + if (added_atfork == 0 + && pthread_atfork (NULL, NULL, reset_once) != 0) + { + /* The child thread will call recv() which is a + cancellation point. */ + (void) pthread_cancel (th); + err = 1; + } + else + added_atfork = 1; + } + } + + if (err != 0) + { + errout: + close_not_cancel_no_status (netlink_socket); + netlink_socket = -1; + } +} + + +/* Register notification upon message arrival to an empty message queue + MQDES. */ +int +mq_notify (mqd_t mqdes, const struct sigevent *notification) +{ + /* Make sure the type is correctly defined. */ + assert (sizeof (union notify_data) == NOTIFY_COOKIE_LEN); + + /* Special treatment needed for SIGEV_THREAD. */ + if (notification == NULL || notification->sigev_notify != SIGEV_THREAD) + return INLINE_SYSCALL (mq_notify, 2, mqdes, notification); + + /* The kernel cannot directly start threads. This will have to be + done at userlevel. Since we cannot start threads from signal + handlers we have to create a dedicated thread which waits for + notifications for arriving messages and creates threads in + response. */ + + /* Initialize only once. */ + pthread_once (&once, init_mq_netlink); + + /* If we cannot create the netlink socket we cannot provide + SIGEV_THREAD support. */ + if (__builtin_expect (netlink_socket == -1, 0)) + { + __set_errno (ENOSYS); + return -1; + } + + /* Create the cookie. It will hold almost all the state. */ + union notify_data data; + memset (&data, '\0', sizeof (data)); + data.fct = notification->sigev_notify_function; + data.param = notification->sigev_value; + + if (notification->sigev_notify_attributes != NULL) + { + /* The thread attribute has to be allocated separately. */ + data.attr = (pthread_attr_t *) malloc (sizeof (pthread_attr_t)); + if (data.attr == NULL) + return -1; + + memcpy (data.attr, notification->sigev_notify_attributes, + sizeof (pthread_attr_t)); + } + + /* Construct the new request. */ + struct sigevent se; + se.sigev_notify = SIGEV_THREAD; + se.sigev_signo = netlink_socket; + se.sigev_value.sival_ptr = &data; + + /* Tell the kernel. */ + int retval = INLINE_SYSCALL (mq_notify, 2, mqdes, &se); + + /* If it failed, free the allocated memory. */ + if (__builtin_expect (retval != 0, 0)) + free (data.attr); + + return retval; +} + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/msync.S b/libpthread/nptl/sysdeps/unix/sysv/linux/msync.S new file mode 100644 index 000000000..074a0d717 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/msync.S @@ -0,0 +1,7 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_msync, msync, 3) +ret +PSEUDO_END(__libc_msync) +libc_hidden_def (__libc_msync) +weak_alias (__libc_msync, msync) +libc_hidden_weak (msync) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nanosleep.S b/libpthread/nptl/sysdeps/unix/sysv/linux/nanosleep.S new file mode 100644 index 000000000..71efe32f9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/nanosleep.S @@ -0,0 +1,9 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_nanosleep, nanosleep, 3) +ret +PSEUDO_END (__libc_nanosleep) +libc_hidden_def (__libc_nanosleep) +weak_alias (__libc_nanosleep, __nanosleep) +libc_hidden_weak (__nanosleep) +weak_alias (__libc_nanosleep, nanosleep) +libc_hidden_weak (nanosleep) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/not-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/not-cancel.h new file mode 100644 index 000000000..80d33be29 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/not-cancel.h @@ -0,0 +1,105 @@ +/* Uncancelable versions of cancelable interfaces. Linux version. + Copyright (C) 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 <sys/types.h> +#include <sysdep.h> + +/* Uncancelable open. */ +#define open_not_cancel(name, flags, mode) \ + INLINE_SYSCALL (open, 3, (const char *) (name), (flags), (mode)) +#define open_not_cancel_2(name, flags) \ + INLINE_SYSCALL (open, 2, (const char *) (name), (flags)) + +/* Uncancelable openat. */ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt +extern int __openat_nocancel (int fd, const char *fname, int oflag, + mode_t mode) attribute_hidden; +extern int __openat64_nocancel (int fd, const char *fname, int oflag, + mode_t mode) attribute_hidden; +#else +# define __openat_nocancel(fd, fname, oflag, mode) \ + openat (fd, fname, oflag, mode) +# define __openat64_nocancel(fd, fname, oflag, mode) \ + openat64 (fd, fname, oflag, mode) +#endif + +#define openat_not_cancel(fd, fname, oflag, mode) \ + __openat_nocancel (fd, fname, oflag, mode) +#define openat_not_cancel_3(fd, fname, oflag) \ + __openat_nocancel (fd, fname, oflag, 0) +#define openat64_not_cancel(fd, fname, oflag, mode) \ + __openat64_nocancel (fd, fname, oflag, mode) +#define openat64_not_cancel_3(fd, fname, oflag) \ + __openat64_nocancel (fd, fname, oflag, 0) + +/* Uncancelable close. */ +#define close_not_cancel(fd) \ + INLINE_SYSCALL (close, 1, fd) +#define close_not_cancel_no_status(fd) \ + (void) ({ INTERNAL_SYSCALL_DECL (err); \ + INTERNAL_SYSCALL (close, err, 1, (fd)); }) + +/* Uncancelable read. */ +#define read_not_cancel(fd, buf, n) \ + INLINE_SYSCALL (read, 3, (fd), (buf), (n)) + +/* Uncancelable write. */ +#define write_not_cancel(fd, buf, n) \ + INLINE_SYSCALL (write, 3, (fd), (buf), (n)) + +/* Uncancelable writev. */ +#define writev_not_cancel_no_status(fd, iov, n) \ + (void) ({ INTERNAL_SYSCALL_DECL (err); \ + INTERNAL_SYSCALL (writev, err, 3, (fd), (iov), (n)); }) + +/* Uncancelable fcntl. */ +#define fcntl_not_cancel(fd, cmd, val) \ + __fcntl_nocancel (fd, cmd, val) + +/* Uncancelable waitpid. */ +#ifdef __NR_waitpid +# define waitpid_not_cancel(pid, stat_loc, options) \ + INLINE_SYSCALL (waitpid, 3, pid, stat_loc, options) +#else +# define waitpid_not_cancel(pid, stat_loc, options) \ + INLINE_SYSCALL (wait4, 4, pid, stat_loc, options, NULL) +#endif + +/* Uncancelable pause. */ +#ifdef __NR_pause +# define pause_not_cancel() \ + INLINE_SYSCALL (pause, 0) +#else +# define pause_not_cancel() \ + __pause_nocancel () +#endif + +/* Uncancelable nanosleep. */ +#ifdef __NR_nanosleep +# define nanosleep_not_cancel(requested_time, remaining) \ + INLINE_SYSCALL (nanosleep, 2, requested_time, remaining) +#else +# define nanosleep_not_cancel(requested_time, remaining) \ + __nanosleep_nocancel (requested_time, remaining) +#endif + +/* Uncancelable sigsuspend. */ +#define sigsuspend_not_cancel(set) \ + __sigsuspend_nocancel (set) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/open.S b/libpthread/nptl/sysdeps/unix/sysv/linux/open.S new file mode 100644 index 000000000..486686a22 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/open.S @@ -0,0 +1,21 @@ +#include <sysdep-cancel.h> + +/* +extern int __open_nocancel (const char *, int, ...) attribute_hidden; +*/ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +PSEUDO (__libc_open, open, 3) +ret +PSEUDO_END(__libc_open) + +libc_hidden_def (__open_nocancel) +libc_hidden_def (__libc_open) +weak_alias (__libc_open, __open) +libc_hidden_weak (__open) +weak_alias (__libc_open, open) +libc_hidden_weak (open) + + + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pause.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pause.S new file mode 100644 index 000000000..3841018a8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pause.S @@ -0,0 +1,7 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_pause, pause, 0) +ret +PSEUDO_END (__libc_pause) +libc_hidden_def (__libc_pause) +weak_alias (__libc_pause, pause) +libc_hidden_weak (pause) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/Makefile new file mode 100644 index 000000000..e98c9bd86 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/Makefile @@ -0,0 +1,2 @@ +# pull in __syscall_error routine +libpthread-routines += sysdep diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h new file mode 100644 index 000000000..c0b59c336 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h @@ -0,0 +1,221 @@ +/* Machine-specific pthread type layouts. PowerPC version. + Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras <paulus@au.ibm.com>, 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. */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#include <bits/wordsize.h> + +#if __WORDSIZE == 64 +# define __SIZEOF_PTHREAD_ATTR_T 56 +# define __SIZEOF_PTHREAD_MUTEX_T 40 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 56 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 32 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#else +# define __SIZEOF_PTHREAD_ATTR_T 36 +# define __SIZEOF_PTHREAD_MUTEX_T 24 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 32 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 20 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#endif + + +/* Thread identifiers. The structure of the attribute type is + deliberately not exposed. */ +typedef unsigned long int pthread_t; + + +typedef union +{ + char __size[__SIZEOF_PTHREAD_ATTR_T]; + long int __align; +} pthread_attr_t; + + +#if __WORDSIZE == 64 +typedef struct __pthread_internal_list +{ + struct __pthread_internal_list *__prev; + struct __pthread_internal_list *__next; +} __pthread_list_t; +#else +typedef struct __pthread_internal_slist +{ + struct __pthread_internal_slist *__next; +} __pthread_slist_t; +#endif + + +/* Data structures for mutex handling. The structure of the attribute + type is deliberately not exposed. */ +typedef union +{ + struct __pthread_mutex_s + { + int __lock; + unsigned int __count; + int __owner; +#if __WORDSIZE == 64 + unsigned int __nusers; +#endif + /* KIND must stay at this position in the structure to maintain + binary compatibility. */ + int __kind; +#if __WORDSIZE == 64 + int __spins; + __pthread_list_t __list; +# define __PTHREAD_MUTEX_HAVE_PREV 1 +#else + unsigned int __nusers; + __extension__ union + { + int __spins; + __pthread_slist_t __list; + }; +#endif + } __data; + char __size[__SIZEOF_PTHREAD_MUTEX_T]; + long int __align; +} pthread_mutex_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; + int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling. The structure of + the attribute type is deliberately not exposed. */ +typedef union +{ + struct + { + int __lock; + unsigned int __futex; + __extension__ unsigned long long int __total_seq; + __extension__ unsigned long long int __wakeup_seq; + __extension__ unsigned long long int __woken_seq; + void *__mutex; + unsigned int __nwaiters; + unsigned int __broadcast_seq; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_CONDATTR_T]; + int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling. The + structure of the attribute type is deliberately not exposed. */ +typedef union +{ +# if __WORDSIZE == 64 + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + int __writer; + int __shared; + unsigned long int __pad1; + unsigned long int __pad2; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned int __flags; + } __data; +# else + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + unsigned char __pad1; + unsigned char __pad2; + unsigned char __shared; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; + int __writer; + } __data; +# endif + char __size[__SIZEOF_PTHREAD_RWLOCK_T]; + long int __align; +} pthread_rwlock_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; + long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type. The structure of the type is + deliberately not exposed. */ +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIER_T]; + long int __align; +} pthread_barrier_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; + int __align; +} pthread_barrierattr_t; +#endif + + +#endif /* bits/pthreadtypes.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h new file mode 100644 index 000000000..c7f121ba5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h @@ -0,0 +1,41 @@ +/* Machine-specific POSIX semaphore type layouts. PowerPC version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras <paulus@au.ibm.com>, 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. */ + +#ifndef _SEMAPHORE_H +# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." +#endif + +#include <bits/wordsize.h> + +#if __WORDSIZE == 64 +# define __SIZEOF_SEM_T 32 +#else +# define __SIZEOF_SEM_T 16 +#endif + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + + +typedef union +{ + char __size[__SIZEOF_SEM_T]; + long int __align; +} sem_t; diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/createthread.c b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/createthread.c new file mode 100644 index 000000000..e811ad74e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/createthread.c @@ -0,0 +1,25 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras <paulus@au.ibm.com>. + + 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. */ + +/* Value passed to 'clone' for initialization of the thread register. */ +#define TLS_VALUE ((void *) (pd) \ + + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE) + +/* Get the real implementation. */ +#include <nptl/sysdeps/pthread/createthread.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/fork.c new file mode 100644 index 000000000..06b7e1c69 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/fork.c @@ -0,0 +1 @@ +#include "../i386/fork.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h new file mode 100644 index 000000000..66c02cbbd --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h @@ -0,0 +1,314 @@ +/* Copyright (C) 2003, 2004, 2006-2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras <paulus@au.ibm.com>, 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. */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H 1 + +#include <time.h> +#include <sys/param.h> +#include <bits/pthreadtypes.h> +#include <atomic.h> +#include <kernel-features.h> + +#ifndef __NR_futex +# define __NR_futex 221 +#endif +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 +#define FUTEX_WAKE_OP 5 +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 +#define FUTEX_WAIT_BITSET 9 +#define FUTEX_WAKE_BITSET 10 +#define FUTEX_PRIVATE_FLAG 128 +#define FUTEX_CLOCK_REALTIME 256 + +#define FUTEX_BITSET_MATCH_ANY 0xffffffff + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \ + & THREAD_GETMEM (THREAD_SELF, header.private_futex)))) +# endif +#endif + +#define lll_futex_wait(futexp, val, private) \ + lll_futex_timed_wait (futexp, val, NULL, private) + +#define lll_futex_timed_wait(futexp, val, timespec, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAIT, private), \ + (val), (timespec)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \ + }) + +#define lll_futex_wake(futexp, nr, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAKE, private), \ + (nr), 0); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \ + }) + +#define lll_robust_dead(futexv, private) \ + do \ + { \ + INTERNAL_SYSCALL_DECL (__err); \ + int *__futexp = &(futexv); \ + \ + atomic_or (__futexp, FUTEX_OWNER_DIED); \ + INTERNAL_SYSCALL (futex, __err, 4, __futexp, \ + __lll_private_flag (FUTEX_WAKE, private), 1, 0); \ + } \ + while (0) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_CMP_REQUEUE, private),\ + (nr_wake), (nr_move), (mutex), (val)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_WAKE_OP, private), \ + (nr_wake), (nr_wake2), (futexp2), \ + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + + +#ifdef UP +# define __lll_acq_instr "" +# define __lll_rel_instr "" +#else +# define __lll_acq_instr "isync" +# ifdef _ARCH_PWR4 +/* + * Newer powerpc64 processors support the new "light weight" sync (lwsync) + * So if the build is using -mcpu=[power4,power5,power5+,970] we can + * safely use lwsync. + */ +# define __lll_rel_instr "lwsync" +# else +/* + * Older powerpc32 processors don't support the new "light weight" + * sync (lwsync). So the only safe option is to use normal sync + * for all powerpc32 applications. + */ +# define __lll_rel_instr "sync" +# endif +#endif + +/* Set *futex to ID if it is 0, atomically. Returns the old value */ +#define __lll_robust_trylock(futex, id) \ + ({ int __val; \ + __asm __volatile ("1: lwarx %0,0,%2" MUTEX_HINT_ACQ "\n" \ + " cmpwi 0,%0,0\n" \ + " bne 2f\n" \ + " stwcx. %3,0,%2\n" \ + " bne- 1b\n" \ + "2: " __lll_acq_instr \ + : "=&r" (__val), "=m" (*futex) \ + : "r" (futex), "r" (id), "m" (*futex) \ + : "cr0", "memory"); \ + __val; \ + }) + +#define lll_robust_trylock(lock, id) __lll_robust_trylock (&(lock), id) + +/* Set *futex to 1 if it is 0, atomically. Returns the old value */ +#define __lll_trylock(futex) __lll_robust_trylock (futex, 1) + +#define lll_trylock(lock) __lll_trylock (&(lock)) + +/* Set *futex to 2 if it is 0, atomically. Returns the old value */ +#define __lll_cond_trylock(futex) __lll_robust_trylock (futex, 2) + +#define lll_cond_trylock(lock) __lll_cond_trylock (&(lock)) + + +extern void __lll_lock_wait_private (int *futex) attribute_hidden; +extern void __lll_lock_wait (int *futex, int private) attribute_hidden; +extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden; + +#define lll_lock(lock, private) \ + (void) ({ \ + int *__futex = &(lock); \ + if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex, 1, 0),\ + 0) != 0) \ + { \ + if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \ + __lll_lock_wait_private (__futex); \ + else \ + __lll_lock_wait (__futex, private); \ + } \ + }) + +#define lll_robust_lock(lock, id, private) \ + ({ \ + int *__futex = &(lock); \ + int __val = 0; \ + if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \ + 0), 0)) \ + __val = __lll_robust_lock_wait (__futex, private); \ + __val; \ + }) + +#define lll_cond_lock(lock, private) \ + (void) ({ \ + int *__futex = &(lock); \ + if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex, 2, 0),\ + 0) != 0) \ + __lll_lock_wait (__futex, private); \ + }) + +#define lll_robust_cond_lock(lock, id, private) \ + ({ \ + int *__futex = &(lock); \ + int __val = 0; \ + int __id = id | FUTEX_WAITERS; \ + if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, __id,\ + 0), 0)) \ + __val = __lll_robust_lock_wait (__futex, private); \ + __val; \ + }) + + +extern int __lll_timedlock_wait + (int *futex, const struct timespec *, int private) attribute_hidden; +extern int __lll_robust_timedlock_wait + (int *futex, const struct timespec *, int private) attribute_hidden; + +#define lll_timedlock(lock, abstime, private) \ + ({ \ + int *__futex = &(lock); \ + int __val = 0; \ + if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex, 1, 0),\ + 0) != 0) \ + __val = __lll_timedlock_wait (__futex, abstime, private); \ + __val; \ + }) + +#define lll_robust_timedlock(lock, abstime, id, private) \ + ({ \ + int *__futex = &(lock); \ + int __val = 0; \ + if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \ + 0), 0)) \ + __val = __lll_robust_timedlock_wait (__futex, abstime, private); \ + __val; \ + }) + +#define lll_unlock(lock, private) \ + ((void) ({ \ + int *__futex = &(lock); \ + int __val = atomic_exchange_rel (__futex, 0); \ + if (__builtin_expect (__val > 1, 0)) \ + lll_futex_wake (__futex, 1, private); \ + })) + +#define lll_robust_unlock(lock, private) \ + ((void) ({ \ + int *__futex = &(lock); \ + int __val = atomic_exchange_rel (__futex, 0); \ + if (__builtin_expect (__val & FUTEX_WAITERS, 0)) \ + lll_futex_wake (__futex, 1, private); \ + })) + +#define lll_islocked(futex) \ + (futex != 0) + + +/* Initializers for lock. */ +#define LLL_LOCK_INITIALIZER (0) +#define LLL_LOCK_INITIALIZER_LOCKED (1) + +/* The states of a lock are: + 0 - untaken + 1 - taken by one user + >1 - taken by more users */ + +/* The kernel notifies a process which uses CLONE_CLEARTID via futex + wakeup when the clone terminates. The memory location contains the + thread ID while the clone is running and is reset to zero + afterwards. */ +#define lll_wait_tid(tid) \ + do { \ + __typeof (tid) __tid; \ + while ((__tid = (tid)) != 0) \ + lll_futex_wait (&(tid), __tid, LLL_SHARED); \ + } while (0) + +extern int __lll_timedwait_tid (int *, const struct timespec *) + attribute_hidden; + +#define lll_timedwait_tid(tid, abstime) \ + ({ \ + int __res = 0; \ + if ((tid) != 0) \ + __res = __lll_timedwait_tid (&(tid), (abstime)); \ + __res; \ + }) + +#endif /* lowlevellock.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/not-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/not-cancel.h new file mode 100644 index 000000000..acf1a617e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/not-cancel.h @@ -0,0 +1 @@ +#include "../i386/not-cancel.h" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S new file mode 100644 index 000000000..675a997e9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S @@ -0,0 +1,9 @@ +/* We want an #include_next, but we are the main source file. + So, #include ourselves and in that incarnation we can use #include_next. */ +#ifndef INCLUDED_SELF +# define INCLUDED_SELF +# include <clone.S> +#else +# define RESET_PID +# include_next <clone.S> +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/pt-vfork.S new file mode 100644 index 000000000..61651fd97 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/pt-vfork.S @@ -0,0 +1,49 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#define _ERRNO_H 1 +#include <bits/errno.h> +#include <bits/kernel-features.h> +#include <tcb-offsets.h> + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + lwz 0,PID(2) + neg 0,0 + stw 0,PID(2) + + DO_CALL (SYS_ify (vfork)) + + cmpwi 1,3,0 + beqlr- 1 + + lwz 0,PID(2) + neg 0,0 + stw 0,PID(2) + + PSEUDO_RET + +PSEUDO_END (__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h new file mode 100644 index 000000000..88b24e7d9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h @@ -0,0 +1,119 @@ +/* Cancellable system call stubs. Linux/PowerPC version. + Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Franz Sirl <Franz.Sirl-kernel@lauterbach.com>, 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., 51 Franklin Street, Fifth Floor, Boston MA + 02110-1301 USA. */ + +#include <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <nptl/pthreadP.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .section ".text"; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + bne- .Lpseudo_cancel; \ + .type __##syscall_name##_nocancel,@function; \ + .globl __##syscall_name##_nocancel; \ + __##syscall_name##_nocancel: \ + DO_CALL (SYS_ify (syscall_name)); \ + PSEUDO_RET; \ + .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ + .Lpseudo_cancel: \ + stwu 1,-48(1); \ + cfi_adjust_cfa_offset (48); \ + mflr 9; \ + stw 9,52(1); \ + cfi_offset (lr, 4); \ + DOCARGS_##args; /* save syscall args around CENABLE. */ \ + CENABLE; \ + stw 3,16(1); /* store CENABLE return value (MASK). */ \ + UNDOCARGS_##args; /* restore syscall args. */ \ + DO_CALL (SYS_ify (syscall_name)); \ + mfcr 0; /* save CR/R3 around CDISABLE. */ \ + stw 3,8(1); \ + stw 0,12(1); \ + lwz 3,16(1); /* pass MASK to CDISABLE. */ \ + CDISABLE; \ + lwz 4,52(1); \ + lwz 0,12(1); /* restore CR/R3. */ \ + lwz 3,8(1); \ + mtlr 4; \ + mtcr 0; \ + addi 1,1,48; + +# define DOCARGS_0 +# define UNDOCARGS_0 + +# define DOCARGS_1 stw 3,20(1); DOCARGS_0 +# define UNDOCARGS_1 lwz 3,20(1); UNDOCARGS_0 + +# define DOCARGS_2 stw 4,24(1); DOCARGS_1 +# define UNDOCARGS_2 lwz 4,24(1); UNDOCARGS_1 + +# define DOCARGS_3 stw 5,28(1); DOCARGS_2 +# define UNDOCARGS_3 lwz 5,28(1); UNDOCARGS_2 + +# define DOCARGS_4 stw 6,32(1); DOCARGS_3 +# define UNDOCARGS_4 lwz 6,32(1); UNDOCARGS_3 + +# define DOCARGS_5 stw 7,36(1); DOCARGS_4 +# define UNDOCARGS_5 lwz 7,36(1); UNDOCARGS_4 + +# define DOCARGS_6 stw 8,40(1); DOCARGS_5 +# define UNDOCARGS_6 lwz 8,40(1); UNDOCARGS_5 + +# ifdef IS_IN_libpthread +# define CENABLE bl __pthread_enable_asynccancel@local +# define CDISABLE bl __pthread_disable_asynccancel@local +# elif !defined NOT_IN_libc +# define CENABLE bl __libc_enable_asynccancel@local +# define CDISABLE bl __libc_disable_asynccancel@local +# elif defined IS_IN_librt +# define CENABLE bl __librt_enable_asynccancel@local +# define CDISABLE bl __librt_disable_asynccancel@local +# else +# error Unsupported library +# endif + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P \ + lwz 10,MULTIPLE_THREADS_OFFSET(2); \ + cmpwi 10,0 +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S new file mode 100644 index 000000000..eed2a8f1a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S @@ -0,0 +1,57 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#define _ERRNO_H 1 +#include <bits/errno.h> +#include <bits/kernel-features.h> +#include <tcb-offsets.h> + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + lwz 0,PID(2) + cmpwi 0,0,0 + neg 0,0 + bne- 0,1f + lis 0,0x8000 +1: stw 0,PID(2) + + DO_CALL (SYS_ify (vfork)) + + cmpwi 1,3,0 + beqlr- 1 + + lwz 0,PID(2) + /* Cannot use clrlwi. here, because cr0 needs to be preserved + until PSEUDO_RET. */ + clrlwi 4,0,1 + cmpwi 1,4,0 + beq- 1,1f + neg 4,0 +1: stw 4,PID(2) + + PSEUDO_RET + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S new file mode 100644 index 000000000..675a997e9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S @@ -0,0 +1,9 @@ +/* We want an #include_next, but we are the main source file. + So, #include ourselves and in that incarnation we can use #include_next. */ +#ifndef INCLUDED_SELF +# define INCLUDED_SELF +# include <clone.S> +#else +# define RESET_PID +# include_next <clone.S> +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/pt-vfork.S new file mode 100644 index 000000000..e5b7b535c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/pt-vfork.S @@ -0,0 +1,49 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#define _ERRNO_H 1 +#include <bits/errno.h> +#include <bits/kernel-features.h> +#include <tcb-offsets.h> + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + lwz 0,PID(13) + neg 0,0 + stw 0,PID(13) + + DO_CALL (SYS_ify (vfork)) + + cmpwi 1,3,0 + beqlr- 1 + + lwz 0,PID(13) + neg 0,0 + stw 0,PID(13) + + PSEUDO_RET + +PSEUDO_END (__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h new file mode 100644 index 000000000..707765ab5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h @@ -0,0 +1,125 @@ +/* Cancellable system call stubs. Linux/PowerPC64 version. + Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Franz Sirl <Franz.Sirl-kernel@lauterbach.com>, 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., 51 Franklin Street, Fifth Floor, Boston MA + 02110-1301 USA. */ + +#include <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <nptl/pthreadP.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define DASHDASHPFX(str) .__##str +# else +# define DASHDASHPFX(str) __##str +# endif + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .section ".text"; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + bne- .Lpseudo_cancel; \ + .type DASHDASHPFX(syscall_name##_nocancel),@function; \ + .globl DASHDASHPFX(syscall_name##_nocancel); \ + DASHDASHPFX(syscall_name##_nocancel): \ + DO_CALL (SYS_ify (syscall_name)); \ + PSEUDO_RET; \ + .size DASHDASHPFX(syscall_name##_nocancel),.-DASHDASHPFX(syscall_name##_nocancel); \ + .Lpseudo_cancel: \ + stdu 1,-128(1); \ + cfi_adjust_cfa_offset (128); \ + mflr 9; \ + std 9,128+16(1); \ + cfi_offset (lr, 16); \ + DOCARGS_##args; /* save syscall args around CENABLE. */ \ + CENABLE; \ + std 3,72(1); /* store CENABLE return value (MASK). */ \ + UNDOCARGS_##args; /* restore syscall args. */ \ + DO_CALL (SYS_ify (syscall_name)); \ + mfcr 0; /* save CR/R3 around CDISABLE. */ \ + std 3,64(1); \ + std 0,8(1); \ + ld 3,72(1); /* pass MASK to CDISABLE. */ \ + CDISABLE; \ + ld 9,128+16(1); \ + ld 0,8(1); /* restore CR/R3. */ \ + ld 3,64(1); \ + mtlr 9; \ + mtcr 0; \ + addi 1,1,128; + +# define DOCARGS_0 +# define UNDOCARGS_0 + +# define DOCARGS_1 std 3,80(1); DOCARGS_0 +# define UNDOCARGS_1 ld 3,80(1); UNDOCARGS_0 + +# define DOCARGS_2 std 4,88(1); DOCARGS_1 +# define UNDOCARGS_2 ld 4,88(1); UNDOCARGS_1 + +# define DOCARGS_3 std 5,96(1); DOCARGS_2 +# define UNDOCARGS_3 ld 5,96(1); UNDOCARGS_2 + +# define DOCARGS_4 std 6,104(1); DOCARGS_3 +# define UNDOCARGS_4 ld 6,104(1); UNDOCARGS_3 + +# define DOCARGS_5 std 7,112(1); DOCARGS_4 +# define UNDOCARGS_5 ld 7,112(1); UNDOCARGS_4 + +# define DOCARGS_6 std 8,120(1); DOCARGS_5 +# define UNDOCARGS_6 ld 8,120(1); UNDOCARGS_5 + +# ifdef IS_IN_libpthread +# define CENABLE bl JUMPTARGET(__pthread_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__pthread_disable_asynccancel) +# elif !defined NOT_IN_libc +# define CENABLE bl JUMPTARGET(__libc_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__libc_disable_asynccancel) +# elif defined IS_IN_librt +# define CENABLE bl JUMPTARGET(__librt_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__librt_disable_asynccancel) +# else +# error Unsupported library +# endif + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P \ + lwz 10,MULTIPLE_THREADS_OFFSET(13); \ + cmpwi 10,0 +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_create.c b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_create.c new file mode 100644 index 000000000..172223af3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_create.c @@ -0,0 +1 @@ +#include "../x86_64/timer_create.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_delete.c b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_delete.c new file mode 100644 index 000000000..537516e0a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_delete.c @@ -0,0 +1 @@ +#include "../x86_64/timer_delete.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_getoverr.c b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_getoverr.c new file mode 100644 index 000000000..3f21a73c9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_getoverr.c @@ -0,0 +1 @@ +#include "../x86_64/timer_getoverr.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_gettime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_gettime.c new file mode 100644 index 000000000..a50143adc --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_gettime.c @@ -0,0 +1 @@ +#include "../x86_64/timer_gettime.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_settime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_settime.c new file mode 100644 index 000000000..37baeffac --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_settime.c @@ -0,0 +1 @@ +#include "../x86_64/timer_settime.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S new file mode 100644 index 000000000..26885bb95 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S @@ -0,0 +1,55 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#define _ERRNO_H 1 +#include <bits/errno.h> +#include <bits/kernel-features.h> +#include <tcb-offsets.h> + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + lwz 0,PID(13) + cmpwi 0,0,0 + neg 0,0 + bne- 0,1f + lis 0,0x8000 +1: stw 0,PID(13) + + DO_CALL (SYS_ify (vfork)) + + cmpwi 1,3,0 + beqlr- 1 + + lwz 0,PID(13) + clrlwi 4,0,1 + cmpwi 1,4,0 + beq- 1,1f + neg 4,0 +1: stw 4,PID(13) + + PSEUDO_RET + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c new file mode 100644 index 000000000..b6d6b3d55 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c @@ -0,0 +1,37 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <setjmp.h> +#include <stdlib.h> +#include <bits/wordsize.h> +#include "pthreadP.h" + +void +__vmx_longjmp (jmp_buf env, int val) +{ + __libc_longjmp (env, val); +} + +void +__vmx_siglongjmp (jmp_buf env, int val) +{ + __libc_siglongjmp (env, val); +} +weak_alias(__vmx_longjmp, longjmp) +weak_alias(__vmx_siglongjmp, siglongjmp) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c new file mode 100644 index 000000000..5f4b7e9c1 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c @@ -0,0 +1,101 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras <paulus@au.ibm.com>, 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 <lowlevellock.h> + + +unsigned long int __fork_generation attribute_hidden; + + +static void +clear_once_control (void *arg) +{ + pthread_once_t *once_control = (pthread_once_t *) arg; + + *once_control = 0; + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +} + + +int +attribute_hidden +__pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) +{ + for (;;) + { + int oldval; + int newval; + int tmp; + + /* Pseudo code: + newval = __fork_generation | 1; + oldval = *once_control; + if ((oldval & 2) == 0) + *once_control = newval; + Do this atomically. + */ + newval = __fork_generation | 1; + __asm __volatile ("1: lwarx %0,0,%3\n" + " andi. %1,%0,2\n" + " bne 2f\n" + " stwcx. %4,0,%3\n" + " bne 1b\n" + "2: isync" + : "=&r" (oldval), "=&r" (tmp), "=m" (*once_control) + : "r" (once_control), "r" (newval), "m" (*once_control) + : "cr0"); + + /* Check if the initializer has already been done. */ + if ((oldval & 2) != 0) + return 0; + + /* Check if another thread already runs the initializer. */ + if ((oldval & 1) == 0) + break; + + /* Check whether the initializer execution was interrupted by a fork. */ + if (oldval != newval) + break; + + /* Same generation, some other thread was faster. Wait. */ + lll_futex_wait (once_control, oldval, LLL_PRIVATE); + } + + + /* This thread is the first here. Do the initialization. + Register a cleanup handler so that in case the thread gets + interrupted the initialization can be restarted. */ + pthread_cleanup_push (clear_once_control, once_control); + + init_routine (); + + pthread_cleanup_pop (0); + + + /* Add one to *once_control to take the bottom 2 bits from 01 to 10. */ + atomic_increment (once_control); + + /* Wake up all other threads. */ + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); + + return 0; +} +weak_alias (__pthread_once, pthread_once) +strong_alias (__pthread_once, __pthread_once_internal) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_spin_unlock.c b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_spin_unlock.c new file mode 100644 index 000000000..90f2dc67c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_spin_unlock.c @@ -0,0 +1,29 @@ +/* pthread_spin_unlock -- unlock a spin lock. PowerPC version. + Copyright (C) 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 + 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 <lowlevellock.h> + +int +pthread_spin_unlock (pthread_spinlock_t *lock) +{ + __asm __volatile (__lll_rel_instr ::: "memory"); + *lock = 0; + return 0; +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/sem_post.c b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/sem_post.c new file mode 100644 index 000000000..0082c570a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/sem_post.c @@ -0,0 +1,47 @@ +/* sem_post -- post to a POSIX semaphore. Powerpc version. + Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras <paulus@au.ibm.com>, 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 <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <internaltypes.h> +#include <semaphore.h> + +int +__new_sem_post (sem_t *sem) +{ + struct new_sem *isem = (struct new_sem *) sem; + + __asm __volatile (__lll_rel_instr ::: "memory"); + atomic_increment (&isem->value); + __asm __volatile (__lll_acq_instr ::: "memory"); + if (isem->nwaiters > 0) + { + int err = lll_futex_wake (&isem->value, 1, + isem->private ^ FUTEX_PRIVATE_FLAG); + if (__builtin_expect (err, 0) < 0) + { + __set_errno (-err); + return -1; + } + } + return 0; +} +weak_alias(__new_sem_post, sem_post) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-accept.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-accept.S new file mode 100644 index 000000000..24062101d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-accept.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_accept +#error Missing definition of NR_accept needed for cancellation. +#endif +PSEUDO (__libc_accept, accept, 3) +ret +PSEUDO_END(__libc_accept) +libpthread_hidden_def (__libc_accept) +weak_alias (__libc_accept, __accept) +libpthread_hidden_weak (__accept) +weak_alias (__libc_accept, accept) +libpthread_hidden_weak (accept) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-close.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-close.S new file mode 100644 index 000000000..ab32ca598 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-close.S @@ -0,0 +1,9 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_close, close, 1) +ret +PSEUDO_END (__libc_close) +libpthread_hidden_def (__libc_close) +weak_alias (__libc_close, __close) +libpthread_hidden_weak (__close) +weak_alias (__libc_close, close) +libpthread_hidden_weak (close) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-connect.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-connect.S new file mode 100644 index 000000000..b5124f8ec --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-connect.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_connect +#error Missing definition of NR_connect needed for cancellation. +#endif +PSEUDO (__libc_connect, connect, 3) +ret +PSEUDO_END(__libc_connect) +libpthread_hidden_def (__libc_connect) +weak_alias (__libc_connect, __connect) +libpthread_hidden_weak (__connect) +weak_alias (__libc_connect, connect) +libpthread_hidden_weak (connect) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fcntl.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fcntl.c new file mode 100644 index 000000000..0a8fd3cc2 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fcntl.c @@ -0,0 +1 @@ +#include <../../../../../../libc/sysdeps/linux/common/__syscall_fcntl.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fork.c new file mode 100644 index 000000000..3e1b70f86 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fork.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 <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <unistd.h> + +extern int __libc_fork (void); + +pid_t +__fork (void) +{ + return __libc_fork (); +} +strong_alias (__fork, fork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fsync.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fsync.c new file mode 100644 index 000000000..6ec4821c7 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fsync.c @@ -0,0 +1,2 @@ +#include <pthreadP.h> +#include <../../../../../../libc/sysdeps/linux/common/fsync.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-llseek.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-llseek.c new file mode 100644 index 000000000..1d0d57870 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-llseek.c @@ -0,0 +1,3 @@ +#include <pthreadP.h> +#define libc_hidden libpthread_hidden +#include <../../../../../../libc/sysdeps/linux/common/llseek.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-lseek.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-lseek.S new file mode 100644 index 000000000..4db71722a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-lseek.S @@ -0,0 +1,7 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_lseek, lseek, 3) +ret +PSEUDO_END (__libc_lseek) +libpthread_hidden_def (__libc_lseek) +weak_alias (__libc_lseek, lseek) +libpthread_hidden_weak (lseek) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msgrcv.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msgrcv.c new file mode 100644 index 000000000..3bb9d53df --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msgrcv.c @@ -0,0 +1,2 @@ +#define L_msgrcv +#include <../../../../../../libc/misc/sysvipc/msgq.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msgsnd.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msgsnd.c new file mode 100644 index 000000000..1566f65f4 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msgsnd.c @@ -0,0 +1,2 @@ +#define L_msgsnd +#include <../../../../../../libc/misc/sysvipc/msgq.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msync.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msync.S new file mode 100644 index 000000000..640270ad9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msync.S @@ -0,0 +1,7 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_msync, msync, 3) +ret +PSEUDO_END(__libc_msync) +libpthread_hidden_def (__libc_msync) +weak_alias (__libc_msync, msync) +libpthread_hidden_weak (msync) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-nanosleep.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-nanosleep.S new file mode 100644 index 000000000..08d8f0150 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-nanosleep.S @@ -0,0 +1,9 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_nanosleep, nanosleep, 3) +ret +PSEUDO_END (__libc_nanosleep) +libpthread_hidden_def (__libc_nanosleep) +weak_alias (__libc_nanosleep, __nanosleep) +libpthread_hidden_weak (__nanosleep) +weak_alias (__libc_nanosleep, nanosleep) +libpthread_hidden_weak (nanosleep) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-open.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-open.S new file mode 100644 index 000000000..39ed92cc7 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-open.S @@ -0,0 +1,9 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_open, open, 3) +ret +PSEUDO_END (__libc_open) +libpthread_hidden_def (__libc_open) +weak_alias (__libc_open, __open) +libpthread_hidden_weak (__open) +weak_alias (__libc_open, open) +libpthread_hidden_weak (open) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-open64.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-open64.c new file mode 100644 index 000000000..2029539a7 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-open64.c @@ -0,0 +1 @@ +#include <../../../../../../libc/sysdeps/linux/common/open64.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-pause.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-pause.S new file mode 100644 index 000000000..c6cb57180 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-pause.S @@ -0,0 +1,7 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_pause, pause, 0) +ret +PSEUDO_END (__libc_pause) +libpthread_hidden_def (__libc_pause) +weak_alias (__libc_pause, pause) +libpthread_hidden_weak (pause) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-pread_pwrite.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-pread_pwrite.c new file mode 100644 index 000000000..f32c0a670 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-pread_pwrite.c @@ -0,0 +1 @@ +#include "pread_write.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-raise.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-raise.c new file mode 100644 index 000000000..d256ebcb0 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-raise.c @@ -0,0 +1,52 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <signal.h> +#include <sysdep.h> +#include <tls.h> +#include <bits/kernel-features.h> + + +int +raise ( + int sig) +{ +#if __ASSUME_TGKILL || defined __NR_tgkill + /* raise is an async-safe function. It could be called while the + fork function temporarily invalidated the PID field. Adjust for + that. */ + pid_t pid = THREAD_GETMEM (THREAD_SELF, pid); + if (__builtin_expect (pid < 0, 0)) + pid = -pid; +#endif + +#if __ASSUME_TGKILL + return INLINE_SYSCALL (tgkill, 3, pid, THREAD_GETMEM (THREAD_SELF, tid), + sig); +#else +# ifdef __NR_tgkill + int res = INLINE_SYSCALL (tgkill, 3, pid, THREAD_GETMEM (THREAD_SELF, tid), + sig); + if (res != -1 || errno != ENOSYS) + return res; +# endif + return INLINE_SYSCALL (tkill, 2, THREAD_GETMEM (THREAD_SELF, tid), sig); +#endif +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-read.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-read.S new file mode 100644 index 000000000..623ba27a8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-read.S @@ -0,0 +1,9 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_read, read, 3) +ret +PSEUDO_END (__libc_read) +libpthread_hidden_def (__libc_read) +weak_alias (__libc_read, __read) +libpthread_hidden_weak (__read) +weak_alias (__libc_read, read) +libpthread_hidden_weak (read) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recv.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recv.S new file mode 100644 index 000000000..6d2e3c2d6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recv.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_recv +#error Missing definition of NR_recv needed for cancellation. +#endif +PSEUDO (__libc_recv, recv, 4) +ret +PSEUDO_END(__libc_recv) +libpthread_hidden_def (__libc_recv) +weak_alias (__libc_recv, __recv) +libpthread_hidden_weak (__recv) +weak_alias (__libc_recv, recv) +libpthread_hidden_weak (recv) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recvfrom.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recvfrom.S new file mode 100644 index 000000000..96aeeaa3d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recvfrom.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_recvfrom +#error Missing definition of NR_recvfrom needed for cancellation. +#endif +PSEUDO (__libc_recvfrom, recvfrom, 6) +ret +PSEUDO_END(__libc_recvfrom) +libpthread_hidden_def (__libc_recvfrom) +weak_alias (__libc_recvfrom, __recvfrom) +libpthread_hidden_weak (__recvfrom) +weak_alias (__libc_recvfrom, recvfrom) +libpthread_hidden_weak (recvfrom) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recvmsg.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recvmsg.S new file mode 100644 index 000000000..f7161e47c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recvmsg.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_recvmsg +#error Missing definition of NR_recvmsg needed for cancellation. +#endif +PSEUDO (__libc_recvmsg, recvmsg, 3) +ret +PSEUDO_END(__libc_recvmsg) +libpthread_hidden_def (__libc_recvmsg) +weak_alias (__libc_recvmsg, __recvmsg) +libpthread_hidden_weak (__recvmsg) +weak_alias (__libc_recvmsg, recvmsg) +libpthread_hidden_weak (recvmsg) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-send.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-send.S new file mode 100644 index 000000000..76bed39ec --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-send.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_send +#error Missing definition of NR_send needed for cancellation. +#endif +PSEUDO (__libc_send, send, 4) +ret +PSEUDO_END (__libc_send) +libpthread_hidden_def (__libc_send) +weak_alias (__libc_send, __send) +libpthread_hidden_weak (__send) +weak_alias (__libc_send, send) +libpthread_hidden_weak (send) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sendmsg.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sendmsg.S new file mode 100644 index 000000000..d17096eae --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sendmsg.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_sendmsg +#error Missing definition of NR_sendmsg needed for cancellation. +#endif +PSEUDO (__libc_sendmsg, sendmsg, 3) +ret +PSEUDO_END(__libc_sendmsg) +libpthread_hidden_def (__libc_sendmsg) +weak_alias (__libc_sendmsg, __sendmsg) +libpthread_hidden_weak (__sendmsg) +weak_alias (__libc_sendmsg, sendmsg) +libpthread_hidden_weak (sendmsg) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sendto.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sendto.S new file mode 100644 index 000000000..d07a71f8a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sendto.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_sendto +#error Missing definition of NR_sendto needed for cancellation. +#endif +PSEUDO (__libc_sendto, sendto, 6) +ret +PSEUDO_END(__libc_sendto) +libpthread_hidden_def (__libc_sendto) +weak_alias (__libc_sendto, __sendto) +libpthread_hidden_weak (__sendto) +weak_alias (__libc_sendto, sendto) +libpthread_hidden_weak (sendto) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sigwait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sigwait.c new file mode 100644 index 000000000..bde0a9292 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sigwait.c @@ -0,0 +1,2 @@ +#include <pthreadP.h> +#include "../../../../../../libc/signal/sigwait.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sleep.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sleep.c new file mode 100644 index 000000000..9e948adce --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sleep.c @@ -0,0 +1,2 @@ +#include <pthreadP.h> +#include <../../../../../../libc/unistd/sleep.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-tcdrain.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-tcdrain.c new file mode 100644 index 000000000..07c1f8233 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-tcdrain.c @@ -0,0 +1 @@ +#include <../../../../../../libc/termios/tcdrain.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-wait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-wait.c new file mode 100644 index 000000000..a05c3eb49 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-wait.c @@ -0,0 +1,2 @@ +#include <pthreadP.h> +#include <../../../../../../libc/sysdeps/linux/common/wait.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-waitpid.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-waitpid.c new file mode 100644 index 000000000..8461c3ff2 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-waitpid.c @@ -0,0 +1 @@ +#include <../../../../../../libc/sysdeps/linux/common/waitpid.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-write.S b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-write.S new file mode 100644 index 000000000..6bc666779 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-write.S @@ -0,0 +1,9 @@ +#include <sysdep-cancel.h> +PSEUDO (__libc_write, write, 3) +ret +PSEUDO_END (__libc_write) +libpthread_hidden_def (__libc_write) +weak_alias (__libc_write, __write) +libpthread_hidden_weak (__write) +weak_alias (__libc_write, write) +libpthread_hidden_weak (write) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym new file mode 100644 index 000000000..46fbd0de7 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym @@ -0,0 +1,8 @@ +#include <pthreadP.h> + +-- These PI macros are used by assembly code. + +MUTEX_KIND offsetof (pthread_mutex_t, __data.__kind) +ROBUST_BIT PTHREAD_MUTEX_ROBUST_NORMAL_NP +PI_BIT PTHREAD_MUTEX_PRIO_INHERIT_NP +PS_BIT PTHREAD_MUTEX_PSHARED_BIT diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c new file mode 100644 index 000000000..2ec2f3d74 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c @@ -0,0 +1,54 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 <assert.h> +#include <errno.h> +#include <pthreadP.h> +#include <string.h> +#include <sysdep.h> +#include <sys/types.h> + + +int +pthread_attr_getaffinity_np(const pthread_attr_t *attr, size_t cpusetsize, + cpu_set_t *cpuset) +{ + const struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (const struct pthread_attr *) attr; + + if (iattr->cpuset != NULL) + { + /* Check whether there are any bits set beyond the limits + the user requested. */ + for (size_t cnt = cpusetsize; cnt < iattr->cpusetsize; ++cnt) + if (((char *) iattr->cpuset)[cnt] != 0) + return EINVAL; + + void *p = mempcpy (cpuset, iattr->cpuset, iattr->cpusetsize); + if (cpusetsize > iattr->cpusetsize) + memset (p, '\0', cpusetsize - iattr->cpusetsize); + } + else + /* We have no information. */ + memset (cpuset, -1, cpusetsize); + + return 0; +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c new file mode 100644 index 000000000..609ee2ad1 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c @@ -0,0 +1,80 @@ +/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdlib.h> +#include <string.h> +#include <pthreadP.h> + + +/* Defined in pthread_setaffinity.c. */ +extern size_t __kernel_cpumask_size attribute_hidden; +extern int __determine_cpumask_size (pid_t tid); +libpthread_hidden_proto(__determine_cpumask_size) + +int +pthread_attr_setaffinity_np (pthread_attr_t *attr, size_t cpusetsize, + const cpu_set_t *cpuset) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + if (cpuset == NULL || cpusetsize == 0) + { + free (iattr->cpuset); + iattr->cpuset = NULL; + iattr->cpusetsize = 0; + } + else + { + if (__kernel_cpumask_size == 0) + { + int res = __determine_cpumask_size (THREAD_SELF->tid); + if (res != 0) + /* Some serious problem. */ + return res; + } + + /* Check whether the new bitmask has any bit set beyond the + last one the kernel accepts. */ + for (size_t cnt = __kernel_cpumask_size; cnt < cpusetsize; ++cnt) + if (((char *) cpuset)[cnt] != '\0') + /* Found a nonzero byte. This means the user request cannot be + fulfilled. */ + return EINVAL; + + if (iattr->cpusetsize != cpusetsize) + { + void *newp = (cpu_set_t *) realloc (iattr->cpuset, cpusetsize); + if (newp == NULL) + return ENOMEM; + + iattr->cpuset = newp; + iattr->cpusetsize = cpusetsize; + } + + memcpy (iattr->cpuset, cpuset, cpusetsize); + } + + return 0; +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c new file mode 100644 index 000000000..affcc6a65 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c @@ -0,0 +1,46 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 <errno.h> +#include <limits.h> +#include <pthreadP.h> +#include <string.h> +#include <sysdep.h> +#include <sys/param.h> +#include <sys/types.h> + + +int +__pthread_getaffinity_np (pthread_t th, size_t cpusetsize, cpu_set_t *cpuset) +{ + const struct pthread *pd = (const struct pthread *) th; + + INTERNAL_SYSCALL_DECL (err); + int res = INTERNAL_SYSCALL (sched_getaffinity, err, 3, pd->tid, + MIN (INT_MAX, cpusetsize), cpuset); + if (INTERNAL_SYSCALL_ERROR_P (res, err)) + return INTERNAL_SYSCALL_ERRNO (res, err); + + /* Clean the rest of the memory the kernel didn't do. */ + memset ((char *) cpuset + res, '\0', cpusetsize - res); + + return 0; +} +strong_alias(__pthread_getaffinity_np, pthread_getaffinity_np) + diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c new file mode 100644 index 000000000..9e28f69fd --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/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 <errno.h> +#include <pthreadP.h> +#include <sys/time.h> +#include <tls.h> + + +int +pthread_getcpuclockid ( + 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/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_kill.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_kill.c new file mode 100644 index 000000000..3a70c3764 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_kill.c @@ -0,0 +1,78 @@ +/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <signal.h> +#include <pthreadP.h> +#include <tls.h> +#include <sysdep.h> +#include <bits/kernel-features.h> + + +int +__pthread_kill ( + pthread_t threadid, + int signo) +{ + struct pthread *pd = (struct pthread *) threadid; + + /* Make sure the descriptor is valid. */ + if (DEBUGGING_P && INVALID_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + + /* Force load of pd->tid into local variable or register. Otherwise + if a thread exits between ESRCH test and tgkill, we might return + EINVAL, because pd->tid would be cleared by the kernel. */ + pid_t tid = atomic_forced_read (pd->tid); + if (__builtin_expect (tid <= 0, 0)) + /* Not a valid thread handle. */ + return ESRCH; + + /* Disallow sending the signal we use for cancellation, timers, for + for the setxid implementation. */ + if (signo == SIGCANCEL || signo == SIGTIMER || signo == SIGSETXID) + return EINVAL; + + /* We have a special syscall to do the work. */ + INTERNAL_SYSCALL_DECL (err); + + /* One comment: The PID field in the TCB can temporarily be changed + (in fork). But this must not affect this code here. Since this + function would have to be called while the thread is executing + fork, it would have to happen in a signal handler. But this is + no allowed, pthread_kill is not guaranteed to be async-safe. */ + int val; +#if __ASSUME_TGKILL + val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), + tid, signo); +#else +# ifdef __NR_tgkill + val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), + tid, signo); + if (INTERNAL_SYSCALL_ERROR_P (val, err) + && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS) +# endif + val = INTERNAL_SYSCALL (tkill, err, 2, tid, signo); +#endif + + return (INTERNAL_SYSCALL_ERROR_P (val, err) + ? INTERNAL_SYSCALL_ERRNO (val, err) : 0); +} +strong_alias (__pthread_kill, pthread_kill) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c new file mode 100644 index 000000000..804bfab44 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c @@ -0,0 +1,14 @@ +#include <pthreadP.h> + +#define LLL_MUTEX_LOCK(mutex) \ + lll_cond_lock ((mutex)->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex)) +#define LLL_MUTEX_TRYLOCK(mutex) \ + lll_cond_trylock ((mutex)->__data.__lock) +#define LLL_ROBUST_MUTEX_LOCK(mutex, id) \ + lll_robust_cond_lock ((mutex)->__data.__lock, id, \ + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)) +#define __pthread_mutex_lock __pthread_mutex_cond_lock +#define __pthread_mutex_lock_full __pthread_mutex_cond_lock_full +#define NO_INCR + +#include <pthread_mutex_lock.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c new file mode 100644 index 000000000..467e8ec70 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c @@ -0,0 +1,91 @@ +/* Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 <alloca.h> +#include <errno.h> +#include <pthreadP.h> +#include <sysdep.h> +#include <sys/types.h> + + +size_t __kernel_cpumask_size attribute_hidden; + + +/* Determine the current affinity. As a side affect we learn + about the size of the cpumask_t in the kernel. */ +extern int __determine_cpumask_size (pid_t tid); +libpthread_hidden_proto(__determine_cpumask_size) +int __determine_cpumask_size (pid_t tid) +{ + INTERNAL_SYSCALL_DECL (err); + int res; + + size_t psize = 128; + void *p = alloca (psize); + + while (res = INTERNAL_SYSCALL (sched_getaffinity, err, 3, tid, psize, p), + INTERNAL_SYSCALL_ERROR_P (res, err) + && INTERNAL_SYSCALL_ERRNO (res, err) == EINVAL) + p = extend_alloca (p, psize, 2 * psize); + + if (res == 0 || INTERNAL_SYSCALL_ERROR_P (res, err)) + return INTERNAL_SYSCALL_ERRNO (res, err); + + __kernel_cpumask_size = res; + + return 0; +} +libpthread_hidden_def(__determine_cpumask_size) + +int +pthread_setaffinity_np (pthread_t th, size_t cpusetsize, + const cpu_set_t *cpuset) +{ + const struct pthread *pd = (const struct pthread *) th; + + INTERNAL_SYSCALL_DECL (err); + int res; + + if (__builtin_expect (__kernel_cpumask_size == 0, 0)) + { + res = __determine_cpumask_size (pd->tid); + if (res != 0) + return res; + } + + /* We now know the size of the kernel cpumask_t. Make sure the user + does not request to set a bit beyond that. */ + for (size_t cnt = __kernel_cpumask_size; cnt < cpusetsize; ++cnt) + if (((char *) cpuset)[cnt] != '\0') + /* Found a nonzero byte. This means the user request cannot be + fulfilled. */ + return EINVAL; + + res = INTERNAL_SYSCALL (sched_setaffinity, err, 3, pd->tid, cpusetsize, + cpuset); + +#ifdef RESET_VGETCPU_CACHE + if (!INTERNAL_SYSCALL_ERROR_P (res, err)) + RESET_VGETCPU_CACHE (); +#endif + + return (INTERNAL_SYSCALL_ERROR_P (res, err) + ? INTERNAL_SYSCALL_ERRNO (res, err) + : 0); +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_sigqueue.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_sigqueue.c new file mode 100644 index 000000000..9e49085ce --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_sigqueue.c @@ -0,0 +1,83 @@ +/* Copyright (C) 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2009. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <signal.h> +#include <string.h> +#include <unistd.h> +#include <pthreadP.h> +#include <tls.h> +#include <sysdep.h> +#include <bits/kernel-features.h> + + +int +pthread_sigqueue ( + pthread_t threadid, + int signo, + const union sigval value) +{ +#ifdef __NR_rt_tgsigqueueinfo + struct pthread *pd = (struct pthread *) threadid; + + /* Make sure the descriptor is valid. */ + if (DEBUGGING_P && INVALID_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + + /* Force load of pd->tid into local variable or register. Otherwise + if a thread exits between ESRCH test and tgkill, we might return + EINVAL, because pd->tid would be cleared by the kernel. */ + pid_t tid = atomic_forced_read (pd->tid); + if (__builtin_expect (tid <= 0, 0)) + /* Not a valid thread handle. */ + return ESRCH; + + /* Disallow sending the signal we use for cancellation, timers, for + for the setxid implementation. */ + if (signo == SIGCANCEL || signo == SIGTIMER || signo == SIGSETXID) + return EINVAL; + + /* Set up the siginfo_t structure. */ + siginfo_t info; + memset (&info, '\0', sizeof (siginfo_t)); + info.si_signo = signo; + info.si_code = SI_QUEUE; + info.si_pid = THREAD_GETMEM (THREAD_SELF, pid); + info.si_uid = getuid (); + info.si_value = value; + + /* We have a special syscall to do the work. */ + INTERNAL_SYSCALL_DECL (err); + + /* One comment: The PID field in the TCB can temporarily be changed + (in fork). But this must not affect this code here. Since this + function would have to be called while the thread is executing + fork, it would have to happen in a signal handler. But this is + no allowed, pthread_sigqueue is not guaranteed to be async-safe. */ + int val = INTERNAL_SYSCALL (rt_tgsigqueueinfo, err, 4, + THREAD_GETMEM (THREAD_SELF, pid), + tid, signo, &info); + + return (INTERNAL_SYSCALL_ERROR_P (val, err) + ? INTERNAL_SYSCALL_ERRNO (val, err) : 0); +#else + return ENOSYS; +#endif +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_yield.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_yield.c new file mode 100644 index 000000000..5aecffcf0 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_yield.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthread.h> +#include <sched.h> + + +/* With the 1-on-1 model we implement this function is equivalent to + the 'sched_yield' function. */ +int +pthread_yield (void) +{ + return sched_yield (); +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/raise.c b/libpthread/nptl/sysdeps/unix/sysv/linux/raise.c new file mode 100644 index 000000000..da35cfe9f --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/raise.c @@ -0,0 +1,74 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <limits.h> +#include <signal.h> +#include <sysdep.h> +#include <pthreadP.h> +#include <bits/kernel-features.h> + + +int +raise ( + int sig) +{ + struct pthread *pd = THREAD_SELF; +#if __ASSUME_TGKILL || defined __NR_tgkill + pid_t pid = THREAD_GETMEM (pd, pid); +#endif + pid_t selftid = THREAD_GETMEM (pd, tid); + if (selftid == 0) + { + /* This system call is not supposed to fail. */ +#ifdef INTERNAL_SYSCALL + INTERNAL_SYSCALL_DECL (err); + selftid = INTERNAL_SYSCALL (gettid, err, 0); +#else + selftid = INLINE_SYSCALL (gettid, 0); +#endif + THREAD_SETMEM (pd, tid, selftid); + +#if __ASSUME_TGKILL || defined __NR_tgkill + /* We do not set the PID field in the TID here since we might be + called from a signal handler while the thread executes fork. */ + pid = selftid; +#endif + } +#if __ASSUME_TGKILL || defined __NR_tgkill + else + /* raise is an async-safe function. It could be called while the + fork/vfork function temporarily invalidated the PID field. Adjust for + that. */ + if (__builtin_expect (pid <= 0, 0)) + pid = (pid & INT_MAX) == 0 ? selftid : -pid; +#endif + +#if __ASSUME_TGKILL + return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig); +#else +# ifdef __NR_tgkill + int res = INLINE_SYSCALL (tgkill, 3, pid, selftid, sig); + if (res != -1 || errno != ENOSYS) + return res; +# endif + return INLINE_SYSCALL (tkill, 2, selftid, sig); +#endif +} +libc_hidden_def (raise) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/read.S b/libpthread/nptl/sysdeps/unix/sysv/linux/read.S new file mode 100644 index 000000000..d3adfa84c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/read.S @@ -0,0 +1,19 @@ +#include <sysdep-cancel.h> + +/* +extern int __read_nocancel (int, void *, size_t) attribute_hidden; +*/ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +PSEUDO (__libc_read, read, 3) +ret +PSEUDO_END(__libc_read) + +libc_hidden_def (__read_nocancel) +libc_hidden_def (__libc_read) +weak_alias (__libc_read, __read) +libc_hidden_weak (__read) +weak_alias (__libc_read, read) +libc_hidden_weak (read) + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/recv.S b/libpthread/nptl/sysdeps/unix/sysv/linux/recv.S new file mode 100644 index 000000000..95fa6516e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/recv.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_recv +#error Missing definition of NR_recv needed for cancellation. +#endif +PSEUDO (__libc_recv, recv, 4) +ret +PSEUDO_END(__libc_recv) +libc_hidden_def (__libc_recv) +weak_alias (__libc_recv, __recv) +libc_hidden_weak (__recv) +weak_alias (__libc_recv, recv) +libc_hidden_weak (recv) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/recvfrom.S b/libpthread/nptl/sysdeps/unix/sysv/linux/recvfrom.S new file mode 100644 index 000000000..d9cc1e9b4 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/recvfrom.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_recvfrom +#error Missing definition of NR_recvfrom needed for cancellation. +#endif +PSEUDO (__libc_recvfrom, recvfrom, 6) +ret +PSEUDO_END(__libc_recvfrom) +libc_hidden_def (__libc_recvfrom) +weak_alias (__libc_recvfrom, __recvfrom) +libc_hidden_weak (__recvfrom) +weak_alias (__libc_recvfrom, recvfrom) +libc_hidden_weak (recvfrom) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/recvmsg.S b/libpthread/nptl/sysdeps/unix/sysv/linux/recvmsg.S new file mode 100644 index 000000000..c761b907c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/recvmsg.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_recvmsg +#error Missing definition of NR_recvmsg needed for cancellation. +#endif +PSEUDO (__libc_recvmsg, recvmsg, 3) +ret +PSEUDO_END(__libc_recvmsg) +libc_hidden_def (__libc_recvmsg) +weak_alias (__libc_recvmsg, __recvmsg) +libc_hidden_weak (__recvmsg) +weak_alias (__libc_recvmsg, recvmsg) +libc_hidden_weak (recvmsg) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/register-atfork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/register-atfork.c new file mode 100644 index 000000000..f956ad565 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/register-atfork.c @@ -0,0 +1,149 @@ +/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <fork.h> +#include <atomic.h> +#include <tls.h> + + +/* Lock to protect allocation and deallocation of fork handlers. */ +int __fork_lock = LLL_LOCK_INITIALIZER; + + +/* Number of pre-allocated handler entries. */ +#define NHANDLER 48 + +/* Memory pool for fork handler structures. */ +static struct fork_handler_pool +{ + struct fork_handler_pool *next; + struct fork_handler mem[NHANDLER]; +} fork_handler_pool; + + +static struct fork_handler * +fork_handler_alloc (void) +{ + struct fork_handler_pool *runp = &fork_handler_pool; + struct fork_handler *result = NULL; + unsigned int i; + + do + { + /* Search for an empty entry. */ + for (i = 0; i < NHANDLER; ++i) + if (runp->mem[i].refcntr == 0) + goto found; + } + while ((runp = runp->next) != NULL); + + /* We have to allocate a new entry. */ + runp = (struct fork_handler_pool *) calloc (1, sizeof (*runp)); + if (runp != NULL) + { + /* Enqueue the new memory pool into the list. */ + runp->next = fork_handler_pool.next; + fork_handler_pool.next = runp; + + /* We use the last entry on the page. This means when we start + searching from the front the next time we will find the first + entry unused. */ + i = NHANDLER - 1; + + found: + result = &runp->mem[i]; + result->refcntr = 1; + result->need_signal = 0; + } + + return result; +} + + +int +__register_atfork ( + void (*prepare) (void), + void (*parent) (void), + void (*child) (void), + void *dso_handle) +{ + /* Get the lock to not conflict with other allocations. */ + lll_lock (__fork_lock, LLL_PRIVATE); + + struct fork_handler *newp = fork_handler_alloc (); + + if (newp != NULL) + { + /* Initialize the new record. */ + newp->prepare_handler = prepare; + newp->parent_handler = parent; + newp->child_handler = child; + newp->dso_handle = dso_handle; + + __linkin_atfork (newp); + } + + /* Release the lock. */ + lll_unlock (__fork_lock, LLL_PRIVATE); + + return newp == NULL ? ENOMEM : 0; +} +libc_hidden_def (__register_atfork) + + +void +attribute_hidden +__linkin_atfork (struct fork_handler *newp) +{ + do + newp->next = __fork_handlers; + while (catomic_compare_and_exchange_bool_acq (&__fork_handlers, + newp, newp->next) != 0); +} + +#if 0 +libc_freeres_fn (free_mem) +{ + /* Get the lock to not conflict with running forks. */ + lll_lock (__fork_lock, LLL_PRIVATE); + + /* No more fork handlers. */ + __fork_handlers = NULL; + + /* Free eventually alloated memory blocks for the object pool. */ + struct fork_handler_pool *runp = fork_handler_pool.next; + + memset (&fork_handler_pool, '\0', sizeof (fork_handler_pool)); + + /* Release the lock. */ + lll_unlock (__fork_lock, LLL_PRIVATE); + + /* We can free the memory after releasing the lock. */ + while (runp != NULL) + { + struct fork_handler_pool *oldp = runp; + runp = runp->next; + free (oldp); + } +} +#endif + diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sem_post.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_post.c new file mode 100644 index 000000000..edb97c4ba --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_post.c @@ -0,0 +1,58 @@ +/* sem_post -- post to a POSIX semaphore. Generic futex-using version. + Copyright (C) 2003, 2004, 2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 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 <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <internaltypes.h> +#include <semaphore.h> +#include <tls.h> + +int +__new_sem_post (sem_t *sem) +{ + struct new_sem *isem = (struct new_sem *) sem; + + __typeof (isem->value) cur; + do + { + cur = isem->value; + if (isem->value == SEM_VALUE_MAX) + { + __set_errno (EOVERFLOW); + return -1; + } + } + while (atomic_compare_and_exchange_bool_acq (&isem->value, cur + 1, cur)); + + atomic_full_barrier (); + if (isem->nwaiters > 0) + { + int err = lll_futex_wake (&isem->value, 1, + isem->private ^ FUTEX_PRIVATE_FLAG); + if (__builtin_expect (err, 0) < 0) + { + __set_errno (-err); + return -1; + } + } + return 0; +} +weak_alias(__new_sem_post, sem_post) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c new file mode 100644 index 000000000..3e5e6dcae --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c @@ -0,0 +1,111 @@ +/* sem_timedwait -- wait on a semaphore. Generic futex-using version. + Copyright (C) 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras <paulus@au.ibm.com>, 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 <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <internaltypes.h> +#include <semaphore.h> + +#include <pthreadP.h> + + +extern void __sem_wait_cleanup (void *arg) attribute_hidden; + + +int +sem_timedwait (sem_t *sem, const struct timespec *abstime) +{ + struct new_sem *isem = (struct new_sem *) sem; + int err; + + if (atomic_decrement_if_positive (&isem->value) > 0) + return 0; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + { + __set_errno (EINVAL); + return -1; + } + + atomic_increment (&isem->nwaiters); + + pthread_cleanup_push (__sem_wait_cleanup, isem); + + while (1) + { + struct timeval tv; + struct timespec rt; + int sec, nsec; + + /* Get the current time. */ + __gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + sec = abstime->tv_sec - tv.tv_sec; + nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (nsec < 0) + { + nsec += 1000000000; + --sec; + } + + /* Already timed out? */ + err = -ETIMEDOUT; + if (sec < 0) + { + __set_errno (ETIMEDOUT); + err = -1; + break; + } + + /* Do wait. */ + rt.tv_sec = sec; + rt.tv_nsec = nsec; + + /* Enable asynchronous cancellation. Required by the standard. */ + int oldtype = __pthread_enable_asynccancel (); + + err = lll_futex_timed_wait (&isem->value, 0, &rt, + isem->private ^ FUTEX_PRIVATE_FLAG); + + /* Disable asynchronous cancellation. */ + __pthread_disable_asynccancel (oldtype); + + if (err != 0 && err != -EWOULDBLOCK) + { + __set_errno (-err); + err = -1; + break; + } + + if (atomic_decrement_if_positive (&isem->value) > 0) + { + err = 0; + break; + } + } + + pthread_cleanup_pop (0); + + atomic_decrement (&isem->nwaiters); + + return err; +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sem_trywait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_trywait.c new file mode 100644 index 000000000..3cf1d9a8a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_trywait.c @@ -0,0 +1,44 @@ +/* sem_trywait -- wait on a semaphore. Generic futex-using version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras <paulus@au.ibm.com>, 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 <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <internaltypes.h> +#include <semaphore.h> + + +int +__new_sem_trywait (sem_t *sem) +{ + int *futex = (int *) sem; + int val; + + if (*futex > 0) + { + val = atomic_decrement_if_positive (futex); + if (val > 0) + return 0; + } + + __set_errno (EAGAIN); + return -1; +} +weak_alias(__new_sem_trywait, sem_trywait) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sem_wait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_wait.c new file mode 100644 index 000000000..e661e09c8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sem_wait.c @@ -0,0 +1,84 @@ +/* sem_wait -- wait on a semaphore. Generic futex-using version. + Copyright (C) 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras <paulus@au.ibm.com>, 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 <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <internaltypes.h> +#include <semaphore.h> + +#include <pthreadP.h> + + +void +attribute_hidden +__sem_wait_cleanup (void *arg) +{ + struct new_sem *isem = (struct new_sem *) arg; + + atomic_decrement (&isem->nwaiters); +} + + +int +__new_sem_wait (sem_t *sem) +{ + struct new_sem *isem = (struct new_sem *) sem; + int err; + + if (atomic_decrement_if_positive (&isem->value) > 0) + return 0; + + atomic_increment (&isem->nwaiters); + + pthread_cleanup_push (__sem_wait_cleanup, isem); + + while (1) + { + /* Enable asynchronous cancellation. Required by the standard. */ + int oldtype = __pthread_enable_asynccancel (); + + err = lll_futex_wait (&isem->value, 0, + isem->private ^ FUTEX_PRIVATE_FLAG); + + /* Disable asynchronous cancellation. */ + __pthread_disable_asynccancel (oldtype); + + if (err != 0 && err != -EWOULDBLOCK) + { + __set_errno (-err); + err = -1; + break; + } + + if (atomic_decrement_if_positive (&isem->value) > 0) + { + err = 0; + break; + } + } + + pthread_cleanup_pop (0); + + atomic_decrement (&isem->nwaiters); + + return err; +} +weak_alias(__new_sem_wait, sem_wait) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/send.S b/libpthread/nptl/sysdeps/unix/sysv/linux/send.S new file mode 100644 index 000000000..eb744c712 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/send.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_send +#error Missing definition of NR_send needed for cancellation. +#endif +PSEUDO (__libc_send, send, 4) +ret +PSEUDO_END (__libc_send) +libc_hidden_def (__libc_send) +weak_alias (__libc_send, __send) +libc_hidden_weak (__send) +weak_alias (__libc_send, send) +libc_hidden_weak (send) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sendmsg.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sendmsg.S new file mode 100644 index 000000000..4c41e01c1 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sendmsg.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_sendmsg +#error Missing definition of NR_sendmsg needed for cancellation. +#endif +PSEUDO (__libc_sendmsg, sendmsg, 3) +ret +PSEUDO_END(__libc_sendmsg) +libc_hidden_def (__libc_sendmsg) +weak_alias (__libc_sendmsg, __sendmsg) +libc_hidden_weak (__sendmsg) +weak_alias (__libc_sendmsg, sendmsg) +libc_hidden_weak (sendmsg) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sendto.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sendto.S new file mode 100644 index 000000000..7cb5278e9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sendto.S @@ -0,0 +1,12 @@ +#include <sysdep-cancel.h> +#ifndef __NR_sendto +#error Missing definition of NR_sendto needed for cancellation. +#endif +PSEUDO (__libc_sendto, sendto, 6) +ret +PSEUDO_END(__libc_sendto) +libc_hidden_def (__libc_sendto) +weak_alias (__libc_sendto, __sendto) +libc_hidden_weak (__sendto) +weak_alias (__libc_sendto, sendto) +libc_hidden_weak (sendto) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile new file mode 100644 index 000000000..43a6fad84 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../../../../ +top_builddir=../../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile.arch b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile.arch new file mode 100644 index 000000000..940bd62f8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile.arch @@ -0,0 +1,85 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_SSRC = pt-vfork.S pthread_once.S pthread_rwlock_wrlock.S \ + pthread_rwlock_rdlock.S pthread_rwlock_unlock.S \ + lowlevellock.S lowlevelrobustlock.S pthread_barrier_wait.S \ + pthread_cond_broadcast.S pthread_cond_signal.S \ + pthread_rwlock_timedwrlock.S pthread_rwlock_timedrdlock.S \ + sem_post.S sem_timedwait.S sem_trywait.S sem_wait.S + +libc_a_CSRC = fork.c +libc_a_SSRC = libc-lowlevellock.S clone.S vfork.S + +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y) +CFLAGS-fork.c = -D__USE_STDIO_FUTEXES__ +endif + +ASFLAGS-pt-vfork.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_once.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_rwlock_wrlock.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_rwlock_rdlock.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_rwlock_unlock.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_rwlock_unlock.S = -D_LIBC_REENTRANT -DUSE___THREAD + +ASFLAGS-pthread_barrier_wait.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_cond_broadcast.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_cond_signal.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_cond_wait.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_cond_timedwait.S = -D_LIBC_REENTRANT -DUSE___THREAD + +ASFLAGS-pthread_rwlock_timedwrlock.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_rwlock_timedrdlock.S = -D_LIBC_REENTRANT -DUSE___THREAD + +ASFLAGS-sem_post.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-sem_timedwait.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-sem_trywait.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-sem_wait.S = -D_LIBC_REENTRANT -DUSE___THREAD + +ASFLAGS-libc-lowlevellock.S = -D_LIBC_REENTRANT -DUSE___THREAD + +ASFLAGS-lowlevellock.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-lowlevelrobustlock.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT -DUSE___THREAD + +ASFLAGS-clone.S = -D_LIBC_REENTRANT +ASFLAGS-vfork.S = -D_LIBC_REENTRANT + +ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) +#Needed to use the correct SYSCALL_ERROR_HANDLER +ASFLAGS-clone.S += -DUSE___THREAD +ASFLAGS-vfork.S += -DUSE___THREAD +endif + +CFLAGS += $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +LINUX_ARCH_DIR:=$(top_srcdir)libpthread/nptl/sysdeps/unix/sysv/linux/sh +LINUX_ARCH_OUT:=$(top_builddir)libpthread/nptl/sysdeps/unix/sysv/linux/sh + +LINUX_ARCH_OBJ:=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libpthread_SSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(LINUX_ARCH_OBJ:.o=.os) +else +libpthread-a-y += $(LINUX_ARCH_OBJ) +endif +libpthread-so-y += $(LINUX_ARCH_OBJ:.o=.oS) + +libpthread-nomulti-y+=$(LINUX_ARCH_OBJS) + +LIBC_LINUX_ARCH_OBJ:=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libc_a_CSRC)) +LIBC_LINUX_ARCH_OBJ+=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libc_a_SSRC)) + +libc-static-y+=$(LIBC_LINUX_ARCH_OBJ) +libc-shared-y+=$(LIBC_LINUX_ARCH_OBJ:.o=.oS) + +libc-nomulti-y+=$(LIBC_LINUX_ARCH_OBJ) + +objclean-y+=nptl_linux_arch_clean + +nptl_linux_arch_clean: + $(do_rm) $(addprefix $(LINUX_ARCH_OUT)/*., o os oS) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h new file mode 100644 index 000000000..badcda570 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h @@ -0,0 +1,183 @@ +/* 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 <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#include <endian.h> + +#define __SIZEOF_PTHREAD_ATTR_T 36 +#define __SIZEOF_PTHREAD_MUTEX_T 24 +#define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +#define __SIZEOF_PTHREAD_COND_T 48 +#define __SIZEOF_PTHREAD_COND_COMPAT_T 12 +#define __SIZEOF_PTHREAD_CONDATTR_T 4 +#define __SIZEOF_PTHREAD_RWLOCK_T 32 +#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +#define __SIZEOF_PTHREAD_BARRIER_T 20 +#define __SIZEOF_PTHREAD_BARRIERATTR_T 4 + + +/* Thread identifiers. The structure of the attribute type is not + exposed on purpose. */ +typedef unsigned long int pthread_t; + + +typedef union +{ + char __size[__SIZEOF_PTHREAD_ATTR_T]; + long int __align; +} pthread_attr_t; + + +typedef struct __pthread_internal_slist +{ + struct __pthread_internal_slist *__next; +} __pthread_slist_t; + + +/* Data structures for mutex handling. The structure of the attribute + type is not exposed on purpose. */ +typedef union +{ + struct __pthread_mutex_s + { + int __lock; + unsigned int __count; + int __owner; + /* KIND must stay at this position in the structure to maintain + binary compatibility. */ + int __kind; + unsigned int __nusers; + __extension__ union + { + int __spins; + __pthread_slist_t __list; + }; + } __data; + char __size[__SIZEOF_PTHREAD_MUTEX_T]; + long int __align; +} pthread_mutex_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; + long int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling. The structure of + the attribute type is not exposed on purpose. */ +typedef union +{ + struct + { + int __lock; + unsigned int __futex; + __extension__ unsigned long long int __total_seq; + __extension__ unsigned long long int __wakeup_seq; + __extension__ unsigned long long int __woken_seq; + void *__mutex; + unsigned int __nwaiters; + unsigned int __broadcast_seq; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_CONDATTR_T]; + long int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling. The + structure of the attribute type is not exposed on purpose. */ +typedef union +{ + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned char __pad1; + unsigned char __pad2; + unsigned char __shared; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; +#else + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; + unsigned char __shared; + unsigned char __pad1; + unsigned char __pad2; +#endif + pthread_t __writer; + } __data; + char __size[__SIZEOF_PTHREAD_RWLOCK_T]; + long int __align; +} pthread_rwlock_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; + long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type. The structure of the type is + deliberately not exposed. */ +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIER_T]; + long int __align; +} pthread_barrier_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; + int __align; +} pthread_barrierattr_t; +#endif + + +#endif /* bits/pthreadtypes.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/semaphore.h new file mode 100644 index 000000000..934493c30 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/semaphore.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SEMAPHORE_H +# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." +#endif + + +#define __SIZEOF_SEM_T 16 + + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + + +typedef union +{ + char __size[__SIZEOF_SEM_T]; + long int __align; +} sem_t; diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/clone.S new file mode 100644 index 000000000..918d57926 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <libc/sysdeps/linux/sh/clone.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/createthread.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/createthread.c new file mode 100644 index 000000000..e17c0174b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/createthread.c @@ -0,0 +1,24 @@ +/* Copyright (C) 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Value passed to 'clone' for initialization of the thread register. */ +#define TLS_VALUE (pd + 1) + + +/* Get the real implementation. */ +#include <sysdeps/pthread/createthread.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/fork.c new file mode 100644 index 000000000..6868b9bcd --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/fork.c @@ -0,0 +1,30 @@ +/* Copyright (C) 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sched.h> +#include <signal.h> +#include <sysdep.h> +#include <tls.h> + +/* TLS pointer argument is passed as the 5-th argument. */ +#define ARCH_FORK() \ + INLINE_SYSCALL (clone, 5, \ + CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0, \ + NULL, &THREAD_SELF->tid, NULL) + +#include "../fork.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S new file mode 100644 index 000000000..feb82110c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S @@ -0,0 +1,19 @@ +/* Copyright (C) 2003, 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 + 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 "lowlevellock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h new file mode 100644 index 000000000..c7028360f --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h @@ -0,0 +1,81 @@ +/* Copyright (C) 2003, 2004, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef __ASSEMBLER__ + +#define _IMP1 #1 +#define _IMM1 #-1 +#define _IMM4 #-4 +#define _IMM6 #-6 +#define _IMM8 #-8 + +#define INC(mem, reg) \ + .align 2; \ + mova 99f, r0; \ + mov r15, r1; \ + mov _IMM6, r15; \ +98: mov.l mem, reg; \ + add _IMP1, reg; \ + mov.l reg, mem; \ +99: mov r1, r15 + +#define DEC(mem, reg) \ + .align 2; \ + mova 99f, r0; \ + mov r15, r1; \ + mov _IMM6, r15; \ +98: mov.l mem, reg; \ + add _IMM1, reg; \ + mov.l reg, mem; \ +99: mov r1, r15 + +#define XADD(reg, mem, old, tmp) \ + .align 2; \ + mova 99f, r0; \ + nop; \ + mov r15, r1; \ + mov _IMM8, r15; \ +98: mov.l mem, old; \ + mov reg, tmp; \ + add old, tmp; \ + mov.l tmp, mem; \ +99: mov r1, r15 + +#define XCHG(reg, mem, old) \ + .align 2; \ + mova 99f, r0; \ + nop; \ + mov r15, r1; \ + mov _IMM4, r15; \ +98: mov.l mem, old; \ + mov.l reg, mem; \ +99: mov r1, r15 + +#define CMPXCHG(reg, mem, new, old) \ + .align 2; \ + mova 99f, r0; \ + nop; \ + mov r15, r1; \ + mov _IMM8, r15; \ +98: mov.l mem, old; \ + cmp/eq old, reg; \ + bf 99f; \ + mov.l new, mem; \ +99: mov r1, r15 + +#endif /* __ASSEMBLER__ */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S new file mode 100644 index 000000000..00edc75a7 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S @@ -0,0 +1,540 @@ +/* Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include <bits/kernel-features.h> +#include <lowlevellock.h> +#include <tcb-offsets.h> +#include "lowlevel-atomic.h" + + .text + +#ifdef __ASSUME_PRIVATE_FUTEX +# define LOAD_PRIVATE_FUTEX_WAIT(reg,tmp,tmp2) \ + mov #(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg; \ + extu.b reg, reg +# define LOAD_PRIVATE_FUTEX_WAKE(reg,tmp,tmp2) \ + mov #(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg; \ + extu.b reg, reg +# define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \ + mov #(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), tmp; \ + extu.b tmp, tmp; \ + xor tmp, reg +# define LOAD_FUTEX_WAIT_ABS(reg,tmp,tmp2) \ + mov #(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG), tmp; \ + extu.b tmp, tmp; \ + mov #(FUTEX_CLOCK_REALTIME >> 8), tmp2; \ + swap.b tmp2, tmp2; \ + or tmp2, tmp; \ + xor tmp, reg +# define LOAD_FUTEX_WAKE(reg,tmp,tmp2) \ + mov #(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), tmp; \ + extu.b tmp, tmp; \ + xor tmp, reg +#else +# if FUTEX_WAIT == 0 +# define LOAD_PRIVATE_FUTEX_WAIT(reg,tmp,tmp2) \ + stc gbr, tmp ; \ + mov.w 99f, reg ; \ + add reg, tmp ; \ + bra 98f ; \ + mov.l @tmp, reg ; \ +99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \ +98: +# else +# define LOAD_PRIVATE_FUTEX_WAIT(reg,tmp,tmp2) \ + stc gbr, tmp ; \ + mov.w 99f, reg ; \ + add reg, tmp ; \ + mov.l @tmp, reg ; \ + bra 98f ; \ + mov #FUTEX_WAIT, tmp ; \ +99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \ +98: or tmp, reg +# endif +# define LOAD_PRIVATE_FUTEX_WAKE(reg,tmp,tmp2) \ + stc gbr, tmp ; \ + mov.w 99f, reg ; \ + add reg, tmp ; \ + mov.l @tmp, reg ; \ + bra 98f ; \ + mov #FUTEX_WAKE, tmp ; \ +99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \ +98: or tmp, reg +# if FUTEX_WAIT == 0 +# define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \ + stc gbr, tmp ; \ + mov.w 99f, tmp2 ; \ + add tmp2, tmp ; \ + mov.l @tmp, tmp2 ; \ + bra 98f ; \ + mov #FUTEX_PRIVATE_FLAG, tmp ; \ +99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \ +98: extu.b tmp, tmp ; \ + xor tmp, reg ; \ + and tmp2, reg +# else +# define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \ + stc gbr, tmp ; \ + mov.w 99f, tmp2 ; \ + add tmp2, tmp ; \ + mov.l @tmp, tmp2 ; \ + bra 98f ; \ + mov #FUTEX_PRIVATE_FLAG, tmp ; \ +99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \ +98: extu.b tmp, tmp ; \ + xor tmp, reg ; \ + and tmp2, reg ; \ + mov #FUTEX_WAIT, tmp ; \ + or tmp, reg +# endif +# define LOAD_FUTEX_WAIT_ABS(reg,tmp,tmp2) \ + stc gbr, tmp ; \ + mov.w 99f, tmp2 ; \ + add tmp2, tmp ; \ + mov.l @tmp, tmp2 ; \ + bra 98f ; \ + mov #FUTEX_PRIVATE_FLAG, tmp ; \ +99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \ +98: extu.b tmp, tmp ; \ + xor tmp, reg ; \ + and tmp2, reg ; \ + mov #FUTEX_WAIT_BITSET, tmp ; \ + mov #(FUTEX_CLOCK_REALTIME >> 8), tmp2; \ + swap.b tmp2, tmp2; \ + or tmp2, tmp; \ + or tmp, reg +# define LOAD_FUTEX_WAKE(reg,tmp,tmp2) \ + stc gbr, tmp ; \ + mov.w 99f, tmp2 ; \ + add tmp2, tmp ; \ + mov.l @tmp, tmp2 ; \ + bra 98f ; \ + mov #FUTEX_PRIVATE_FLAG, tmp ; \ +99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \ +98: extu.b tmp, tmp ; \ + xor tmp, reg ; \ + and tmp2, reg ; \ + mov #FUTEX_WAKE, tmp ; \ + or tmp, reg +#endif + + .globl __lll_lock_wait_private + .type __lll_lock_wait_private,@function + .hidden __lll_lock_wait_private + .align 5 + cfi_startproc +__lll_lock_wait_private: + mov.l r8, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r8, 0) + mov r4, r6 + mov r5, r8 + mov #0, r7 /* No timeout. */ + LOAD_PRIVATE_FUTEX_WAIT (r5, r0, r1) + + mov #2, r4 + cmp/eq r4, r6 + bf 2f + +1: + mov r8, r4 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + +2: + mov #2, r6 + XCHG (r6, @r8, r2) + tst r2, r2 + bf 1b + + mov.l @r15+, r8 + rts + mov r2, r0 + cfi_endproc + .size __lll_lock_wait_private,.-__lll_lock_wait_private + +#ifdef NOT_IN_libc + .globl __lll_lock_wait + .type __lll_lock_wait,@function + .hidden __lll_lock_wait + .align 5 + cfi_startproc +__lll_lock_wait: + mov.l r9, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r9, 0) + mov.l r8, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r8, 0) + mov r6, r9 + mov r4, r6 + mov r5, r8 + mov #0, r7 /* No timeout. */ + mov r9, r5 + LOAD_FUTEX_WAIT (r5, r0, r1) + + mov #2, r4 + cmp/eq r4, r6 + bf 2f + +1: + mov r8, r4 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + +2: + mov #2, r6 + XCHG (r6, @r8, r2) + tst r2, r2 + bf 1b + + mov.l @r15+, r8 + mov.l @r15+, r9 + ret + mov r2, r0 + cfi_endproc + .size __lll_lock_wait,.-__lll_lock_wait + + /* r5 (r8): futex + r7 (r11): flags + r6 (r9): timeout + r4 (r10): futex value + */ + .globl __lll_timedlock_wait + .type __lll_timedlock_wait,@function + .hidden __lll_timedlock_wait + .align 5 + cfi_startproc +__lll_timedlock_wait: + mov.l r12, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r12, 0) + +# ifndef __ASSUME_FUTEX_CLOCK_REALTIME + mov.l .Lhave, r1 +# ifdef __PIC__ + mova .Lgot, r0 + mov.l .Lgot, r12 + add r0, r12 + add r12, r1 +# endif + mov.l @r1, r0 + tst r0, r0 + bt .Lreltmo +# endif + + mov r4, r2 + mov r5, r4 + mov r7, r5 + mov r6, r7 + LOAD_FUTEX_WAIT_ABS (r5, r0, r1) + + mov #2, r6 + cmp/eq r6, r2 + bf/s 2f + mov r6, r2 + +1: + mov #2, r6 + mov #-1, r1 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x16 + SYSCALL_INST_PAD + mov r0, r6 + +2: + XCHG (r2, @r4, r3) /* NB: lock is implied */ + + tst r3, r3 + bt/s 3f + mov r6, r0 + + cmp/eq #-ETIMEDOUT, r0 + bt 4f + cmp/eq #-EINVAL, r0 + bf 1b +4: + neg r0, r3 +3: + mov r3, r0 + rts + mov.l @r15+, r12 + + .align 2 +# ifndef __ASSUME_FUTEX_CLOCK_REALTIME +# ifdef __PIC__ +.Lgot: + .long _GLOBAL_OFFSET_TABLE_ +.Lhave: + .long __have_futex_clock_realtime@GOTOFF +# else +.Lhave: + .long __have_futex_clock_realtime +# endif + +.Lreltmo: + /* Check for a valid timeout value. */ + mov.l @(4,r6), r1 + mov.l .L1g, r0 + cmp/hs r0, r1 + bt 3f + + mov.l r11, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r11, 0) + mov.l r10, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r10, 0) + mov.l r9, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r9, 0) + mov.l r8, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r8, 0) + mov r7, r11 + mov r4, r10 + mov r6, r9 + mov r5, r8 + + /* Stack frame for the timespec and timeval structs. */ + add #-8, r15 + cfi_adjust_cfa_offset(8) + + mov #2, r2 + XCHG (r2, @r8, r3) + + tst r3, r3 + bt 6f + +1: + /* Get current time. */ + mov r15, r4 + mov #0, r5 + mov #__NR_gettimeofday, r3 + trapa #0x12 + SYSCALL_INST_PAD + + /* Compute relative timeout. */ + mov.l @(4,r15), r0 + mov.w .L1k, r1 + dmulu.l r0, r1 /* Micro seconds to nano seconds. */ + mov.l @r9, r2 + mov.l @(4,r9), r3 + mov.l @r15, r0 + sts macl, r1 + sub r0, r2 + clrt + subc r1, r3 + bf 4f + mov.l .L1g, r1 + add r1, r3 + add #-1, r2 +4: + cmp/pz r2 + bf 2f /* Time is already up. */ + + mov.l r2, @r15 /* Store relative timeout. */ + mov.l r3, @(4,r15) + + mov r8, r4 + mov r11, r5 + LOAD_FUTEX_WAIT (r5, r0, r1) + mov r10, r6 + mov r15, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + mov r0, r5 + + mov #2, r2 + XCHG (r2, @r8, r3) + + tst r3, r3 + bt/s 6f + mov #-ETIMEDOUT, r1 + cmp/eq r5, r1 + bf 1b + +2: mov #ETIMEDOUT, r3 + +6: + mov r3, r0 + add #8, r15 + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r10 + mov.l @r15+, r11 + rts + mov.l @r15+, r12 + +3: + mov.l @r15+, r12 + rts + mov #EINVAL, r0 +# endif + cfi_endproc + +.L1k: + .word 1000 + .align 2 +.L1g: + .long 1000000000 + + .size __lll_timedlock_wait,.-__lll_timedlock_wait +#endif + + .globl __lll_unlock_wake_private + .type __lll_unlock_wake_private,@function + .hidden __lll_unlock_wake_private + .align 5 + cfi_startproc +__lll_unlock_wake_private: + LOAD_PRIVATE_FUTEX_WAKE (r5, r0, r1) + mov #1, r6 /* Wake one thread. */ + mov #0, r7 + mov.l r7, @r4 /* Stores 0. */ + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + rts + nop + cfi_endproc + .size __lll_unlock_wake_private,.-__lll_unlock_wake_private + +#ifdef NOT_IN_libc + .globl __lll_unlock_wake + .type __lll_unlock_wake,@function + .hidden __lll_unlock_wake + .align 5 + cfi_startproc +__lll_unlock_wake: + LOAD_FUTEX_WAKE (r5, r0, r1) + mov #1, r6 /* Wake one thread. */ + mov #0, r7 + mov.l r7, @r4 /* Stores 0. */ + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + rts + nop + cfi_endproc + .size __lll_unlock_wake,.-__lll_unlock_wake + + .globl __lll_timedwait_tid + .type __lll_timedwait_tid,@function + .hidden __lll_timedwait_tid + .align 5 + cfi_startproc +__lll_timedwait_tid: + mov.l r9, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r9, 0) + mov.l r8, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r8, 0) + mov r4, r8 + mov r5, r9 + + /* Stack frame for the timespec and timeval structs. */ + add #-8, r15 + cfi_adjust_cfa_offset(8) + +2: + /* Get current time. */ + mov r15, r4 + mov #0, r5 + mov #__NR_gettimeofday, r3 + trapa #0x12 + SYSCALL_INST_PAD + + /* Compute relative timeout. */ + mov.l @(4,r15), r0 + mov.w .L1k2, r1 + dmulu.l r0, r1 /* Micro seconds to nano seconds. */ + mov.l @r9, r2 + mov.l @(4,r9), r3 + mov.l @r15, r0 + sts macl, r1 + sub r0, r2 + clrt + subc r1, r3 + bf 5f + mov.l .L1g2, r1 + add r1, r3 + add #-1, r2 +5: + cmp/pz r2 + bf 6f /* Time is already up. */ + + mov.l r2, @r15 /* Store relative timeout. */ + mov.l r3, @(4,r15) + + mov.l @r8, r2 + tst r2, r2 + bt 4f + + mov r8, r4 + /* XXX The kernel so far uses global futex for the wakeup at + all times. */ + mov #0, r5 + extu.b r5, r5 + mov r2, r6 + mov r15, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + mov.l @r8, r2 + tst r2, r2 + bf 1f +4: + mov #0, r0 +3: + add #8, r15 + mov.l @r15+, r8 + rts + mov.l @r15+, r9 +1: + /* Check whether the time expired. */ + mov #-ETIMEDOUT, r1 + cmp/eq r0, r1 + bf 2b +6: + bra 3b + mov #ETIMEDOUT, r0 + cfi_endproc + +.L1k2: + .word 1000 + .align 2 +.L1g2: + .long 1000000000 + .size __lll_timedwait_tid,.-__lll_timedwait_tid +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h new file mode 100644 index 000000000..19ce7fe40 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h @@ -0,0 +1,420 @@ +/* Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H 1 + +#ifndef __ASSEMBLER__ +#include <time.h> +#include <sys/param.h> +#include <bits/pthreadtypes.h> +#include <bits/kernel-features.h> +#endif + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_CMP_REQUEUE 4 +#define FUTEX_WAKE_OP 5 +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 +#define FUTEX_WAIT_BITSET 9 +#define FUTEX_WAKE_BITSET 10 +#define FUTEX_PRIVATE_FLAG 128 +#define FUTEX_CLOCK_REALTIME 256 + +#define FUTEX_BITSET_MATCH_ANY 0xffffffff + +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \ + & THREAD_GETMEM (THREAD_SELF, header.private_futex)))) +# endif +#endif + +#ifndef __ASSEMBLER__ + +/* Initializer for compatibility lock. */ +#define LLL_LOCK_INITIALIZER (0) +#define LLL_LOCK_INITIALIZER_LOCKED (1) +#define LLL_LOCK_INITIALIZER_WAITERS (2) + +extern int __lll_lock_wait_private (int val, int *__futex) + attribute_hidden; +extern int __lll_lock_wait (int val, int *__futex, int private) + attribute_hidden; +extern int __lll_timedlock_wait (int val, int *__futex, + const struct timespec *abstime, int private) + attribute_hidden; +extern int __lll_robust_lock_wait (int val, int *__futex, int private) + attribute_hidden; +extern int __lll_robust_timedlock_wait (int val, int *__futex, + const struct timespec *abstime, + int private) + attribute_hidden; +extern int __lll_unlock_wake_private (int *__futex) attribute_hidden; +extern int __lll_unlock_wake (int *__futex, int private) attribute_hidden; + +#define lll_trylock(futex) \ + ({ unsigned char __result; \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.l @%1,r2\n\ + cmp/eq r2,%3\n\ + bf 1f\n\ + mov.l %2,@%1\n\ + 1: mov r1,r15\n\ + mov #-1,%0\n\ + negc %0,%0"\ + : "=r" (__result) \ + : "r" (&(futex)), \ + "r" (LLL_LOCK_INITIALIZER_LOCKED), \ + "r" (LLL_LOCK_INITIALIZER) \ + : "r0", "r1", "r2", "t", "memory"); \ + __result; }) + +#define lll_robust_trylock(futex, id) \ + ({ unsigned char __result; \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.l @%1,r2\n\ + cmp/eq r2,%3\n\ + bf 1f\n\ + mov.l %2,@%1\n\ + 1: mov r1,r15\n\ + mov #-1,%0\n\ + negc %0,%0"\ + : "=r" (__result) \ + : "r" (&(futex)), \ + "r" (id), \ + "r" (LLL_LOCK_INITIALIZER) \ + : "r0", "r1", "r2", "t", "memory"); \ + __result; }) + +#define lll_cond_trylock(futex) \ + ({ unsigned char __result; \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.l @%1,r2\n\ + cmp/eq r2,%3\n\ + bf 1f\n\ + mov.l %2,@%1\n\ + 1: mov r1,r15\n\ + mov #-1,%0\n\ + negc %0,%0"\ + : "=r" (__result) \ + : "r" (&(futex)), \ + "r" (LLL_LOCK_INITIALIZER_WAITERS), \ + "r" (LLL_LOCK_INITIALIZER) \ + : "r0", "r1", "r2", "t", "memory"); \ + __result; }) + +#define lll_lock(futex, private) \ + (void) ({ int __result, *__futex = &(futex); \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.l @%2,%0\n\ + tst %0,%0\n\ + bf 1f\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result) : "r" (1), "r" (__futex) \ + : "r0", "r1", "t", "memory"); \ + if (__result) \ + { \ + if (__builtin_constant_p (private) \ + && (private) == LLL_PRIVATE) \ + __lll_lock_wait_private (__result, __futex); \ + else \ + __lll_lock_wait (__result, __futex, (private)); \ + } \ + }) + +#define lll_robust_lock(futex, id, private) \ + ({ int __result, *__futex = &(futex); \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.l @%2,%0\n\ + tst %0,%0\n\ + bf 1f\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result) : "r" (id), "r" (__futex) \ + : "r0", "r1", "t", "memory"); \ + if (__result) \ + __result = __lll_robust_lock_wait (__result, __futex, private); \ + __result; }) + +/* Special version of lll_mutex_lock which causes the unlock function to + always wakeup waiters. */ +#define lll_cond_lock(futex, private) \ + (void) ({ int __result, *__futex = &(futex); \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.l @%2,%0\n\ + tst %0,%0\n\ + bf 1f\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result) : "r" (2), "r" (__futex) \ + : "r0", "r1", "t", "memory"); \ + if (__result) \ + __lll_lock_wait (__result, __futex, private); }) + +#define lll_robust_cond_lock(futex, id, private) \ + ({ int __result, *__futex = &(futex); \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.l @%2,%0\n\ + tst %0,%0\n\ + bf 1f\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result) : "r" (id | FUTEX_WAITERS), "r" (__futex) \ + : "r0", "r1", "t", "memory"); \ + if (__result) \ + __result = __lll_robust_lock_wait (__result, __futex, private); \ + __result; }) + +#define lll_timedlock(futex, timeout, private) \ + ({ int __result, *__futex = &(futex); \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.l @%2,%0\n\ + tst %0,%0\n\ + bf 1f\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result) : "r" (1), "r" (__futex) \ + : "r0", "r1", "t", "memory"); \ + if (__result) \ + __result = __lll_timedlock_wait (__result, __futex, timeout, private); \ + __result; }) + +#define lll_robust_timedlock(futex, timeout, id, private) \ + ({ int __result, *__futex = &(futex); \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.l @%2,%0\n\ + tst %0,%0\n\ + bf 1f\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result) : "r" (id), "r" (__futex) \ + : "r0", "r1", "t", "memory"); \ + if (__result) \ + __result = __lll_robust_timedlock_wait (__result, __futex, \ + timeout, private); \ + __result; }) + +#define lll_unlock(futex, private) \ + (void) ({ int __result, *__futex = &(futex); \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.l @%1,%0\n\ + add #-1,%0\n\ + mov.l %0,@%1\n\ + 1: mov r1,r15"\ + : "=&r" (__result) : "r" (__futex) \ + : "r0", "r1", "memory"); \ + if (__result) \ + { \ + if (__builtin_constant_p (private) \ + && (private) == LLL_PRIVATE) \ + __lll_unlock_wake_private (__futex); \ + else \ + __lll_unlock_wake (__futex, (private)); \ + } \ + }) + +#define lll_robust_unlock(futex, private) \ + (void) ({ int __result, *__futex = &(futex); \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.l @%1,%0\n\ + and %2,%0\n\ + mov.l %0,@%1\n\ + 1: mov r1,r15"\ + : "=&r" (__result) : "r" (__futex), "r" (FUTEX_WAITERS) \ + : "r0", "r1", "memory"); \ + if (__result) \ + __lll_unlock_wake (__futex, private); }) + +#define lll_robust_dead(futex, private) \ + (void) ({ int __ignore, *__futex = &(futex); \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.l @%1,%0\n\ + or %2,%0\n\ + mov.l %0,@%1\n\ + 1: mov r1,r15"\ + : "=&r" (__ignore) : "r" (__futex), "r" (FUTEX_OWNER_DIED) \ + : "r0", "r1", "memory"); \ + lll_futex_wake (__futex, 1, private); }) + +# ifdef NEED_SYSCALL_INST_PAD +# define SYSCALL_WITH_INST_PAD "\ + trapa #0x14; or r0,r0; or r0,r0; or r0,r0; or r0,r0; or r0,r0" +# else +# define SYSCALL_WITH_INST_PAD "\ + trapa #0x14" +# endif + +#define lll_futex_wait(futex, val, private) \ + lll_futex_timed_wait (futex, val, NULL, private) + + +#define lll_futex_timed_wait(futex, val, timeout, private) \ + ({ \ + int __status; \ + register unsigned long __r3 __asm ("r3") = SYS_futex; \ + register unsigned long __r4 __asm ("r4") = (unsigned long) (futex); \ + register unsigned long __r5 __asm ("r5") \ + = __lll_private_flag (FUTEX_WAIT, private); \ + register unsigned long __r6 __asm ("r6") = (unsigned long) (val); \ + register unsigned long __r7 __asm ("r7") = (timeout); \ + __asm __volatile (SYSCALL_WITH_INST_PAD \ + : "=z" (__status) \ + : "r" (__r3), "r" (__r4), "r" (__r5), \ + "r" (__r6), "r" (__r7) \ + : "memory", "t"); \ + __status; \ + }) + + +#define lll_futex_wake(futex, nr, private) \ + do { \ + int __ignore; \ + register unsigned long __r3 __asm ("r3") = SYS_futex; \ + register unsigned long __r4 __asm ("r4") = (unsigned long) (futex); \ + register unsigned long __r5 __asm ("r5") \ + = __lll_private_flag (FUTEX_WAKE, private); \ + register unsigned long __r6 __asm ("r6") = (unsigned long) (nr); \ + register unsigned long __r7 __asm ("r7") = 0; \ + __asm __volatile (SYSCALL_WITH_INST_PAD \ + : "=z" (__ignore) \ + : "r" (__r3), "r" (__r4), "r" (__r5), \ + "r" (__r6), "r" (__r7) \ + : "memory", "t"); \ + } while (0) + + +#define lll_islocked(futex) \ + (futex != LLL_LOCK_INITIALIZER) + +/* The kernel notifies a process with uses CLONE_CLEARTID via futex + wakeup when the clone terminates. The memory location contains the + thread ID while the clone is running and is reset to zero + afterwards. */ + +#define lll_wait_tid(tid) \ + do { \ + __typeof (tid) *__tid = &(tid); \ + while (*__tid != 0) \ + lll_futex_wait (__tid, *__tid, LLL_SHARED); \ + } while (0) + +extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime) + attribute_hidden; +#define lll_timedwait_tid(tid, abstime) \ + ({ \ + int __result = 0; \ + if (tid != 0) \ + { \ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) \ + __result = EINVAL; \ + else \ + __result = __lll_timedwait_tid (&tid, abstime); \ + } \ + __result; }) + +#endif /* !__ASSEMBLER__ */ + +#endif /* lowlevellock.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevelrobustlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevelrobustlock.S new file mode 100644 index 000000000..1e05a56c0 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevelrobustlock.S @@ -0,0 +1,265 @@ +/* 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include <lowlevellock.h> +#include <lowlevelrobustlock.h> +#include <bits/kernel-features.h> +#include <tcb-offsets.h> +#include "lowlevel-atomic.h" + + .text + +#define FUTEX_WAITERS 0x80000000 +#define FUTEX_OWNER_DIED 0x40000000 + +#ifdef __ASSUME_PRIVATE_FUTEX +# define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \ + mov #(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), tmp; \ + extu.b tmp, tmp; \ + xor tmp, reg +#else +# if FUTEX_WAIT == 0 +# define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \ + stc gbr, tmp ; \ + mov.w 99f, tmp2 ; \ + add tmp2, tmp ; \ + mov.l @tmp, tmp2 ; \ + bra 98f ; \ + mov #FUTEX_PRIVATE_FLAG, tmp ; \ +99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \ +98: extu.b tmp, tmp ; \ + xor tmp, reg ; \ + and tmp2, reg +# else +# define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \ + stc gbr, tmp ; \ + mov.w 99f, tmp2 ; \ + add tmp2, tmp ; \ + mov.l @tmp, tmp2 ; \ + bra 98f ; \ + mov #FUTEX_PRIVATE_FLAG, tmp ; \ +99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \ +98: extu.b tmp, tmp ; \ + xor tmp, reg ; \ + and tmp2, reg ; \ + mov #FUTEX_WAIT, tmp ; \ + or tmp, reg +# endif +#endif + + .globl __lll_robust_lock_wait + .type __lll_robust_lock_wait,@function + .hidden __lll_robust_lock_wait + .align 5 + cfi_startproc +__lll_robust_lock_wait: + mov.l r8, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r8, 0) + mov r5, r8 + mov #0, r7 /* No timeout. */ + mov r6, r5 + LOAD_FUTEX_WAIT (r5, r0, r1) + +4: + mov r4, r6 + mov.l .L_FUTEX_WAITERS, r0 + or r0, r6 + shlr r0 /* r0 = FUTEX_OWNER_DIED */ + tst r0, r4 + bf/s 3f + cmp/eq r4, r6 + bt 1f + + CMPXCHG (r4, @r8, r6, r2) + bf 2f + +1: + mov r8, r4 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + mov.l @r8, r2 + +2: + tst r2, r2 + bf/s 4b + mov r2, r4 + + stc gbr, r1 + mov.w .Ltidoff, r2 + add r2, r1 + mov.l @r1, r6 + mov #0, r3 + CMPXCHG (r3, @r8, r6, r4) + bf 4b + mov #0, r4 + +3: + mov.l @r15+, r8 + ret + mov r4, r0 + cfi_endproc + .align 2 +.L_FUTEX_WAITERS: + .long FUTEX_WAITERS +.Ltidoff: + .word TID - TLS_PRE_TCB_SIZE + .size __lll_robust_lock_wait,.-__lll_robust_lock_wait + + + .globl __lll_robust_timedlock_wait + .type __lll_robust_timedlock_wait,@function + .hidden __lll_robust_timedlock_wait + .align 5 + cfi_startproc +__lll_robust_timedlock_wait: + /* Check for a valid timeout value. */ + mov.l @(4,r6), r1 + mov.l .L1g, r0 + cmp/hs r0, r1 + bt 3f + + mov.l r11, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r11, 0) + mov.l r10, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r10, 0) + mov.l r9, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r9, 0) + mov.l r8, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r8, 0) + mov r7, r11 + mov r4, r10 + mov r6, r9 + mov r5, r8 + + /* Stack frame for the timespec and timeval structs. */ + add #-8, r15 + cfi_adjust_cfa_offset(8) + +1: + /* Get current time. */ + mov r15, r4 + mov #0, r5 + mov #__NR_gettimeofday, r3 + trapa #0x12 + SYSCALL_INST_PAD + + /* Compute relative timeout. */ + mov.l @(4,r15), r0 + mov.w .L1k, r1 + dmulu.l r0, r1 /* Micro seconds to nano seconds. */ + mov.l @r9, r2 + mov.l @(4,r9), r3 + mov.l @r15, r0 + sts macl, r1 + sub r0, r2 + clrt + subc r1, r3 + bf 4f + mov.l .L1g, r1 + add r1, r3 + add #-1, r2 +4: + cmp/pz r2 + bf 8f /* Time is already up. */ + + mov.l r2, @r15 /* Store relative timeout. */ + mov.l r3, @(4,r15) + + mov r10, r6 + mov.l .L_FUTEX_WAITERS2, r0 + or r0, r6 + shlr r0 /* r0 = FUTEX_OWNER_DIED */ + tst r0, r4 + bf/s 6f + cmp/eq r4, r6 + bt 2f + + CMPXCHG (r4, @r8, r6, r2) + bf/s 5f + mov #0, r5 + +2: + mov r8, r4 + mov r11, r5 + LOAD_FUTEX_WAIT (r5, r0, r1) + mov r10, r6 + mov r15, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + mov r0, r5 + + mov.l @r8, r2 + +5: + tst r2, r2 + bf/s 7f + mov r2, r10 + + stc gbr, r1 + mov.w .Ltidoff2, r2 + add r2, r1 + mov.l @r1, r4 + mov #0, r3 + CMPXCHG (r3, @r8, r4, r10) + bf 7f + mov #0, r0 + +6: + add #8, r15 + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r10 + rts + mov.l @r15+, r11 + +7: + /* Check whether the time expired. */ + mov #-ETIMEDOUT, r1 + cmp/eq r5, r1 + bf 1b + +8: + bra 6b + mov #ETIMEDOUT, r0 +3: + rts + mov #EINVAL, r0 + cfi_endproc + .align 2 +.L_FUTEX_WAITERS2: + .long FUTEX_WAITERS +.L1g: + .long 1000000000 +.Ltidoff2: + .word TID - TLS_PRE_TCB_SIZE +.L1k: + .word 1000 + .size __lll_robust_timedlock_wait,.-__lll_robust_timedlock_wait diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-initfini.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-initfini.c new file mode 100644 index 000000000..82c97c352 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-initfini.c @@ -0,0 +1,126 @@ +/* Special .init and .fini section support for SH. NPTL version. + Copyright (C) 2003, 2009 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 Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Library General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Library General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +__asm__ ("\n\ +\n\ +#include \"defs.h\"\n\ +\n\ +/*@HEADER_ENDS*/\n\ +\n\ +/*@TESTS_BEGIN*/\n\ +\n\ +/*@TESTS_END*/\n\ +\n\ +/*@_init_PROLOG_BEGINS*/\n\ + .section .init\n\ + .align 5\n\ + .global _init\n\ + .type _init,@function\n\ +_init:\n\ + mov.l r12,@-r15\n\ + mov.l r14,@-r15\n\ + sts.l pr,@-r15\n\ + mova .L22,r0\n\ + mov.l .L22,r12\n\ + add r0,r12\n\ + mova .L24,r0\n\ + mov.l .L24,r1\n\ + add r0,r1\n\ + jsr @r1\n\ + mov r15,r14\n\ + bra 1f\n\ + nop\n\ + .align 2\n\ +.L22:\n\ + .long _GLOBAL_OFFSET_TABLE_\n\ +.L24:\n\ + .long __pthread_initialize_minimal_internal@PLT\n\ +1:\n\ + ALIGN\n\ + END_INIT\n\ +\n\ +/*@_init_PROLOG_ENDS*/\n\ +\n\ +/*@_init_EPILOG_BEGINS*/\n\ + .section .init\n\ + mov r14,r15\n\ + lds.l @r15+,pr\n\ + mov.l @r15+,r14\n\ + rts \n\ + mov.l @r15+,r12\n\ + END_INIT\n\ + \n\ +/*@_init_EPILOG_ENDS*/\n\ +\n\ +/*@_fini_PROLOG_BEGINS*/\n\ + .section .fini\n\ + .align 5\n\ + .global _fini\n\ + .type _fini,@function\n\ +_fini:\n\ + mov.l r12,@-r15\n\ + mov.l r14,@-r15\n\ + sts.l pr,@-r15\n\ + mova .L27,r0\n\ + mov.l .L27,r12\n\ + add r0,r12\n\ + mov r15,r14\n\ + ALIGN\n\ + END_FINI\n\ + bra 1f\n\ + nop\n\ + .align 2\n\ +.L27:\n\ + .long _GLOBAL_OFFSET_TABLE_\n\ +1:\n\ +/*@_fini_PROLOG_ENDS*/\n\ +\n\ +/*@_fini_EPILOG_BEGINS*/\n\ + .section .fini\n\ + mov r14,r15\n\ + lds.l @r15+,pr\n\ + mov.l @r15+,r14\n\ + rts \n\ + mov.l @r15+,r12\n\ +\n\ + END_FINI\n\ + \n\ +/*@_fini_EPILOG_ENDS*/\n\ +\n\ +/*@TRAILER_BEGINS*/\n\ +"); diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-vfork.S new file mode 100644 index 000000000..54f2281d7 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-vfork.S @@ -0,0 +1,65 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#define _ERRNO_H 1 +#include <bits/errno.h> +#include <tcb-offsets.h> + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + /* Save the PID value. */ + stc gbr, r2 + mov.w .L2, r0 + mov.l @(r0,r2), r4 + neg r4, r1 + mov.l r1, @(r0,r2) + + mov.w .L1, r3 + trapa #0x10 + mov r0, r1 + + /* Restore the old PID value in the parent. */ + tst r0, r0 + bt/s 2f + stc gbr, r2 + mov.w .L2, r0 + mov.l r4, @(r0,r2) + mov r1, r0 +2: + mov #-12, r2 + shad r2, r1 + not r1, r1 // r1=0 means r0 = -1 to -4095 + tst r1, r1 // i.e. error in linux + bf .Lpseudo_end + SYSCALL_ERROR_HANDLER +.Lpseudo_end: + rts + nop +.L1: + .word __NR_vfork +.L2: + .word PID - TLS_PRE_TCB_SIZE + +PSEUDO_END (__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S new file mode 100644 index 000000000..4a6059aef --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S @@ -0,0 +1,216 @@ +/* Copyright (C) 2003, 2004, 2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelbarrier.h> +#include "lowlevel-atomic.h" + + .text + + .globl pthread_barrier_wait + .type pthread_barrier_wait,@function + .align 5 +pthread_barrier_wait: + mov.l r9, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + mov r4, r8 + + /* Get the mutex. */ + mov #0, r3 + mov #1, r4 + CMPXCHG (r3, @(MUTEX,r8), r4, r2) + bf 1f + + /* One less waiter. If this was the last one needed wake + everybody. */ +2: + mov.l @(LEFT,r8), r0 + add #-1, r0 + mov.l r0, @(LEFT,r8) + tst r0, r0 + bt 3f + + /* There are more threads to come. */ + mov.l @(CURR_EVENT,r8), r6 + + /* Release the mutex. */ + DEC (@(MUTEX,r8), r2) + tst r2, r2 + bf 6f +7: + /* Wait for the remaining threads. The call will return immediately + if the CURR_EVENT memory has meanwhile been changed. */ + mov r8, r4 +#if CURR_EVENT != 0 + add #CURR_EVENT, r4 +#endif +#if FUTEX_WAIT == 0 + mov.l @(PRIVATE,r8), r5 +#else + mov #FUTEX_WAIT, r5 + mov.l @(PRIVATE,r8), r0 + or r0, r5 +#endif + mov #0, r7 +8: + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + /* Don't return on spurious wakeups. The syscall does not change + any register except r0 so there is no need to reload any of + them. */ + mov.l @(CURR_EVENT,r8), r0 + cmp/eq r0, r6 + bt 8b + + /* Increment LEFT. If this brings the count back to the + initial count unlock the object. */ + mov #1, r3 + mov.l @(INIT_COUNT,r8), r4 + XADD (r3, @(LEFT,r8), r2, r5) + add #-1, r4 + cmp/eq r2, r4 + bf 10f + + /* Release the mutex. We cannot release the lock before + waking the waiting threads since otherwise a new thread might + arrive and gets waken up, too. */ + DEC (@(MUTEX,r8), r2) + tst r2, r2 + bf 9f + +10: + mov #0, r0 /* != PTHREAD_BARRIER_SERIAL_THREAD */ + lds.l @r15+, pr + mov.l @r15+, r8 + rts + mov.l @r15+, r9 + +3: + /* The necessary number of threads arrived. */ + mov.l @(CURR_EVENT,r8), r1 + add #1, r1 + mov.l r1, @(CURR_EVENT,r8) + + /* Wake up all waiters. The count is a signed number in the kernel + so 0x7fffffff is the highest value. */ + mov.l .Lall, r6 + mov r8, r4 +#if CURR_EVENT != 0 + add #CURR_EVENT, r4 +#endif + mov #0, r7 + mov #FUTEX_WAKE, r5 + mov.l @(PRIVATE,r8), r0 + or r0, r5 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + /* Increment LEFT. If this brings the count back to the + initial count unlock the object. */ + mov #1, r3 + mov.l @(INIT_COUNT,r8), r4 + XADD (r3, @(LEFT,r8), r2, r5) + add #-1, r4 + cmp/eq r2, r4 + bf 5f + + /* Release the mutex. */ + DEC (@(MUTEX,r8), r2) + tst r2, r2 + bf 4f +5: + mov #-1, r0 /* == PTHREAD_BARRIER_SERIAL_THREAD */ + lds.l @r15+, pr + mov.l @r15+, r8 + rts + mov.l @r15+, r9 + +1: + mov.l @(PRIVATE,r8), r6 + mov #LLL_SHARED, r0 + extu.b r0, r0 + xor r0, r6 + mov r2, r4 + mov r8, r5 + mov.l .Lwait0, r1 + bsrf r1 + add #MUTEX, r5 +.Lwait0b: + bra 2b + nop + +4: + mov.l @(PRIVATE,r8), r5 + mov #LLL_SHARED, r0 + extu.b r0, r0 + xor r0, r5 + mov r8, r4 + mov.l .Lwake0, r1 + bsrf r1 + add #MUTEX, r4 +.Lwake0b: + bra 5b + nop + +6: + mov r6, r9 + mov.l @(PRIVATE,r8), r5 + mov #LLL_SHARED, r0 + extu.b r0, r0 + xor r0, r5 + mov r8, r4 + mov.l .Lwake1, r1 + bsrf r1 + add #MUTEX, r4 +.Lwake1b: + bra 7b + mov r9, r6 + +9: + mov r6, r9 + mov.l @(PRIVATE,r8), r5 + mov #LLL_SHARED, r0 + extu.b r0, r0 + xor r0, r5 + mov r8, r4 + mov.l .Lwake2, r1 + bsrf r1 + add #MUTEX, r4 +.Lwake2b: + bra 10b + mov r9, r6 + + .align 2 +.Lall: + .long 0x7fffffff +.Lwait0: + .long __lll_lock_wait-.Lwait0b +.Lwake0: + .long __lll_unlock_wake-.Lwake0b +.Lwake1: + .long __lll_unlock_wake-.Lwake1b +.Lwake2: + .long __lll_unlock_wake-.Lwake2b + .size pthread_barrier_wait,.-pthread_barrier_wait diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S new file mode 100644 index 000000000..0884c1381 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S @@ -0,0 +1,263 @@ +/* Copyright (C) 2003, 2004, 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelcond.h> +#include <bits/kernel-features.h> +#include <pthread-pi-defines.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include "lowlevel-atomic.h" + + .text + + /* int pthread_cond_broadcast (pthread_cond_t *cond) */ + .globl __pthread_cond_broadcast + .type __pthread_cond_broadcast, @function + .hidden __pthread_cond_broadcast + .align 5 +__pthread_cond_broadcast: + mov.l r10, @-r15 + mov.l r9, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + mov r4, r8 + + /* Get internal lock. */ + mov #0, r3 + mov #1, r4 +#if cond_lock != 0 + CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else + CMPXCHG (r3, @r8, r4, r2) +#endif + bf 1f +2: + mov.l @(total_seq+4,r8),r0 + mov.l @(total_seq,r8),r1 + mov.l @(wakeup_seq+4,r8), r2 + cmp/hi r2, r0 + bt 3f + cmp/hi r0, r2 + bt 4f + mov.l @(wakeup_seq,r8), r2 + cmp/hi r2, r1 + bf 4f + +3: + /* Cause all currently waiting threads to recognize they are + woken up. */ + mov.l r1, @(wakeup_seq,r8) + mov.l r0, @(wakeup_seq+4,r8) + mov.l r1, @(woken_seq,r8) + mov.l r0, @(woken_seq+4,r8) + mov.l @(broadcast_seq,r8), r2 + add #1, r2 + mov.l r2, @(broadcast_seq,r8) + add r1, r1 + mov r1, r10 + mov.l r10, @(cond_futex,r8) + + /* Get the address of the mutex used. */ + mov.l @(dep_mutex,r8), r9 + + /* Unlock. */ +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bf 7f + +8: + /* Don't use requeue for pshared condvars. */ + mov #-1, r0 + cmp/eq r0, r9 + mov r8, r4 + bt/s 9f + add #cond_futex, r4 + + /* XXX: The kernel only supports FUTEX_CMP_REQUEUE to the same + type of futex (private resp. shared). */ + mov.l @(MUTEX_KIND,r9), r0 + tst #(PI_BIT|PS_BIT), r0 + bf 9f + + /* Wake up all threads. */ +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_CMP_REQUEUE, r0 + or r0, r5 +#endif + mov #1, r6 + mov #-1, r7 + shlr r7 /* r7 = 0x7fffffff */ + mov r9, r0 +# if MUTEX_FUTEX != 0 + add #MUTEX_FUTEX, r0 +# endif + mov r10, r1 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x16 + SYSCALL_INST_PAD + + /* For any kind of error, which mainly is EAGAIN, we try again + with WAKE. The general test also covers running on old + kernels. */ + mov r0, r1 + mov #-12, r2 + shad r2, r1 + not r1, r1 + tst r1, r1 + mov r8, r4 + bt/s 9f + add #cond_futex, r4 + +10: + mov #0, r0 + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r9 + rts + mov.l @r15+, r10 + +4: + /* Unlock. */ +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bf 5f +6: + mov #0, r0 + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r9 + rts + mov.l @r15+, r10 + +1: + /* Initial locking failed. */ + mov r8, r5 +#if cond_lock != 0 + add #cond_lock, r5 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r6 + mov #LLL_SHARED, r6 +99: + extu.b r6, r6 + mov.l .Lwait5, r1 + bsrf r1 + mov r2, r4 +.Lwait5b: + bra 2b + nop + +5: + /* Unlock in loop requires wakeup. */ + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r5 + mov #LLL_SHARED, r5 +99: + mov.l .Lwake5, r1 + bsrf r1 + extu.b r5, r5 +.Lwake5b: + bra 6b + nop + +7: + /* Unlock in loop requires wakeup. */ + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov #-1, r0 + cmp/eq r0, r9 + bf/s 99f + mov #LLL_PRIVATE, r5 + mov #LLL_SHARED, r5 +99: + mov.l .Lwake6, r1 + bsrf r1 + extu.b r5, r5 +.Lwake6b: + bra 8b + nop + +9: + mov #-1, r0 + cmp/eq r0, r9 + bt/s 99f + mov #FUTEX_WAKE, r5 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_WAKE, r0 + or r0, r5 +#endif +99: + mov #-1, r6 + shlr r6 /* r6 = 0x7fffffff */ + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + bra 10b + nop + +#ifndef __ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif + + .align 2 +.Lwait5: + .long __lll_lock_wait-.Lwait5b +.Lwake5: + .long __lll_unlock_wake-.Lwake5b +.Lwake6: + .long __lll_unlock_wake-.Lwake6b + .size __pthread_cond_broadcast, .-__pthread_cond_broadcast +weak_alias (__pthread_cond_broadcast, pthread_cond_broadcast) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S new file mode 100644 index 000000000..d2d7c19dc --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S @@ -0,0 +1,190 @@ +/* Copyright (C) 2003, 2004, 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelcond.h> +#include <bits/kernel-features.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include "lowlevel-atomic.h" + + .text + + /* int pthread_cond_signal (pthread_cond_t *cond) */ + .globl __pthread_cond_signal + .type __pthread_cond_signal, @function + .hidden __pthread_cond_signal + .align 5 +__pthread_cond_signal: + mov.l r8, @-r15 + sts.l pr, @-r15 + mov r4, r8 + + /* Get internal lock. */ + mov #0, r3 + mov #1, r4 +#if cond_lock != 0 + CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else + CMPXCHG (r3, @r8, r4, r2) +#endif + bf 1f +2: + mov.l @(total_seq+4,r8),r0 + mov.l @(total_seq,r8),r1 + mov.l @(wakeup_seq+4,r8), r2 + cmp/hi r2, r0 + bt 3f + cmp/hi r0, r2 + bt 4f + mov.l @(wakeup_seq,r8), r2 + cmp/hi r2, r1 + bf 4f + +3: + /* Bump the wakeup number. */ + mov #1, r2 + mov #0, r3 + clrt + mov.l @(wakeup_seq,r8),r0 + mov.l @(wakeup_seq+4,r8),r1 + addc r2, r0 + addc r3, r1 + mov.l r0,@(wakeup_seq,r8) + mov.l r1,@(wakeup_seq+4,r8) + mov.l @(cond_futex,r8),r0 + add r2, r0 + mov.l r0,@(cond_futex,r8) + + /* Wake up one thread. */ + mov r8, r4 + add #cond_futex, r4 + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bt/s 99f + mov #FUTEX_WAKE_OP, r5 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_WAKE_OP, r0 + or r0, r5 +#endif +99: + mov #1, r6 + mov #0, r7 + mov r8, r0 + add #cond_lock, r0 + mov.l .Lfutexop, r1 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + /* For any kind of error, we try again with WAKE. + The general test also covers running on old kernels. */ + mov r0, r1 + mov #-12, r2 + shad r2, r1 + not r1, r1 + tst r1, r1 + bt 7f + +6: + mov #0, r0 + lds.l @r15+, pr + rts + mov.l @r15+, r8 + +#ifndef __ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif + .align 2 +.Lfutexop: + .long FUTEX_OP_CLEAR_WAKE_IF_GT_ONE + +7: + /* r5 should be either FUTEX_WAKE_OP or + FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG from the previous syscall. */ + mov #(FUTEX_WAKE ^ FUTEX_WAKE_OP), r0 + xor r0, r5 + trapa #0x14 + SYSCALL_INST_PAD + +4: + /* Unlock. */ +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bt 6b + +5: + /* Unlock in loop requires wakeup. */ + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r5 + mov #LLL_SHARED, r5 +99: + mov.l .Lwake4, r1 + bsrf r1 + extu.b r5, r5 +.Lwake4b: + bra 6b + nop + +1: + /* Initial locking failed. */ + mov r8, r5 +#if cond_lock != 0 + add #cond_lock, r5 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r6 + mov #LLL_SHARED, r6 +99: + extu.b r6, r6 + mov.l .Lwait4, r1 + bsrf r1 + mov r2, r4 +.Lwait4b: + bra 2b + nop + + .align 2 +.Lwait4: + .long __lll_lock_wait-.Lwait4b +.Lwake4: + .long __lll_unlock_wake-.Lwake4b + .size __pthread_cond_signal, .-__pthread_cond_signal +weak_alias (__pthread_cond_signal, pthread_cond_signal) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S new file mode 100644 index 000000000..7db789f73 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S @@ -0,0 +1,861 @@ +/* Copyright (C) 2003, 2004, 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelcond.h> +#include <pthread-errnos.h> +#include <bits/kernel-features.h> +#include <tcb-offsets.h> +#include "lowlevel-atomic.h" + + .text + +/* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime) */ + .globl __pthread_cond_timedwait + .type __pthread_cond_timedwait, @function + .hidden __pthread_cond_timedwait + .align 5 +__pthread_cond_timedwait: +.LSTARTCODE: + mov.l r8, @-r15 +.Lpush_r8: + mov.l r9, @-r15 +.Lpush_r9: + mov.l r10, @-r15 +.Lpush_r10: + mov.l r11, @-r15 +.Lpush_r11: + mov.l r12, @-r15 +.Lpush_r12: + mov.l r13, @-r15 +.Lpush_r13: + sts.l pr, @-r15 +.Lpush_pr: + add #-64, r15 +.Lalloc: + mov r4, r8 + mov r5, r9 + mov r6, r13 +#ifdef __PIC__ + mova .Lgot0, r0 + mov.l .Lgot0, r12 + add r0, r12 +#endif + + mov.l @(4,r13), r0 + mov.l .L1g, r1 + cmp/hs r1, r0 + bf 0f + bra 18f + mov #EINVAL, r0 +0: + /* Get internal lock. */ + mov #0, r3 + mov #1, r4 +#if cond_lock != 0 + CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else + CMPXCHG (r3, @r8, r4, r2) +#endif + bt 2f + bra 1f + nop +#ifdef __PIC__ + .align 2 +.Lgot0: + .long _GLOBAL_OFFSET_TABLE_ +#endif + +2: + /* Store the reference to the mutex. If there is already a + different value in there this is a bad user bug. */ + mov.l @(dep_mutex,r8),r0 + cmp/eq #-1, r0 + bt 17f + mov.l r9, @(dep_mutex,r8) + +17: + /* Unlock the mutex. */ + mov.l .Lmunlock1, r1 + mov #0, r5 + bsrf r1 + mov r9, r4 +.Lmunlock1b: + + tst r0, r0 + bt 0f + bra 16f + nop +0: + mov #1, r2 + mov #0, r3 + + clrt + mov.l @(total_seq,r8),r0 + mov.l @(total_seq+4,r8),r1 + addc r2, r0 + addc r3, r1 + mov.l r0,@(total_seq,r8) + mov.l r1,@(total_seq+4,r8) + mov.l @(cond_futex,r8), r0 + add r2, r0 + mov.l r0, @(cond_futex,r8) + mov #(1 << nwaiters_shift), r2 + mov.l @(cond_nwaiters,r8), r0 + add r2, r0 + mov.l r0, @(cond_nwaiters,r8) + + /* Get and store current wakeup_seq value. */ + mov.l @(wakeup_seq,r8), r10 + mov.l @(wakeup_seq+4,r8), r11 + mov.l @(broadcast_seq,r8), r0 + mov.l r0, @(4,r15) + +8: + /* Get current time. */ +#ifdef __NR_clock_gettime + /* Get the clock number. */ + mov.l @(cond_nwaiters,r8), r4 + mov #((1 << nwaiters_shift) - 1), r0 + and r0, r4 + /* Only clocks 0 and 1 are allowed. Both are handled in the + kernel. */ + mov r15, r5 + add #16, r5 + mov.w .L__NR_clock_gettime, r3 + trapa #0x12 + SYSCALL_INST_PAD +# ifndef __ASSUME_POSIX_TIMERS + cmp/eq #-ENOSYS, r0 + bt 19f +# endif + + /* Compute relative timeout. */ + mov.l @r13, r2 + mov.l @(4,r13), r3 + mov.l @(16,r15), r0 + bra 0f + mov.l @(20,r15), r1 +.L__NR_clock_gettime: + .word __NR_clock_gettime + +# ifndef __ASSUME_POSIX_TIMERS +19: + mov r15, r4 + add #16, r4 + mov #0, r5 + mov #__NR_gettimeofday, r3 + trapa #0x12 + SYSCALL_INST_PAD + + /* Compute relative timeout. */ + mov.l @(20,r15), r0 + mov.w .L1k, r1 + dmulu.l r0, r1 /* Micro seconds to nano seconds. */ + mov.l @r13, r2 + mov.l @(4,r13), r3 + mov.l @(16,r15), r0 + sts macl, r1 +#endif +0: +#else + mov r15, r4 + add #16, r4 + mov #0, r5 + mov #__NR_gettimeofday, r3 + trapa #0x12 + SYSCALL_INST_PAD + + /* Compute relative timeout. */ + mov.l @(20,r15), r0 + mov.w .L1k, r1 + dmulu.l r0, r1 /* Micro seconds to nano seconds. */ + mov.l @r13, r2 + mov.l @(4,r13), r3 + mov.l @(16,r15), r0 + sts macl, r1 +#endif + sub r0, r2 + clrt + subc r1, r3 + bf 12f + mov.l .L1g, r1 + add r1, r3 + add #-1, r2 +12: + mov #-ETIMEDOUT, r1 + mov.l r1, @(12,r15) + cmp/pz r2 + bf 6f /* Time is already up. */ + + /* Store relative timeout. */ + mov.l r2, @(16,r15) + mov.l r3, @(20,r15) + mov.l @(cond_futex,r8), r1 + mov.l r1, @(8,r15) + + /* Unlock. */ +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bt 4f + bra 3f + nop +4: +.LcleanupSTART: + mov.l .Lenable1, r1 + bsrf r1 + nop +.Lenable1b: + mov.l r0, @r15 + + mov r15, r7 + add #16, r7 + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bt/s 99f + mov #FUTEX_WAIT, r5 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_WAIT, r0 + or r0, r5 +#endif +99: + mov.l @(8,r15), r6 + mov r8, r4 + add #cond_futex, r4 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + mov.l r0, @(12,r15) + + mov.l .Ldisable1, r1 + bsrf r1 + mov.l @r15, r4 +.Ldisable1b: +.LcleanupEND: + + /* Lock. */ + mov #0, r3 + mov #1, r4 +#if cond_lock != 0 + CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else + CMPXCHG (r3, @r8, r4, r2) +#endif + bf 5f +6: + mov.l @(broadcast_seq,r8), r0 + mov.l @(4,r15), r1 + cmp/eq r0, r1 + bf 23f + + mov.l @(woken_seq,r8), r0 + mov.l @(woken_seq+4,r8), r1 + + mov.l @(wakeup_seq,r8), r2 + mov.l @(wakeup_seq+4,r8), r3 + + cmp/eq r3, r11 + bf 7f + cmp/eq r2, r10 + bt 15f +7: + cmp/eq r1, r3 + bf 9f + cmp/eq r0, r2 + bf 9f +15: + mov.l @(12,r15),r0 + cmp/eq #-ETIMEDOUT, r0 + bf 8b + + mov #1, r2 + mov #0, r3 + + clrt + mov.l @(wakeup_seq,r8),r0 + mov.l @(wakeup_seq+4,r8),r1 + addc r2, r0 + addc r3, r1 + mov.l r0,@(wakeup_seq,r8) + mov.l r1,@(wakeup_seq+4,r8) + mov.l @(cond_futex,r8),r0 + add r2, r0 + mov.l r0,@(cond_futex,r8) + mov #ETIMEDOUT, r0 + bra 14f + mov.l r0, @(24,r15) + +23: + mov #0, r0 + bra 24f + mov.l r0, @(24,r15) + +9: + mov #0, r0 + mov.l r0, @(24,r15) +14: + mov #1, r2 + mov #0, r3 + + clrt + mov.l @(woken_seq,r8),r0 + mov.l @(woken_seq+4,r8),r1 + addc r2, r0 + addc r3, r1 + mov.l r0,@(woken_seq,r8) + mov.l r1,@(woken_seq+4,r8) + +24: + mov #(1 << nwaiters_shift), r2 + mov.l @(cond_nwaiters,r8),r0 + sub r2, r0 + mov.l r0,@(cond_nwaiters,r8) + + /* Wake up a thread which wants to destroy the condvar object. */ + mov.l @(total_seq,r8),r0 + mov.l @(total_seq+4,r8),r1 + and r1, r0 + not r0, r0 + cmp/eq #0, r0 + bf/s 25f + mov #((1 << nwaiters_shift) - 1), r1 + not r1, r1 + mov.l @(cond_nwaiters,r8),r0 + tst r1, r0 + bf 25f + + mov r8, r4 + add #cond_nwaiters, r4 + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bt/s 99f + mov #FUTEX_WAKE, r5 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_WAKE, r0 + or r0, r5 +#endif +99: + mov #1, r6 + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + +25: +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bf 10f + +11: + mov r9, r4 + mov.l .Lmlocki1, r1 + bsrf r1 + nop +.Lmlocki1b: + + /* We return the result of the mutex_lock operation if it failed. */ + tst r0, r0 + bf 18f + mov.l @(24,r15), r0 + +18: + add #64, r15 + lds.l @r15+, pr + mov.l @r15+, r13 + mov.l @r15+, r12 + mov.l @r15+, r11 + mov.l @r15+, r10 + mov.l @r15+, r9 + rts + mov.l @r15+, r8 + +#ifndef __ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif +.L1k: + .word 1000 + .align 2 +.Lmunlock1: + .long __pthread_mutex_unlock_usercnt-.Lmunlock1b +.Lenable1: + .long __pthread_enable_asynccancel-.Lenable1b +.Ldisable1: + .long __pthread_disable_asynccancel-.Ldisable1b +.Lmlocki1: + .long __pthread_mutex_cond_lock-.Lmlocki1b +.L1g: + .long 1000000000 + +1: + /* Initial locking failed. */ + mov r8, r5 +#if cond_lock != 0 + add #cond_lock, r5 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r6 + mov #LLL_SHARED, r6 +99: + extu.b r6, r6 + mov.l .Lwait2, r1 + bsrf r1 + mov r2, r4 +.Lwait2b: + bra 2b + nop + +3: + /* Unlock in loop requires wakeup. */ + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r5 + mov #LLL_SHARED, r5 +99: + mov.l .Lmwait2, r1 + bsrf r1 + extu.b r5, r5 +.Lmwait2b: + bra 4b + nop + +5: + /* Locking in loop failed. */ + mov r8, r5 +#if cond_lock != 0 + add #cond_lock, r5 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r6 + mov #LLL_SHARED, r6 +99: + extu.b r6, r6 + mov.l .Lwait3, r1 + bsrf r1 + mov r2, r4 +.Lwait3b: + bra 6b + nop + +10: + /* Unlock after loop requires wakeup. */ + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r5 + mov #LLL_SHARED, r5 +99: + mov.l .Lmwait3, r1 + bsrf r1 + extu.b r5, r5 +.Lmwait3b: + bra 11b + nop + +16: + /* The initial unlocking of the mutex failed. */ + mov.l r0, @(24,r15) +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bf 17f + + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r5 + mov #LLL_SHARED, r5 +99: + mov.l .Lmwait4, r1 + bsrf r1 + extu.b r5, r5 +.Lmwait4b: +17: + bra 18b + mov.l @(24,r15), r0 + + .align 2 +.Lwait2: + .long __lll_lock_wait-.Lwait2b +.Lmwait2: + .long __lll_unlock_wake-.Lmwait2b +.Lwait3: + .long __lll_lock_wait-.Lwait3b +.Lmwait3: + .long __lll_unlock_wake-.Lmwait3b +.Lmwait4: + .long __lll_unlock_wake-.Lmwait4b + .size __pthread_cond_timedwait, .-__pthread_cond_timedwait +weak_alias (__pthread_cond_timedwait, pthread_cond_timedwait) + + + .type __condvar_tw_cleanup, @function +__condvar_tw_cleanup: + mov r4, r11 + + /* Get internal lock. */ + mov #0, r3 + mov #1, r4 +#if cond_lock != 0 + CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else + CMPXCHG (r3, @r8, r4, r2) +#endif + bt 1f + nop + + mov r8, r5 +#if cond_lock != 0 + add #cond_lock, r5 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r6 + mov #LLL_SHARED, r6 +99: + extu.b r6, r6 + mov.l .Lwait5, r1 + bsrf r1 + mov r2, r4 +.Lwait5b: + +1: + mov.l @(broadcast_seq,r8), r0 + mov.l @(4,r15), r1 + cmp/eq r0, r1 + bf 3f + + mov #1, r2 + mov #0, r3 + + /* We increment the wakeup_seq counter only if it is lower than + total_seq. If this is not the case the thread was woken and + then canceled. In this case we ignore the signal. */ + mov.l @(total_seq+4,r8), r0 + mov.l @(wakeup_seq+4,r8), r1 + cmp/hi r1, r0 + bt/s 6f + cmp/hi r0, r1 + bt 7f + mov.l @(total_seq,r8), r0 + mov.l @(wakeup_seq,r8), r1 + cmp/hs r0, r1 + bt 7f + +6: + clrt + mov.l @(wakeup_seq,r8),r0 + mov.l @(wakeup_seq+4,r8),r1 + addc r2, r0 + addc r3, r1 + mov.l r0,@(wakeup_seq,r8) + mov.l r1,@(wakeup_seq+4,r8) + mov.l @(cond_futex,r8),r0 + add r2, r0 + mov.l r0,@(cond_futex,r8) + +7: + clrt + mov.l @(woken_seq,r8),r0 + mov.l @(woken_seq+4,r8),r1 + addc r2, r0 + addc r3, r1 + mov.l r0,@(woken_seq,r8) + mov.l r1,@(woken_seq+4,r8) + +3: + mov #(1 << nwaiters_shift), r2 + mov.l @(cond_nwaiters,r8),r0 + sub r2, r0 + mov.l r0,@(cond_nwaiters,r8) + + /* Wake up a thread which wants to destroy the condvar object. */ + mov #0, r10 + mov.l @(total_seq,r8),r0 + mov.l @(total_seq+4,r8),r1 + and r1, r0 + not r0, r0 + cmp/eq #0, r0 + bf/s 4f + mov #((1 << nwaiters_shift) - 1), r1 + not r1, r1 + mov.l @(cond_nwaiters,r8),r0 + tst r1, r0 + bf 4f + + mov r8, r4 + add #cond_nwaiters, r4 + mov #FUTEX_WAKE, r5 + mov #1, r6 + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + mov #1, r10 + +4: +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bt 2f + + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r5 + mov #LLL_SHARED, r5 +99: + mov.l .Lmwait5, r1 + bsrf r1 + extu.b r5, r5 +.Lmwait5b: + +2: + /* Wake up all waiters to make sure no signal gets lost. */ + tst r10, r10 + bf/s 5f + mov r8, r4 + add #cond_futex, r4 + mov #FUTEX_WAKE, r5 + mov #-1, r6 + shlr r6 /* r6 = 0x7fffffff */ + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + +5: + mov.l .Lmlocki5, r1 + bsrf r1 + mov r9, r4 +.Lmlocki5b: + +.LcallUR: + mov.l .Lresume, r1 +#ifdef __PIC__ + add r12, r1 +#endif + jsr @r1 + mov r11, r4 + sleep + + .align 2 +.Lwait5: + .long __lll_lock_wait-.Lwait5b +.Lmwait5: + .long __lll_unlock_wake-.Lmwait5b +.Lmlocki5: + .long __pthread_mutex_cond_lock-.Lmlocki5b +.Lresume: +#ifdef __PIC__ + .long _Unwind_Resume@GOTOFF +#else + .long _Unwind_Resume +#endif +.LENDCODE: + .size __condvar_tw_cleanup, .-__condvar_tw_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte 0xff ! @LPStart format (omit) + .byte 0xff ! @TType format (omit) + .byte 0x0b ! call-site format + ! DW_EH_PE_sdata4 + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .ualong .LcleanupSTART-.LSTARTCODE + .ualong .LcleanupEND-.LcleanupSTART + .ualong __condvar_tw_cleanup-.LSTARTCODE + .uleb128 0 + .ualong .LcallUR-.LSTARTCODE + .ualong .LENDCODE-.LcallUR + .ualong 0 + .uleb128 0 +.Lcstend: + + .section .eh_frame,"a",@progbits +.LSTARTFRAME: + .ualong .LENDCIE-.LSTARTCIE ! Length of the CIE. +.LSTARTCIE: + .ualong 0 ! CIE ID. + .byte 1 ! Version number. +#ifdef SHARED + .string "zPLR" ! NUL-terminated augmentation + ! string. +#else + .string "zPL" ! NUL-terminated augmentation + ! string. +#endif + .uleb128 1 ! Code alignment factor. + .sleb128 -4 ! Data alignment factor. + .byte 0x11 ! Return address register + ! column. +#ifdef SHARED + .uleb128 7 ! Augmentation value length. + .byte 0x9b ! Personality: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4 + ! + DW_EH_PE_indirect + .ualong DW.ref.__gcc_personality_v0-. + .byte 0x1b ! LSDA Encoding: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4. + .byte 0x1b ! FDE Encoding: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4. +#else + .uleb128 6 ! Augmentation value length. + .byte 0x0 ! Personality: absolute + .ualong __gcc_personality_v0 + .byte 0x0 ! LSDA Encoding: absolute +#endif + .byte 0x0c ! DW_CFA_def_cfa + .uleb128 0xf + .uleb128 0 + .align 2 +.LENDCIE: + + .ualong .LENDFDE-.LSTARTFDE ! Length of the FDE. +.LSTARTFDE: + .ualong .LSTARTFDE-.LSTARTFRAME ! CIE pointer. +#ifdef SHARED + .ualong .LSTARTCODE-. ! PC-relative start address + ! of the code. +#else + .ualong .LSTARTCODE ! Start address of the code. +#endif + .ualong .LENDCODE-.LSTARTCODE ! Length of the code. + .uleb128 4 ! Augmentation size +#ifdef SHARED + .ualong .LexceptSTART-. +#else + .ualong .LexceptSTART +#endif + .byte 0x4 + .ualong .Lpush_r8-.LSTARTCODE + .byte 0xe + .uleb128 4 + .byte 0x88 + .uleb128 1 + .byte 0x4 + .ualong .Lpush_r9-.Lpush_r8 + .byte 0xe + .uleb128 8 + .byte 0x89 + .uleb128 2 + .byte 0x4 + .ualong .Lpush_r10-.Lpush_r9 + .byte 0xe + .uleb128 12 + .byte 0x8a + .uleb128 3 + .byte 0x4 + .ualong .Lpush_r11-.Lpush_r10 + .byte 0xe + .uleb128 16 + .byte 0x8b + .uleb128 4 + .byte 0x4 + .ualong .Lpush_r12-.Lpush_r11 + .byte 0xe + .uleb128 20 + .byte 0x8c + .uleb128 5 + .byte 0x4 + .ualong .Lpush_r13-.Lpush_r12 + .byte 0xe + .uleb128 24 + .byte 0x8d + .uleb128 6 + .byte 0x4 + .ualong .Lpush_pr-.Lpush_r13 + .byte 0xe + .uleb128 28 + .byte 0x91 + .uleb128 7 + .byte 0x4 + .ualong .Lalloc-.Lpush_pr + .byte 0xe + .uleb128 92 + .align 2 +.LENDFDE: + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 4 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: + .long __gcc_personality_v0 +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S new file mode 100644 index 000000000..f4f22b645 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S @@ -0,0 +1,754 @@ +/* Copyright (C) 2003, 2004, 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelcond.h> +#include <tcb-offsets.h> +#include <bits/kernel-features.h> +#include "lowlevel-atomic.h" + + .text + +/* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */ + .globl __pthread_cond_wait + .type __pthread_cond_wait, @function + .hidden __pthread_cond_wait + .align 5 +__pthread_cond_wait: +.LSTARTCODE: + mov.l r8, @-r15 +.Lpush_r8: + mov.l r9, @-r15 +.Lpush_r9: + mov.l r10, @-r15 +.Lpush_r10: + mov.l r11, @-r15 +.Lpush_r11: + mov.l r12, @-r15 +.Lpush_r12: + sts.l pr, @-r15 +.Lpush_pr: + add #-48, r15 +.Lalloc: + mov r4, r8 + mov r5, r9 +#ifdef __PIC__ + mova .Lgot0, r0 + mov.l .Lgot0, r12 + add r0, r12 +#endif + + /* Get internal lock. */ + mov #0, r3 + mov #1, r4 +#if cond_lock != 0 + CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else + CMPXCHG (r3, @r8, r4, r2) +#endif + bt 2f + bra 1f + nop +#ifdef __PIC__ + .align 2 +.Lgot0: + .long _GLOBAL_OFFSET_TABLE_ +#endif + +2: + /* Store the reference to the mutex. If there is already a + different value in there this is a bad user bug. */ + mov.l @(dep_mutex,r8),r0 + cmp/eq #-1, r0 + bt 15f + mov.l r9, @(dep_mutex,r8) + +15: + /* Unlock the mutex. */ + mov.l .Lmunlock0, r1 + mov #0, r5 + bsrf r1 + mov r9, r4 +.Lmunlock0b: + + tst r0, r0 + bt 0f + bra 12f + nop +0: + mov #1, r2 + mov #0, r3 + + clrt + mov.l @(total_seq,r8),r0 + mov.l @(total_seq+4,r8),r1 + addc r2, r0 + addc r3, r1 + mov.l r0,@(total_seq,r8) + mov.l r1,@(total_seq+4,r8) + mov.l @(cond_futex,r8),r0 + add r2, r0 + mov.l r0,@(cond_futex,r8) + mov #(1 << nwaiters_shift), r2 + mov.l @(cond_nwaiters,r8), r0 + add r2, r0 + mov.l r0, @(cond_nwaiters,r8) + + /* Get and store current wakeup_seq value. */ + mov.l @(wakeup_seq,r8), r10 + mov.l @(wakeup_seq+4,r8), r11 + mov.l @(broadcast_seq,r8), r0 + mov.l r0, @(4,r15) + +8: + mov.l @(cond_futex,r8),r0 + mov.l r0, @(8,r15) + + /* Unlock. */ +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bf 3f +4: +.LcleanupSTART: + mov.l .Lenable0, r1 + bsrf r1 + nop +.Lenable0b: + mov.l r0, @r15 + + mov #0, r7 + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bt/s 99f + mov #FUTEX_WAIT, r5 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff0, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_WAIT, r0 + or r0, r5 +#endif +99: + mov.l @(8,r15), r6 + mov r8, r4 + add #cond_futex, r4 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + mov.l .Ldisable0, r1 + bsrf r1 + mov.l @r15, r4 +.Ldisable0b: +.LcleanupEND: + + /* Lock. */ + mov #0, r3 + mov #1, r4 +#if cond_lock != 0 + CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else + CMPXCHG (r3, @r8, r4, r2) +#endif + bf 5f +6: + mov.l @(broadcast_seq,r8), r0 + mov.l @(4,r15), r1 + cmp/eq r0, r1 + bf 16f + + mov.l @(woken_seq,r8), r0 + mov.l @(woken_seq+4,r8), r1 + + mov.l @(wakeup_seq,r8), r2 + mov.l @(wakeup_seq+4,r8), r3 + + cmp/eq r3, r11 + bf 7f + cmp/eq r2, r10 + bt 8b +7: + cmp/eq r1, r3 + bf 9f + cmp/eq r0, r2 + bt 8b +9: + mov #1, r2 + mov #0, r3 + + clrt + mov.l @(woken_seq,r8),r0 + mov.l @(woken_seq+4,r8),r1 + addc r2, r0 + addc r3, r1 + mov.l r0,@(woken_seq,r8) + mov.l r1,@(woken_seq+4,r8) + +16: + mov #(1 << nwaiters_shift), r2 + mov.l @(cond_nwaiters,r8),r0 + sub r2, r0 + mov.l r0,@(cond_nwaiters,r8) + + /* Wake up a thread which wants to destroy the condvar object. */ + mov.l @(total_seq,r8),r0 + mov.l @(total_seq+4,r8),r1 + and r1, r0 + not r0, r0 + cmp/eq #0, r0 + bf/s 17f + mov #((1 << nwaiters_shift) - 1), r1 + not r1, r1 + mov.l @(cond_nwaiters,r8),r0 + tst r1, r0 + bf 17f + + mov r8, r4 + add #cond_nwaiters, r4 + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bt/s 99f + mov #FUTEX_WAKE, r5 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff0, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_WAKE, r0 + or r0, r5 +#endif +99: + mov #1, r6 + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + +17: +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bf 10f + +11: + mov.l .Lmlocki0, r1 + bsrf r1 + mov r9, r4 +.Lmlocki0b: + /* We return the result of the mutex_lock operation. */ + +14: + add #48, r15 + lds.l @r15+, pr + mov.l @r15+, r12 + mov.l @r15+, r11 + mov.l @r15+, r10 + mov.l @r15+, r9 + rts + mov.l @r15+, r8 + +#ifndef __ASSUME_PRIVATE_FUTEX +.Lpfoff0: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif + .align 2 +.Lmunlock0: + .long __pthread_mutex_unlock_usercnt-.Lmunlock0b +.Lenable0: + .long __pthread_enable_asynccancel-.Lenable0b +.Ldisable0: + .long __pthread_disable_asynccancel-.Ldisable0b +.Lmlocki0: + .long __pthread_mutex_cond_lock-.Lmlocki0b + +1: + /* Initial locking failed. */ + mov r8, r5 +#if cond_lock != 0 + add #cond_lock, r5 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r6 + mov #LLL_SHARED, r6 +99: + extu.b r6, r6 + mov.l .Lwait0, r1 + bsrf r1 + mov r2, r4 +.Lwait0b: + bra 2b + nop +3: + /* Unlock in loop requires waekup. */ + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r5 + mov #LLL_SHARED, r5 +99: + mov.l .Lwake0, r1 + bsrf r1 + extu.b r5, r5 +.Lwake0b: + bra 4b + nop + +5: + /* Locking in loop failed. */ + mov r8, r5 +#if cond_lock != 0 + add #cond_lock, r5 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r6 + mov #LLL_SHARED, r6 +99: + extu.b r6, r6 + mov.l .Lwait1, r1 + bsrf r1 + mov r2, r4 +.Lwait1b: + bra 6b + nop + +10: + /* Unlock after loop requires wakeup. */ + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r5 + mov #LLL_SHARED, r5 +99: + mov.l .Lwake1, r1 + bsrf r1 + extu.b r5, r5 +.Lwake1b: + bra 11b + nop + +12: + /* The initial unlocking of the mutex failed. */ + mov.l r0, @(12,r15) +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bf 13f + + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r5 + mov #LLL_SHARED, r5 +99: + mov.l .Lwake2, r1 + bsrf r1 + extu.b r5, r5 +.Lwake2b: + +13: + bra 14b + mov.l @(12,r15), r0 + + .align 2 +.Lwait0: + .long __lll_lock_wait-.Lwait0b +.Lwake0: + .long __lll_unlock_wake-.Lwake0b +.Lwait1: + .long __lll_lock_wait-.Lwait1b +.Lwake1: + .long __lll_unlock_wake-.Lwake1b +.Lwake2: + .long __lll_unlock_wake-.Lwake2b + .size __pthread_cond_wait, .-__pthread_cond_wait +weak_alias (__pthread_cond_wait, pthread_cond_wait) + + + .type __condvar_w_cleanup, @function +__condvar_w_cleanup: + mov r4, r11 + + /* Get internal lock. */ + mov #0, r3 + mov #1, r4 +#if cond_lock != 0 + CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else + CMPXCHG (r3, @r8, r4, r2) +#endif + bt 1f + nop + + mov r8, r5 +#if cond_lock != 0 + add #cond_lock, r5 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r6 + mov #LLL_SHARED, r6 +99: + extu.b r6, r6 + mov.l .Lwait3, r1 + bsrf r1 + mov r2, r4 +.Lwait3b: + +1: + mov.l @(broadcast_seq,r8), r0 + mov.l @(4,r15), r1 + cmp/eq r0, r1 + bf 3f + + mov #1, r2 + mov #0, r3 + + /* We increment the wakeup_seq counter only if it is lower than + total_seq. If this is not the case the thread was woken and + then canceled. In this case we ignore the signal. */ + mov.l @(total_seq+4,r8), r0 + mov.l @(wakeup_seq+4,r8), r1 + cmp/hi r1, r0 + bt/s 6f + cmp/hi r0, r1 + bt 7f + mov.l @(total_seq,r8), r0 + mov.l @(wakeup_seq,r8), r1 + cmp/hs r0, r1 + bt 7f + +6: + clrt + mov.l @(wakeup_seq,r8),r0 + mov.l @(wakeup_seq+4,r8),r1 + addc r2, r0 + addc r3, r1 + mov.l r0,@(wakeup_seq,r8) + mov.l r1,@(wakeup_seq+4,r8) + mov.l @(cond_futex,r8),r0 + add r2, r0 + mov.l r0,@(cond_futex,r8) + +7: + clrt + mov.l @(woken_seq,r8),r0 + mov.l @(woken_seq+4,r8),r1 + addc r2, r0 + addc r3, r1 + mov.l r0,@(woken_seq,r8) + mov.l r1,@(woken_seq+4,r8) + +3: + mov #(1 << nwaiters_shift), r2 + mov.l @(cond_nwaiters,r8),r0 + sub r2, r0 + mov.l r0,@(cond_nwaiters,r8) + + /* Wake up a thread which wants to destroy the condvar object. */ + mov #0, r10 + mov.l @(total_seq,r8),r0 + mov.l @(total_seq+4,r8),r1 + and r1, r0 + not r0, r0 + cmp/eq #0, r0 + bf/s 4f + mov #((1 << nwaiters_shift) - 1), r1 + not r1, r1 + mov.l @(cond_nwaiters,r8),r0 + tst r1, r0 + bf 4f + + mov r8, r4 + add #cond_nwaiters, r4 + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bt/s 99f + mov #FUTEX_WAKE, r5 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff1, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_WAKE, r0 + or r0, r5 +#endif +99: + mov #1, r6 + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + mov #1, r10 + +4: +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bt 2f + + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r5 + mov #LLL_SHARED, r5 +99: + mov.l .Lwake3, r1 + bsrf r1 + extu.b r5, r5 +.Lwake3b: + +2: + /* Wake up all waiters to make sure no signal gets lost. */ + tst r10, r10 + bf/s 5f + mov r8, r4 + add #cond_futex, r4 + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bt/s 99f + mov #FUTEX_WAKE, r5 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff1, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_WAKE, r0 + or r0, r5 +#endif +99: + mov #-1, r6 + shlr r6 /* r6 = 0x7fffffff */ + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + +5: + mov.l .Lmlocki3, r1 + bsrf r1 + mov r9, r4 +.Lmlocki3b: + +.LcallUR: + mov.l .Lresume, r1 +#ifdef __PIC__ + add r12, r1 +#endif + jsr @r1 + mov r11, r4 + sleep + +#ifndef __ASSUME_PRIVATE_FUTEX +.Lpfoff1: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif + .align 2 +.Lwait3: + .long __lll_lock_wait-.Lwait3b +.Lwake3: + .long __lll_unlock_wake-.Lwake3b +.Lmlocki3: + .long __pthread_mutex_cond_lock-.Lmlocki3b +.Lresume: +#ifdef __PIC__ + .long _Unwind_Resume@GOTOFF +#else + .long _Unwind_Resume +#endif +.LENDCODE: + .size __condvar_w_cleanup, .-__condvar_w_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte 0xff ! @LPStart format (omit) + .byte 0xff ! @TType format (omit) + .byte 0x0b ! call-site format + ! DW_EH_PE_sdata4 + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .ualong .LcleanupSTART-.LSTARTCODE + .ualong .LcleanupEND-.LcleanupSTART + .ualong __condvar_w_cleanup-.LSTARTCODE + .uleb128 0 + .ualong .LcallUR-.LSTARTCODE + .ualong .LENDCODE-.LcallUR + .ualong 0 + .uleb128 0 +.Lcstend: + + .section .eh_frame,"a",@progbits +.LSTARTFRAME: + .ualong .LENDCIE-.LSTARTCIE ! Length of the CIE. +.LSTARTCIE: + .ualong 0 ! CIE ID. + .byte 1 ! Version number. +#ifdef SHARED + .string "zPLR" ! NUL-terminated augmentation + ! string. +#else + .string "zPL" ! NUL-terminated augmentation + ! string. +#endif + .uleb128 1 ! Code alignment factor. + .sleb128 -4 ! Data alignment factor. + .byte 0x11 ! Return address register + ! column. +#ifdef SHARED + .uleb128 7 ! Augmentation value length. + .byte 0x9b ! Personality: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4 + ! + DW_EH_PE_indirect + .ualong DW.ref.__gcc_personality_v0-. + .byte 0x1b ! LSDA Encoding: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4. + .byte 0x1b ! FDE Encoding: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4. +#else + .uleb128 6 ! Augmentation value length. + .byte 0x0 ! Personality: absolute + .ualong __gcc_personality_v0 + .byte 0x0 ! LSDA Encoding: absolute +#endif + .byte 0x0c ! DW_CFA_def_cfa + .uleb128 0xf + .uleb128 0 + .align 2 +.LENDCIE: + + .ualong .LENDFDE-.LSTARTFDE ! Length of the FDE. +.LSTARTFDE: + .ualong .LSTARTFDE-.LSTARTFRAME ! CIE pointer. +#ifdef SHARED + .ualong .LSTARTCODE-. ! PC-relative start address + ! of the code. +#else + .ualong .LSTARTCODE ! Start address of the code. +#endif + .ualong .LENDCODE-.LSTARTCODE ! Length of the code. + .uleb128 4 ! Augmentation size +#ifdef SHARED + .ualong .LexceptSTART-. +#else + .ualong .LexceptSTART +#endif + .byte 0x4 + .ualong .Lpush_r8-.LSTARTCODE + .byte 0xe + .uleb128 4 + .byte 0x88 + .uleb128 1 + .byte 0x4 + .ualong .Lpush_r9-.Lpush_r8 + .byte 0xe + .uleb128 8 + .byte 0x89 + .uleb128 2 + .byte 0x4 + .ualong .Lpush_r10-.Lpush_r9 + .byte 0xe + .uleb128 12 + .byte 0x8a + .uleb128 3 + .byte 0x4 + .ualong .Lpush_r11-.Lpush_r10 + .byte 0xe + .uleb128 16 + .byte 0x8b + .uleb128 4 + .byte 0x4 + .ualong .Lpush_r12-.Lpush_r11 + .byte 0xe + .uleb128 20 + .byte 0x8c + .uleb128 5 + .byte 0x4 + .ualong .Lpush_pr-.Lpush_r12 + .byte 0xe + .uleb128 24 + .byte 0x91 + .uleb128 6 + .byte 0x4 + .ualong .Lalloc-.Lpush_pr + .byte 0xe + .uleb128 72 + .align 2 +.LENDFDE: + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 4 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: + .long __gcc_personality_v0 +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S new file mode 100644 index 000000000..da6ecfb49 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S @@ -0,0 +1,263 @@ +/* Copyright (C) 2003, 2004, 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 + 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 <unwindbuf.h> +#include <sysdep.h> +#include <bits/kernel-features.h> +#include <lowlevellock.h> +#include <tcb-offsets.h> +#include "lowlevel-atomic.h" + + + .comm __fork_generation, 4, 4 + + .text + .globl __pthread_once + .type __pthread_once,@function + .hidden __pthread_once + .align 5 + cfi_startproc +__pthread_once: + mov.l @r4, r0 + tst #2, r0 + bt 1f + rts + mov #0, r0 + +1: + mov.l r12, @-r15 + cfi_adjust_cfa_offset (4) + cfi_rel_offset (r12, 0) + mov.l r9, @-r15 + cfi_adjust_cfa_offset (4) + cfi_rel_offset (r9, 0) + mov.l r8, @-r15 + cfi_adjust_cfa_offset (4) + cfi_rel_offset (r8, 0) + sts.l pr, @-r15 + cfi_adjust_cfa_offset (4) + cfi_rel_offset (pr, 0) + mov r5, r8 + mov r4, r9 + + /* Not yet initialized or initialization in progress. + Get the fork generation counter now. */ +6: + mov.l @r4, r1 + mova .Lgot, r0 + mov.l .Lgot, r12 + add r0, r12 + +5: + mov r1, r0 + + tst #2, r0 + bf 4f + + and #3, r0 + mov.l .Lfgen, r2 +#ifdef __PIC__ + add r12, r2 +#endif + mov.l @r2, r3 + or r3, r0 + or #1, r0 + mov r0, r3 + mov r1, r5 + + CMPXCHG (r5, @r4, r3, r2) + bf 5b + + /* Check whether another thread already runs the initializer. */ + mov r2, r0 + tst #1, r0 + bt 3f /* No -> do it. */ + + /* Check whether the initializer execution was interrupted + by a fork. */ + xor r3, r0 + mov #-4, r1 /* -4 = 0xfffffffc */ + tst r1, r0 + bf 3f /* Different for generation -> run initializer. */ + + /* Somebody else got here first. Wait. */ +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r5 +# if FUTEX_WAIT != 0 + mov #FUTEX_WAIT, r0 + or r0, r5 +# endif +#endif + mov r3, r6 + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + bra 6b + nop + + .align 2 +.Lgot: + .long _GLOBAL_OFFSET_TABLE_ +#ifdef __PIC__ +.Lfgen: + .long __fork_generation@GOTOFF +#else +.Lfgen: + .long __fork_generation +#endif + +3: + /* Call the initializer function after setting up the + cancellation handler. Note that it is not possible here + to use the unwind-based cleanup handling. This would require + that the user-provided function and all the code it calls + is compiled with exceptions. Unfortunately this cannot be + guaranteed. */ + add #-UNWINDBUFSIZE, r15 + cfi_adjust_cfa_offset (UNWINDBUFSIZE) + + mov.l .Lsigsetjmp, r1 + mov #UWJMPBUF, r4 + add r15, r4 + bsrf r1 + mov #0, r5 +.Lsigsetjmp0: + tst r0, r0 + bf 7f + + mov.l .Lcpush, r1 + bsrf r1 + mov r15, r4 +.Lcpush0: + + /* Call the user-provided initialization function. */ + jsr @r8 + nop + + /* Pop the cleanup handler. */ + mov.l .Lcpop, r1 + bsrf r1 + mov r15, r4 +.Lcpop0: + + add #UNWINDBUFSIZE, r15 + cfi_adjust_cfa_offset (-UNWINDBUFSIZE) + + /* Sucessful run of the initializer. Signal that we are done. */ + INC (@r9, r2) + /* Wake up all other threads. */ + mov r9, r4 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAKE), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_WAKE, r0 + or r0, r5 +#endif + mov #-1, r6 + shlr r6 /* r6 = 0x7fffffff */ + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + +4: + lds.l @r15+, pr + cfi_adjust_cfa_offset (-4) + cfi_restore (pr) + mov.l @r15+, r8 + cfi_adjust_cfa_offset (-4) + cfi_restore (r8) + mov.l @r15+, r9 + cfi_adjust_cfa_offset (-4) + cfi_restore (r9) + mov.l @r15+, r12 + cfi_adjust_cfa_offset (-4) + cfi_restore (r12) + rts + mov #0, r0 + +7: + /* __sigsetjmp returned for the second time. */ + cfi_adjust_cfa_offset (UNWINDBUFSIZE+16) + cfi_offset (r12, -4) + cfi_offset (r9, -8) + cfi_offset (r8, -12) + cfi_offset (pr, -16) + mov #0, r7 + mov.l r7, @r9 + mov r9, r4 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAKE), r5 +#else + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_WAKE, r0 + or r0, r5 +#endif + extu.b r5, r5 + mov #-1, r6 + shlr r6 /* r6 = 0x7fffffff */ + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + mov.l .Lunext, r1 + bsrf r1 + mov r15, r4 +.Lunext0: + /* NOTREACHED */ + sleep + cfi_endproc + +#ifndef __ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif + .align 2 +.Lsigsetjmp: + .long __sigsetjmp@PLT-(.Lsigsetjmp0-.) +.Lcpush: + .long HIDDEN_JUMPTARGET(__pthread_register_cancel)-.Lcpush0 +.Lcpop: + .long HIDDEN_JUMPTARGET(__pthread_unregister_cancel)-.Lcpop0 +.Lunext: + .long HIDDEN_JUMPTARGET(__pthread_unwind_next)-.Lunext0 + .size __pthread_once,.-__pthread_once + + .globl __pthread_once_internal +__pthread_once_internal = __pthread_once + + .globl pthread_once +pthread_once = __pthread_once diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S new file mode 100644 index 000000000..5b100d8cd --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S @@ -0,0 +1,255 @@ +/* Copyright (C) 2003, 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include <bits/kernel-features.h> +#include "lowlevel-atomic.h" + + + .text + + .globl __pthread_rwlock_rdlock + .type __pthread_rwlock_rdlock,@function + .hidden __pthread_rwlock_rdlock + .align 5 +__pthread_rwlock_rdlock: + mov.l r12, @-r15 + mov.l r9, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + mov r4, r8 + + /* Get the lock. */ + mov #0, r3 + mov #1, r4 +#if MUTEX == 0 + CMPXCHG (r3, @r8, r4, r2) +#else + CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif + bf 1f +2: + mov.l @(WRITER,r8), r0 + tst r0, r0 + bf 14f + mov.l @(WRITERS_QUEUED,r8), r0 + tst r0, r0 + bt 5f + mov #FLAGS, r0 + mov.b @(r0,r8), r0 + tst r0, r0 + bt 5f +3: + mov.l @(READERS_QUEUED,r8), r0 + add #1, r0 + mov.l r0, @(READERS_QUEUED,r8) + tst r0, r0 + bt 4f + + mov.l @(READERS_WAKEUP,r8), r9 + +#if MUTEX == 0 + DEC (@r8, r2) +#else + DEC (@(MUTEX,r8), r2) +#endif + tst r2, r2 + bf 10f +11: +#ifdef __ASSUME_PRIVATE_FUTEX + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r0 + xor r0, r5 + extu.b r5, r5 +#else + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 +# if FUTEX_WAIT != 0 + mov #FUTEX_WAIT, r0 + or r0, r5 +# endif + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r0 + xor r0, r5 +#endif + mov r8, r4 + add #READERS_WAKEUP, r4 + mov r9, r6 + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + /* Reget the lock. */ + mov #0, r3 + mov #1, r4 +#if MUTEX == 0 + CMPXCHG (r3, @r8, r4, r2) +#else + CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif + bf 12f +13: + mov.l @(READERS_QUEUED,r8), r0 + add #-1, r0 + bra 2b + mov.l r0, @(READERS_QUEUED,r8) + +5: + mov #0, r3 + mov.l @(NR_READERS,r8), r0 + add #1, r0 + mov.l r0, @(NR_READERS,r8) + tst r0, r0 + bt 8f + +9: +#if MUTEX == 0 + DEC (@r8, r2) +#else + DEC (@(MUTEX,r8), r2) +#endif + tst r2, r2 + bf 6f +7: + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r12 + rts + mov r3, r0 + +#ifndef __ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif + +1: + mov r8, r5 +#if MUTEX != 0 + add #MUTEX, r5 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r6 + extu.b r6, r6 + mov.l .Lwait0, r1 + bsrf r1 + mov r2, r4 +.Lwait0b: + bra 2b + nop +14: + stc gbr, r1 + mov.w .Ltidoff, r2 + add r2, r1 + mov.l @r1, r1 + cmp/eq r1, r0 + bf 3b + /* Deadlock detected. */ + bra 9b + mov #EDEADLK, r3 + +.Ltidoff: + .word TID - TLS_PRE_TCB_SIZE + +6: + mov r8, r4 +#if MUTEX != 0 + add #MUTEX, r4 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov.l .Lwake0, r1 + bsrf r1 + nop +.Lwake0b: + bra 7b + mov #0, r3 + +8: + /* Overflow. */ + mov.l @(NR_READERS,r8), r1 + add #-1, r1 + mov.l r1, @(NR_READERS,r8) + bra 9b + mov #EAGAIN, r3 + +4: + /* Overflow. */ + mov.l @(READERS_QUEUED,r8), r1 + add #-1, r1 + mov.l r1, @(READERS_QUEUED,r8) + bra 9b + mov #EAGAIN, r3 + +10: + mov r8, r4 +#if MUTEX != 0 + add #MUTEX, r4 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov.l .Lwake1, r1 + bsrf r1 + nop +.Lwake1b: + bra 11b + nop + +12: + mov r8, r5 +#if MUTEX != 0 + add #MUTEX, r5 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r6 + extu.b r6, r6 + mov.l .Lwait1, r1 + bsrf r1 + mov r2, r4 +.Lwait1b: + bra 13b + nop + + .align 2 +.Lwait0: + .long __lll_lock_wait-.Lwait0b +.Lwake0: + .long __lll_unlock_wake-.Lwake0b +.Lwait1: + .long __lll_lock_wait-.Lwait1b +.Lwake1: + .long __lll_unlock_wake-.Lwake1b + .size __pthread_rwlock_rdlock,.-__pthread_rwlock_rdlock + + .globl pthread_rwlock_rdlock +pthread_rwlock_rdlock = __pthread_rwlock_rdlock + + .globl __pthread_rwlock_rdlock_internal +__pthread_rwlock_rdlock_internal = __pthread_rwlock_rdlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S new file mode 100644 index 000000000..6e7af21e9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S @@ -0,0 +1,314 @@ +/* Copyright (C) 2003, 2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include <bits/kernel-features.h> +#include "lowlevel-atomic.h" + + + .text + + .globl pthread_rwlock_timedrdlock + .type pthread_rwlock_timedrdlock,@function + .align 5 +pthread_rwlock_timedrdlock: + mov.l r12, @-r15 + mov.l r10, @-r15 + mov.l r9, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + add #-8, r15 + mov r4, r8 + mov r5, r9 + + /* Get the lock. */ + mov #0, r3 + mov #1, r4 +#if MUTEX == 0 + CMPXCHG (r3, @r8, r4, r2) +#else + CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif + bf 1f +2: + mov.l @(WRITER,r8), r0 + tst r0, r0 + bf 14f + mov.l @(WRITERS_QUEUED,r8), r0 + tst r0, r0 + bt 5f + mov #FLAGS, r0 + mov.b @(r0,r8), r0 + tst r0, r0 + bt 5f +3: + /* Check the value of the timeout parameter. */ + mov.l .L1g0, r1 + mov.l @(4,r9), r0 + cmp/hs r1, r0 + bt 19f + + mov.l @(READERS_QUEUED,r8), r0 + add #1, r0 + mov.l r0, @(READERS_QUEUED,r8) + tst r0, r0 + bt 4f + + mov.l @(READERS_WAKEUP,r8), r10 + +#if MUTEX == 0 + DEC (@r8, r2) +#else + DEC (@(MUTEX,r8), r2) +#endif + tst r2, r2 + bf 10f + +11: + /* Get current time. */ + mov r15, r4 + mov #0, r5 + mov #__NR_gettimeofday, r3 + trapa #0x12 + SYSCALL_INST_PAD + + mov.l @(4,r15), r0 + mov.w .L1k0, r1 + dmulu.l r0, r1 /* Milli seconds to nano seconds. */ + mov.l @r9, r2 + mov.l @(4,r9), r3 + mov.l @r15, r0 + sts macl, r1 + sub r0, r2 + clrt + subc r1, r3 + bf 15f + mov.l .L1g0, r1 + add r1, r3 + add #-1, r2 +15: + cmp/pz r2 + bf 16f /* Time is already up. */ + + /* Store relative timeout. */ + mov.l r2, @r15 + mov.l r3, @(4,r15) + + /* Futex call. */ + mov r15, r7 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r0 + xor r0, r5 + extu.b r5, r5 +#else + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 +# if FUTEX_WAIT != 0 + mov #FUTEX_WAIT, r0 + or r0, r5 +# endif + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r0 + xor r0, r5 +#endif + mov r10, r6 + mov r8, r4 + add #READERS_WAKEUP, r4 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + mov r0, r3 + +17: + /* Reget the lock. */ + mov #0, r5 + mov #1, r4 +#if MUTEX == 0 + CMPXCHG (r5, @r8, r4, r2) +#else + CMPXCHG (r5, @(MUTEX,r8), r4, r2) +#endif + bf 12f + +13: + mov.l @(READERS_QUEUED,r8), r0 + add #-1, r0 + mov.l r0, @(READERS_QUEUED,r8) + mov #-ETIMEDOUT, r0 + cmp/eq r0, r3 + bf 2b + +18: + bra 9f + mov #ETIMEDOUT, r3 + +5: + mov #0, r3 + mov.l @(NR_READERS,r8), r0 + add #1, r0 + mov.l r0, @(NR_READERS,r8) + tst r0, r0 + bt 8f + +9: +#if MUTEX == 0 + DEC (@r8, r2) +#else + DEC (@(MUTEX,r8), r2) +#endif + tst r2, r2 + bf 6f +7: + add #8,r15 + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r10 + mov.l @r15+, r12 + rts + mov r3, r0 + +#ifndef __ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif + .align 2 +.L1k0: + .long 1000 +.L1g0: + .long 1000000000 + +1: + mov r8, r5 +#if MUTEX != 0 + add #MUTEX, r5 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r6 + extu.b r6, r6 + mov.l .Lwait2, r1 + bsrf r1 + mov r2, r4 +.Lwait2b: + bra 2b + nop +14: + stc gbr, r1 + mov.w .Ltidoff, r2 + add r2, r1 + mov.l @r1, r1 + cmp/eq r1, r0 + bf 3b + /* Deadlock detected. */ + bra 9b + mov #EDEADLK, r3 + +.Ltidoff: + .word TID - TLS_PRE_TCB_SIZE + +6: + mov r3, r10 + mov r8, r4 +#if MUTEX != 0 + add #MUTEX, r4 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov.l .Lwake2, r1 + bsrf r1 + nop +.Lwake2b: + bra 7b + mov r10, r3 + +8: + /* Overflow. */ + mov.l @(NR_READERS,r8), r1 + add #-1, r1 + mov.l r1, @(NR_READERS,r8) + bra 9b + mov #EAGAIN, r3 + +4: + /* Overflow. */ + mov.l @(READERS_QUEUED,r8), r1 + add #-1, r1 + mov.l r1, @(READERS_QUEUED,r8) + bra 9b + mov #EAGAIN, r3 + +10: + mov r8, r4 +#if MUTEX != 0 + add #MUTEX, r4 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov.l .Lwake3, r1 + bsrf r1 + nop +.Lwake3b: + bra 11b + nop + +12: + mov r3, r10 + mov r8, r5 +#if MUTEX != 0 + add #MUTEX, r5 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r6 + extu.b r6, r6 + mov.l .Lwait3, r1 + bsrf r1 + mov r2, r4 +.Lwait3b: + bra 13b + mov r10, r3 + +16: + bra 17b + mov #-ETIMEDOUT, r3 + +19: + bra 9b + mov #EINVAL, r3 + + .align 2 +.Lwait2: + .long __lll_lock_wait-.Lwait2b +.Lwake2: + .long __lll_unlock_wake-.Lwake2b +.Lwait3: + .long __lll_lock_wait-.Lwait3b +.Lwake3: + .long __lll_unlock_wake-.Lwake3b + .size pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S new file mode 100644 index 000000000..1cb7cbdde --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S @@ -0,0 +1,298 @@ +/* Copyright (C) 2003, 2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include <bits/kernel-features.h> +#include "lowlevel-atomic.h" + + + .text + + .globl pthread_rwlock_timedwrlock + .type pthread_rwlock_timedwrlock,@function + .align 5 +pthread_rwlock_timedwrlock: + mov.l r12, @-r15 + mov.l r10, @-r15 + mov.l r9, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + add #-8, r15 + mov r4, r8 + mov r5, r9 + + /* Get the lock. */ + mov #0, r3 + mov #1, r4 +#if MUTEX == 0 + CMPXCHG (r3, @r8, r4, r2) +#else + CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif + bf 1f +2: + mov.l @(WRITER,r8), r0 + tst r0, r0 + bf 14f + mov.l @(NR_READERS,r8), r0 + tst r0, r0 + bt 5f +3: + /* Check the value of the timeout parameter. */ + mov.l .L1g1, r1 + mov.l @(4,r9), r0 + cmp/hs r1, r0 + bt 19f + + mov.l @(WRITERS_QUEUED,r8), r0 + add #1, r0 + mov.l r0, @(WRITERS_QUEUED,r8) + tst r0, r0 + bt 4f + + mov.l @(WRITERS_WAKEUP,r8), r10 + +#if MUTEX == 0 + DEC (@r8, r2) +#else + DEC (@(MUTEX,r8), r2) +#endif + tst r2, r2 + bf 10f + +11: + /* Get current time. */ + mov r15, r4 + mov #0, r5 + mov #__NR_gettimeofday, r3 + trapa #0x12 + SYSCALL_INST_PAD + + mov.l @(4,r15), r0 + mov.w .L1k1, r1 + dmulu.l r0, r1 /* Milli seconds to nano seconds. */ + mov.l @r9, r2 + mov.l @(4,r9), r3 + mov.l @r15, r0 + sts macl, r1 + sub r0, r2 + clrt + subc r1, r3 + bf 15f + mov.l .L1g1, r1 + add r1, r3 + add #-1, r2 +15: + cmp/pz r2 + bf 16f /* Time is already up. */ + + /* Store relative timeout. */ + mov.l r2, @r15 + mov.l r3, @(4,r15) + + /* Futex call. */ + mov r15, r7 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r0 + xor r0, r5 + extu.b r5, r5 +#else + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 +# if FUTEX_WAIT != 0 + mov #FUTEX_WAIT, r0 + or r0, r5 +# endif + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r0 + xor r0, r5 +#endif + mov r10, r6 + mov r8, r4 + add #WRITERS_WAKEUP, r4 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + mov r0, r3 + +17: + /* Reget the lock. */ + mov #0, r5 + mov #1, r4 +#if MUTEX == 0 + CMPXCHG (r5, @r8, r4, r2) +#else + CMPXCHG (r5, @(MUTEX,r8), r4, r2) +#endif + bf 12f + +13: + mov.l @(WRITERS_QUEUED,r8), r0 + add #-1, r0 + mov.l r0, @(WRITERS_QUEUED,r8) + mov #-ETIMEDOUT, r0 + cmp/eq r0, r3 + bf 2b + +18: + bra 9f + mov #ETIMEDOUT, r3 + +19: + bra 9f + mov #EINVAL, r3 + +5: + mov #0, r3 + stc gbr, r0 + mov.w .Ltidoff, r1 + mov.l @(r0,r1), r0 + mov.l r0, @(WRITER,r8) +9: +#if MUTEX == 0 + DEC (@r8, r2) +#else + DEC (@(MUTEX,r8), r2) +#endif + tst r2, r2 + bf 6f +7: + add #8,r15 + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r10 + mov.l @r15+, r12 + rts + mov r3, r0 + +#ifndef __ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif +.L1k1: + .word 1000 + .align 2 +.L1g1: + .long 1000000000 + +1: + mov r8, r5 +#if MUTEX != 0 + add #MUTEX, r5 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r6 + extu.b r6, r6 + mov.l .Lwait6, r1 + bsrf r1 + mov r2, r4 +.Lwait6b: + bra 2b + nop +14: + stc gbr, r1 + mov.w .Ltidoff, r2 + add r2, r1 + mov.l @r1, r1 + cmp/eq r1, r0 + bf 3b + bra 9b + mov #EDEADLK, r3 +6: + mov r3, r10 + mov r8, r4 +#if MUTEX != 0 + add #MUTEX, r4 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov.l .Lwake6, r1 + bsrf r1 + nop +.Lwake6b: + bra 7b + mov r10, r3 + +.Ltidoff: + .word TID - TLS_PRE_TCB_SIZE + +4: + /* Overflow. */ + mov.l @(WRITERS_QUEUED,r8), r1 + add #-1, r1 + mov.l r1, @(WRITERS_QUEUED,r8) + bra 9b + mov #EAGAIN, r3 + +10: + mov r8, r4 +#if MUTEX != 0 + add #MUTEX, r4 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov.l .Lwake7, r1 + bsrf r1 + nop +.Lwake7b: + bra 11b + nop + +12: + mov r3, r10 + mov r8, r5 +#if MUTEX != 0 + add #MUTEX, r5 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r6 + extu.b r6, r6 + mov.l .Lwait7, r1 + bsrf r1 + mov r2, r4 +.Lwait7b: + bra 13b + mov r10, r3 + +16: + bra 17b + mov #-ETIMEDOUT, r3 + + .align 2 +.Lwait6: + .long __lll_lock_wait-.Lwait6b +.Lwake6: + .long __lll_unlock_wake-.Lwake6b +.Lwait7: + .long __lll_lock_wait-.Lwait7b +.Lwake7: + .long __lll_unlock_wake-.Lwake7b + .size pthread_rwlock_timedwrlock,.-pthread_rwlock_timedwrlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S new file mode 100644 index 000000000..ca7a692f5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S @@ -0,0 +1,199 @@ +/* Copyright (C) 2003, 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelrwlock.h> +#include <bits/kernel-features.h> +#include <tcb-offsets.h> +#include "lowlevel-atomic.h" + + + .text + + .globl __pthread_rwlock_unlock + .type __pthread_rwlock_unlock,@function + .hidden __pthread_rwlock_unlock + .align 5 +__pthread_rwlock_unlock: + mov.l r12, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + mov r4, r8 + + /* Get the lock. */ + mov #0, r3 + mov #1, r4 +#if MUTEX == 0 + CMPXCHG (r3, @r8, r4, r2) +#else + CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif + bf 1f +2: + mov.l @(WRITER,r8), r0 + tst r0, r0 + bf 5f + mov.l @(NR_READERS,r8), r0 + add #-1, r0 + mov.l r0, @(NR_READERS,r8) + tst r0, r0 + bf 6f +5: + mov #0, r0 + mov.l r0, @(WRITER,r8) + mov #1, r6 + mov r8, r4 + add #WRITERS_WAKEUP, r4 + mov.l @(WRITERS_QUEUED,r8), r0 + tst r0, r0 + bf 0f + + /* If also no readers waiting nothing to do. */ + mov.l @(READERS_QUEUED,r8), r0 + tst r0, r0 + bt 6f + + mov #-1, r6 + shlr r6 /* r6 = 0x7fffffff */ + mov r8, r4 + add #READERS_WAKEUP, r4 + +0: + mov.l @r4, r0 + add #1, r0 + mov.l r0, @r4 +#if MUTEX == 0 + DEC (@r8, r2) +#else + DEC (@(MUTEX,r8), r2) +#endif + tst r2, r2 + bf 7f + +8: +#ifdef __ASSUME_PRIVATE_FUTEX + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAKE), r0 + xor r0, r5 + extu.b r5, r5 +#else + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov #FUTEX_WAKE, r0 + or r0, r5 + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r0 + xor r0, r5 +#endif + mov #SYS_futex, r3 + mov #0, r7 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r12 + rts + mov #0, r0 +6: +#if MUTEX == 0 + DEC (@r8, r2) +#else + DEC (@(MUTEX,r8), r2) +#endif + tst r2, r2 + bf 3f +4: + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r12 + rts + mov #0, r0 + +1: + mov r8, r5 +#if MUTEX != 0 + add #MUTEX, r5 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r6 + extu.b r6, r6 + mov.l .Lwait8, r1 + bsrf r1 + mov r2, r4 +.Lwait8b: + bra 2b + nop +3: + mov r8, r4 +#if MUTEX != 0 + add #MUTEX, r4 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov.l .Lwake8, r1 + bsrf r1 + nop +.Lwake8b: + bra 4b + nop + +7: + mov.l r4, @-r15 + mov.l r6, @-r15 + mov r8, r4 +#if MUTEX != 0 + add #MUTEX, r4 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov.l .Lwake9, r1 + bsrf r1 + nop +.Lwake9b: + + mov.l @r15+, r6 + bra 8b + mov.l @r15+, r4 + +#ifndef __ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif + .align 2 +.Lwait8: + .long __lll_lock_wait-.Lwait8b +.Lwake8: + .long __lll_unlock_wake-.Lwake8b +.Lwake9: + .long __lll_unlock_wake-.Lwake9b + .size __pthread_rwlock_unlock,.-__pthread_rwlock_unlock + + .globl pthread_rwlock_unlock +pthread_rwlock_unlock = __pthread_rwlock_unlock + + .globl __pthread_rwlock_unlock_internal +__pthread_rwlock_unlock_internal = __pthread_rwlock_unlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S new file mode 100644 index 000000000..fa051b1ec --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S @@ -0,0 +1,235 @@ +/* Copyright (C) 2003, 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include <bits/kernel-features.h> +#include "lowlevel-atomic.h" + + + .text + + .globl __pthread_rwlock_wrlock + .type __pthread_rwlock_wrlock,@function + .hidden __pthread_rwlock_wrlock + .align 5 +__pthread_rwlock_wrlock: + mov.l r12, @-r15 + mov.l r9, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + mov r4, r8 + + /* Get the lock. */ + mov #0, r3 + mov #1, r4 +#if MUTEX == 0 + CMPXCHG (r3, @r8, r4, r2) +#else + CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif + bf 1f +2: + mov.l @(WRITER,r8), r0 + tst r0, r0 + bf 14f + mov.l @(NR_READERS,r8), r0 + tst r0, r0 + bt 5f +3: + mov.l @(WRITERS_QUEUED,r8), r0 + add #1, r0 + mov.l r0, @(WRITERS_QUEUED,r8) + tst r0, r0 + bt 4f + + mov.l @(WRITERS_WAKEUP,r8), r9 + +#if MUTEX == 0 + DEC (@r8, r2) +#else + DEC (@(MUTEX,r8), r2) +#endif + tst r2, r2 + bf 10f +11: + mov r8, r4 + add #WRITERS_WAKEUP, r4 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r0 + xor r0, r5 + extu.b r5, r5 +#else + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 +# if FUTEX_WAIT != 0 + mov #FUTEX_WAIT, r0 + or r0, r5 +# endif + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r0 + xor r0, r5 +#endif + mov r9, r6 + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + /* Reget the lock. */ + mov #0, r3 + mov #1, r4 +#if MUTEX == 0 + CMPXCHG (r3, @r8, r4, r2) +#else + CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif + bf 12f +13: + mov.l @(WRITERS_QUEUED,r8), r0 + add #-1, r0 + bra 2b + mov.l r0, @(WRITERS_QUEUED,r8) + +5: + mov #0, r3 + stc gbr, r0 + mov.w .Ltidoff, r1 + mov.l @(r0,r1), r0 + mov.l r0, @(WRITER,r8) +9: +#if MUTEX == 0 + DEC (@r8, r2) +#else + DEC (@(MUTEX,r8), r2) +#endif + tst r2, r2 + bf 6f +7: + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r12 + rts + mov r3, r0 + +1: + mov r8, r5 +#if MUTEX != 0 + add #MUTEX, r5 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r6 + extu.b r6, r6 + mov.l .Lwait4, r1 + bsrf r1 + mov r2, r4 +.Lwait4b: + bra 2b + nop +14: + stc gbr, r1 + mov.w .Ltidoff, r2 + add r2, r1 + mov.l @r1, r1 + cmp/eq r1, r0 + bf 3b + bra 9b + mov #EDEADLK, r3 +6: + mov r8, r4 +#if MUTEX != 0 + add #MUTEX, r4 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov.l .Lwake4, r1 + bsrf r1 + nop +.Lwake4b: + bra 7b + mov #0, r3 + +#ifndef __ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif +.Ltidoff: + .word TID - TLS_PRE_TCB_SIZE + +4: + mov.l @(WRITERS_QUEUED,r8), r1 + add #-1, r1 + mov.l r1, @(WRITERS_QUEUED,r8) + bra 9b + mov #EAGAIN, r3 + +10: + mov r8, r4 +#if MUTEX != 0 + add #MUTEX, r4 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov.l .Lwake5, r1 + bsrf r1 + nop +.Lwake5b: + bra 11b + nop + +12: + mov r8, r5 +#if MUTEX != 0 + add #MUTEX, r5 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r6 + extu.b r6, r6 + mov.l .Lwait5, r1 + bsrf r1 + mov r2, r4 +.Lwait5b: + bra 13b + nop + + .align 2 +.Lwait4: + .long __lll_lock_wait-.Lwait4b +.Lwake4: + .long __lll_unlock_wake-.Lwake4b +.Lwait5: + .long __lll_lock_wait-.Lwait5b +.Lwake5: + .long __lll_unlock_wake-.Lwake5b + .globl pthread_rwlock_wrlock +pthread_rwlock_wrlock = __pthread_rwlock_wrlock + + .globl __pthread_rwlock_wrlock_internal +__pthread_rwlock_wrlock_internal = __pthread_rwlock_wrlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_post.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_post.S new file mode 100644 index 000000000..f71cd930d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_post.S @@ -0,0 +1,110 @@ +/* Copyright (C) 2003, 2004, 2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include <structsem.h> +#include <lowlevellock.h> +#include "lowlevel-atomic.h" + + + .text + + .globl __new_sem_post + .type __new_sem_post,@function + .align 5 +__new_sem_post: + mov.l @(VALUE,r4), r2 +0: + mov.l .Lmax, r1 + cmp/eq r1, r2 + bt/s 3f + mov r2, r3 + mov r3, r5 + add #1, r5 + CMPXCHG (r3, @(VALUE,r4), r5, r2) + bf 0b + mov.l @(NWAITERS,r4), r2 + tst r2, r2 + bt 2f + mov #FUTEX_WAKE, r5 + mov.l @(PRIVATE,r4), r1 + or r1, r5 + mov #1, r6 + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + cmp/pz r0 + bf 1f +2: + rts + mov #0, r0 + +1: + bra 4f + mov #EINVAL, r2 + +3: + mov #EOVERFLOW, r2 +4: + mov.l r12, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + mova .Lgot3, r0 + mov.l .Lgot3, r12 + add r0, r12 + +#if USE___THREAD + mov.l .Lerrno3, r0 + stc gbr, r1 + mov.l @(r0, r12), r0 + bra .Lexit + add r1, r0 + .align 2 +.Lerrno3: + .long errno@GOTTPOFF +.Lexit: + mov.l r2, @r0 +#else + mov r2, r8 + mov.l .Lerrloc3, r1 + bsrf r1 + nop +.Lerrloc3b: + mov r8, @r0 +#endif + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r12 + rts + mov #-1, r0 + + .align 2 +.Lmax: + .long SEM_VALUE_MAX +.Lgot3: + .long _GLOBAL_OFFSET_TABLE_ +#if !USE___THREAD +.Lerrloc3: + .long __errno_location@PLT-(.Lerrloc3b-.) +#endif + .size __new_sem_post,.-__new_sem_post + weak_alias(__new_sem_post, sem_post) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S new file mode 100644 index 000000000..7fb61b273 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S @@ -0,0 +1,358 @@ +/* Copyright (C) 2003, 2004, 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include <structsem.h> +#include <lowlevellock.h> +#include "lowlevel-atomic.h" + + +#if VALUE != 0 +# error "code needs to be rewritten for VALUE != 0" +#endif + + .text + + .globl sem_timedwait + .type sem_timedwait,@function + .align 5 +sem_timedwait: +.LSTARTCODE: + mov.l @r4, r0 +2: + tst r0, r0 + bt 1f + mov r0, r3 + mov r0, r6 + add #-1, r3 + CMPXCHG (r6, @r4, r3, r2) + bf/s 2b + mov r2, r0 + rts + mov #0, r0 + +1: + /* Check whether the timeout value is valid. */ + mov.l r8, @-r15 +.Lpush_r8: + mov.l r9, @-r15 +.Lpush_r9: + mov.l r10, @-r15 +.Lpush_r10: + mov.l r12, @-r15 +.Lpush_r12: + sts.l pr, @-r15 +.Lpush_pr: + add #-8, r15 +.Lalloc: + mov r4, r8 + mov r5, r9 + + /* Check for invalid nanosecond field. */ + mov.l @(4,r9), r0 + mov.l .L1g, r1 + cmp/hs r1, r0 + bt/s 6f + mov #EINVAL, r0 + INC (@(NWAITERS,r8),r2) + +7: + /* Compute relative timeout. */ + mov r15, r4 + mov #0, r5 + mov #__NR_gettimeofday, r3 + trapa #0x12 + SYSCALL_INST_PAD + + mov.l @(4,r15), r0 + mov.w .L1k, r1 + dmulu.l r0, r1 /* Milli seconds to nano seconds. */ + mov.l @r9, r2 + mov.l @(4,r9), r3 + mov.l @r15, r0 + sts macl, r1 + sub r0, r2 + clrt + subc r1, r3 + bf 5f + mov.l .L1g, r1 + add r1, r3 + add #-1, r2 +5: + cmp/pz r2 + bf/s 6f /* Time is already up. */ + mov #ETIMEDOUT, r0 + + /* Store relative timeout. */ + mov.l r2, @r15 + mov.l r3, @(4,r15) + +.LcleanupSTART: + mov.l .Lenable0, r1 + bsrf r1 + nop +.Lenable0b: + mov r0, r10 + + mov r8, r4 +#if FUTEX_WAIT == 0 + mov.l @(PRIVATE,r8), r5 +#else + mov.l @(PRIVATE,r8), r5 + mov #FUTEX_WAIT, r0 + or r0, r5 +#endif + mov #0, r6 + mov r15, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + mov.l .Ldisable0, r1 + mov r10, r4 + bsrf r1 + mov r0, r10 +.Ldisable0b: + mov r10, r0 +.LcleanupEND: + + tst r0, r0 + bt 9f + cmp/eq #-EWOULDBLOCK, r0 + bf 3f +9: + mov.l @r8, r0 +8: + tst r0, r0 + bt 7b + + mov r0, r3 + mov r0, r4 + add #-1, r3 + CMPXCHG (r4, @r8, r3, r2) + bf/s 8b + mov r2, r0 + + DEC (@(NWAITERS,r8), r2) + mov #0, r0 + +10: + add #8, r15 + lds.l @r15+, pr + mov.l @r15+, r12 + mov.l @r15+, r10 + mov.l @r15+, r9 + mov.l @r15+, r8 + rts + nop + +3: + neg r0, r0 +6: + mov r0, r10 + mova .Lgot2, r0 + mov.l .Lgot2, r12 + add r0, r12 + +#if USE___THREAD + mov.l .Lerrno2, r0 + stc gbr, r1 + mov.l @(r0, r12), r0 + bra .Lexit + add r1, r0 + .align 2 +.Lerrno2: + .long errno@GOTTPOFF +.Lexit: +#else + mov.l .Lerrloc2, r1 + bsrf r1 + nop +.Lerrloc2b: +#endif + mov.l r10, @r0 + DEC (@(NWAITERS,r8), r2) + bra 10b + mov #-1, r0 + +.L1k: + .word 1000 + .align 2 +.L1g: + .long 1000000000 +.Lgot2: + .long _GLOBAL_OFFSET_TABLE_ +#if !USE___THREAD +.Lerrloc2: + .long __errno_location@PLT-(.Lerrloc2b-.) +#endif +.Lenable0: + .long __pthread_enable_asynccancel-.Lenable0b +.Ldisable0: + .long __pthread_disable_asynccancel-.Ldisable0b + .size sem_timedwait,.-sem_timedwait + + .type sem_wait_cleanup,@function +sem_wait_cleanup: + DEC (@(NWAITERS,r8), r2) +.LcallUR: + mov.l .Lresume, r1 +#ifdef __PIC__ + add r12, r1 +#endif + jsr @r1 + nop + sleep + + .align 2 +.Lresume: +#ifdef __PIC__ + .long _Unwind_Resume@GOTOFF +#else + .long _Unwind_Resume +#endif +.LENDCODE: + .size sem_wait_cleanup,.-sem_wait_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte 0xff ! @LPStart format (omit) + .byte 0xff ! @TType format (omit) + .byte 0x01 ! call-site format + ! DW_EH_PE_uleb128 + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 sem_wait_cleanup-.LSTARTCODE + .uleb128 0 + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +.Lcstend: + + + .section .eh_frame,"a",@progbits +.LSTARTFRAME: + .ualong .LENDCIE-.LSTARTCIE ! Length of the CIE. +.LSTARTCIE: + .ualong 0 ! CIE ID. + .byte 1 ! Version number. +#ifdef SHARED + .string "zPLR" ! NUL-terminated augmentation + ! string. +#else + .string "zPL" ! NUL-terminated augmentation + ! string. +#endif + .uleb128 1 ! Code alignment factor. + .sleb128 -4 ! Data alignment factor. + .byte 0x11 ! Return address register + ! column. +#ifdef SHARED + .uleb128 7 ! Augmentation value length. + .byte 0x9b ! Personality: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4 + ! + DW_EH_PE_indirect + .ualong DW.ref.__gcc_personality_v0-. + .byte 0x1b ! LSDA Encoding: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4. + .byte 0x1b ! FDE Encoding: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4. +#else + .uleb128 6 ! Augmentation value length. + .byte 0x0 ! Personality: absolute + .ualong __gcc_personality_v0 + .byte 0x0 ! LSDA Encoding: absolute +#endif + .byte 0x0c ! DW_CFA_def_cfa + .uleb128 0xf + .uleb128 0 + .align 4 +.LENDCIE: + + .ualong .LENDFDE-.LSTARTFDE ! Length of the FDE. +.LSTARTFDE: + .ualong .LSTARTFDE-.LSTARTFRAME ! CIE pointer. +#ifdef SHARED + .ualong .LSTARTCODE-. ! PC-relative start address + ! of the code. +#else + .ualong .LSTARTCODE ! Start address of the code. +#endif + .ualong .LENDCODE-.LSTARTCODE ! Length of the code. + .uleb128 4 ! Augmentation size +#ifdef SHARED + .ualong .LexceptSTART-. +#else + .ualong .LexceptSTART +#endif + + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_r8-.LSTARTCODE + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 4 + .byte 0x88 ! DW_CFA_offset r8 + .uleb128 1 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_r9-.Lpush_r8 + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 8 + .byte 0x89 ! DW_CFA_offset r9 + .uleb128 2 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_r10-.Lpush_r9 + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 12 + .byte 0x8a ! DW_CFA_offset r10 + .uleb128 3 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_r12-.Lpush_r10 + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 16 + .byte 0x8c ! DW_CFA_offset r12 + .uleb128 4 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_pr-.Lpush_r12 + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 20 + .byte 0x91 ! DW_CFA_offset pr + .uleb128 5 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lalloc-.Lpush_pr + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 28 + .align 4 +.LENDFDE: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 4 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: + .long __gcc_personality_v0 +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_trywait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_trywait.S new file mode 100644 index 000000000..b46eb1a56 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_trywait.S @@ -0,0 +1,90 @@ +/* Copyright (C) 2003, 2004, 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include <lowlevellock.h> +#include "lowlevel-atomic.h" + + + .text + + .globl __new_sem_trywait + .type __new_sem_trywait,@function + .align 5 +__new_sem_trywait: + mov.l r12, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + mov r4, r8 + mov.l @r8, r0 +2: + tst r0, r0 + bt 1f + + mov r0, r3 + mov r0, r4 + add #-1, r3 + CMPXCHG (r4, @r8, r3, r2) + bf/s 2b + mov r2, r0 + + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r12 + rts + mov #0, r0 + +1: + mov #EAGAIN, r8 + mova .Lgot1, r0 + mov.l .Lgot1, r12 + add r0, r12 + +#if USE___THREAD + mov.l .Lerrno1, r0 + stc gbr, r1 + mov.l @(r0, r12), r0 + bra .Lexit + add r1, r0 + .align 2 +.Lerrno1: + .long errno@GOTTPOFF +.Lexit: +#else + mov.l .Lerrloc1, r1 + bsrf r1 + nop +.Lerrloc1b: +#endif + mov.l r8, @r0 + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r12 + rts + mov #-1, r0 + + .align 2 +.Lgot1: + .long _GLOBAL_OFFSET_TABLE_ +#if !USE___THREAD +.Lerrloc1: + .long __errno_location@PLT-(.Lerrloc1b-.) +#endif + .size __new_sem_trywait,.-__new_sem_trywait + weak_alias(__new_sem_trywait, sem_trywait) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S new file mode 100644 index 000000000..00a125bc5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S @@ -0,0 +1,303 @@ +/* Copyright (C) 2003, 2004, 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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include <structsem.h> +#include <lowlevellock.h> +#include "lowlevel-atomic.h" + + +#if VALUE != 0 +# error "code needs to be rewritten for VALUE != 0" +#endif + + .text + + .globl __new_sem_wait + .type __new_sem_wait,@function + .align 5 +__new_sem_wait: +.LSTARTCODE: + mov.l r8, @-r15 +.Lpush_r8: + mov.l r10, @-r15 +.Lpush_r10: + mov.l r12, @-r15 +.Lpush_r12: + sts.l pr, @-r15 +.Lpush_pr: + mov r4, r8 + + mov.l @r8, r0 +2: + tst r0, r0 + bt 1f + mov r0, r3 + mov r0, r4 + add #-1, r3 + CMPXCHG (r4, @r8, r3, r2) + bf/s 2b + mov r2, r0 +7: + mov #0, r0 +9: + lds.l @r15+, pr + mov.l @r15+, r12 + mov.l @r15+, r10 + rts + mov.l @r15+, r8 + +.Lafter_ret: +1: + INC (@(NWAITERS,r8),r2) + +.LcleanupSTART: +6: + mov.l .Lenable0, r1 + bsrf r1 + nop +.Lenable0b: + mov r0, r10 + + mov r8, r4 +#if FUTEX_WAIT == 0 + mov.l @(PRIVATE,r8), r5 +#else + mov.l @(PRIVATE,r8), r5 + mov #FUTEX_WAIT, r0 + or r0, r5 +#endif + mov #0, r6 + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + mov.l .Ldisable0, r1 + mov r10, r4 + bsrf r1 + mov r0, r10 +.Ldisable0b: + mov r10, r0 +.LcleanupEND: + + tst r0, r0 + bt 3f + cmp/eq #-EWOULDBLOCK, r0 + bf 4f + +3: + mov.l @r8, r0 +5: + tst r0, r0 + bt 6b + + mov r0, r3 + mov r0, r4 + add #-1, r3 + CMPXCHG (r4, @r8, r3, r2) + bf/s 5b + mov r2, r0 + + DEC (@(NWAITERS,r8), r2) + bra 7b + nop + +4: + neg r0, r0 + mov r0, r4 + DEC (@(NWAITERS,r8), r2) + mov r4, r8 + mova .Lgot0, r0 + mov.l .Lgot0, r12 + add r0, r12 + +#if USE___THREAD + mov.l .Lerrno0, r0 + stc gbr, r1 + mov.l @(r0, r12), r0 + bra .Lexit + add r1, r0 + .align 2 +.Lerrno0: + .long errno@GOTTPOFF +.Lexit: +#else + mov.l .Lerrloc0, r1 + bsrf r1 + nop +.Lerrloc0b: +#endif + mov.l r8, @r0 + bra 9b + mov #-1, r0 + + .align 2 +.Lgot0: + .long _GLOBAL_OFFSET_TABLE_ +#if !USE___THREAD +.Lerrloc0: + .long __errno_location@PLT-(.Lerrloc0b-.) +#endif +.Lenable0: + .long __pthread_enable_asynccancel-.Lenable0b +.Ldisable0: + .long __pthread_disable_asynccancel-.Ldisable0b + .size __new_sem_wait,.-__new_sem_wait + weak_alias(__new_sem_wait, sem_wait) + + + .type sem_wait_cleanup,@function +sem_wait_cleanup: + DEC (@(NWAITERS,r8), r2) +.LcallUR: + mov.l .Lresume, r1 +#ifdef __PIC__ + add r12, r1 +#endif + jsr @r1 + nop + sleep + + .align 2 +.Lresume: +#ifdef __PIC__ + .long _Unwind_Resume@GOTOFF +#else + .long _Unwind_Resume +#endif +.LENDCODE: + .size sem_wait_cleanup,.-sem_wait_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte 0xff ! @LPStart format (omit) + .byte 0xff ! @TType format (omit) + .byte 0x01 ! call-site format + ! DW_EH_PE_uleb128 + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 sem_wait_cleanup-.LSTARTCODE + .uleb128 0 + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +.Lcstend: + + + .section .eh_frame,"a",@progbits +.LSTARTFRAME: + .ualong .LENDCIE-.LSTARTCIE ! Length of the CIE. +.LSTARTCIE: + .ualong 0 ! CIE ID. + .byte 1 ! Version number. +#ifdef SHARED + .string "zPLR" ! NUL-terminated augmentation + ! string. +#else + .string "zPL" ! NUL-terminated augmentation + ! string. +#endif + .uleb128 1 ! Code alignment factor. + .sleb128 -4 ! Data alignment factor. + .byte 0x11 ! Return address register + ! column. +#ifdef SHARED + .uleb128 7 ! Augmentation value length. + .byte 0x9b ! Personality: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4 + ! + DW_EH_PE_indirect + .ualong DW.ref.__gcc_personality_v0-. + .byte 0x1b ! LSDA Encoding: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4. + .byte 0x1b ! FDE Encoding: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4. +#else + .uleb128 6 ! Augmentation value length. + .byte 0x0 ! Personality: absolute + .ualong __gcc_personality_v0 + .byte 0x0 ! LSDA Encoding: absolute +#endif + .byte 0x0c ! DW_CFA_def_cfa + .uleb128 0xf + .uleb128 0 + .align 4 +.LENDCIE: + + .ualong .LENDFDE-.LSTARTFDE ! Length of the FDE. +.LSTARTFDE: + .ualong .LSTARTFDE-.LSTARTFRAME ! CIE pointer. +#ifdef SHARED + .ualong .LSTARTCODE-. ! PC-relative start address + ! of the code. +#else + .ualong .LSTARTCODE ! Start address of the code. +#endif + .ualong .LENDCODE-.LSTARTCODE ! Length of the code. + .uleb128 4 ! Augmentation size +#ifdef SHARED + .ualong .LexceptSTART-. +#else + .ualong .LexceptSTART +#endif + + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_r8-.LSTARTCODE + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 4 + .byte 0x88 ! DW_CFA_offset r8 + .uleb128 1 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_r10-.Lpush_r8 + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 8 + .byte 0x8a ! DW_CFA_offset r10 + .uleb128 2 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_r12-.Lpush_r10 + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 12 + .byte 0x8c ! DW_CFA_offset r12 + .uleb128 3 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_pr-.Lpush_r12 + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 16 + .byte 0x91 ! DW_CFA_offset pr + .uleb128 4 + .align 4 +.LENDFDE: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 4 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: + .long __gcc_personality_v0 +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h new file mode 100644 index 000000000..8cdcac556 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h @@ -0,0 +1,4 @@ +/* 4 instruction cycles not accessing cache and TLB are needed after + trapa instruction to avoid an SH-4 silicon bug. */ +#define NEED_SYSCALL_INST_PAD +#include <sysdeps/unix/sysv/linux/sh/lowlevellock.h> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/smp.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/smp.h new file mode 100644 index 000000000..2c0cbe99a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/smp.h @@ -0,0 +1,24 @@ +/* Determine whether the host has multiple processors. SH version. + Copyright (C) 2002 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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. */ + +static inline int +is_smp_system (void) +{ + return 0; +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h new file mode 100644 index 000000000..ad2ca40ac --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h @@ -0,0 +1,169 @@ +/* Copyright (C) 2003, 2004, 2005, 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <tls.h> +#include <sysdep.h> +#ifndef __ASSEMBLER__ +# include <pthreadP.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# define _IMM12 #-12 +# define _IMM16 #-16 +# define _IMP16 #16 +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name); \ + .Lpseudo_start: \ + SINGLE_THREAD_P; \ + bf .Lpseudo_cancel; \ + .type __##syscall_name##_nocancel,@function; \ + .globl __##syscall_name##_nocancel; \ + __##syscall_name##_nocancel: \ + DO_CALL (syscall_name, args); \ + mov r0,r1; \ + mov _IMM12,r2; \ + shad r2,r1; \ + not r1,r1; \ + tst r1,r1; \ + bt .Lsyscall_error; \ + bra .Lpseudo_end; \ + nop; \ + .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ + .Lpseudo_cancel: \ + sts.l pr,@-r15; \ + cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (pr, 0); \ + add _IMM16,r15; \ + cfi_adjust_cfa_offset (16); \ + SAVE_ARGS_##args; \ + CENABLE; \ + LOAD_ARGS_##args; \ + add _IMP16,r15; \ + cfi_adjust_cfa_offset (-16); \ + lds.l @r15+,pr; \ + cfi_adjust_cfa_offset (-4); \ + cfi_restore (pr); \ + DO_CALL(syscall_name, args); \ + SYSCALL_INST_PAD; \ + sts.l pr,@-r15; \ + cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (pr, 0); \ + mov.l r0,@-r15; \ + cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (r0, 0); \ + CDISABLE; \ + mov.l @r15+,r0; \ + cfi_adjust_cfa_offset (-4); \ + lds.l @r15+,pr; \ + cfi_adjust_cfa_offset (-4); \ + cfi_restore (pr); \ + mov r0,r1; \ + mov _IMM12,r2; \ + shad r2,r1; \ + not r1,r1; \ + tst r1,r1; \ + bf .Lpseudo_end; \ + .Lsyscall_error: \ + SYSCALL_ERROR_HANDLER; \ + .Lpseudo_end: + +# undef PSEUDO_END +# define PSEUDO_END(sym) \ + END (sym) + +# define SAVE_ARGS_0 /* Nothing. */ +# define SAVE_ARGS_1 SAVE_ARGS_0; mov.l r4,@(0,r15); cfi_offset (r4,-4) +# define SAVE_ARGS_2 SAVE_ARGS_1; mov.l r5,@(4,r15); cfi_offset (r5,-8) +# define SAVE_ARGS_3 SAVE_ARGS_2; mov.l r6,@(8,r15); cfi_offset (r6,-12) +# define SAVE_ARGS_4 SAVE_ARGS_3; mov.l r7,@(12,r15); cfi_offset (r7,-16) +# define SAVE_ARGS_5 SAVE_ARGS_4 +# define SAVE_ARGS_6 SAVE_ARGS_5 + +# define LOAD_ARGS_0 /* Nothing. */ +# define LOAD_ARGS_1 LOAD_ARGS_0; mov.l @(0,r15),r4 +# define LOAD_ARGS_2 LOAD_ARGS_1; mov.l @(4,r15),r5 +# define LOAD_ARGS_3 LOAD_ARGS_2; mov.l @(8,r15),r6 +# define LOAD_ARGS_4 LOAD_ARGS_3; mov.l @(12,r15),r7 +# define LOAD_ARGS_5 LOAD_ARGS_4 +# define LOAD_ARGS_6 LOAD_ARGS_5 + +# ifdef IS_IN_libpthread +# define __local_enable_asynccancel __pthread_enable_asynccancel +# define __local_disable_asynccancel __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +# define __local_enable_asynccancel __libc_enable_asynccancel +# define __local_disable_asynccancel __libc_disable_asynccancel +# elif defined IS_IN_librt +# define __local_enable_asynccancel __librt_enable_asynccancel +# define __local_disable_asynccancel __librt_disable_asynccancel +# else +# error Unsupported library +# endif + +# define CENABLE \ + mov.l 1f,r0; \ + bsrf r0; \ + nop; \ + 0: bra 2f; \ + mov r0,r2; \ + .align 2; \ + 1: .long __local_enable_asynccancel - 0b; \ + 2: + +# define CDISABLE \ + mov.l 1f,r0; \ + bsrf r0; \ + mov r2,r4; \ + 0: bra 2f; \ + nop; \ + .align 2; \ + 1: .long __local_disable_asynccancel - 0b; \ + 2: + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P \ + stc gbr,r0; \ + mov.w 0f,r1; \ + sub r1,r0; \ + mov.l @(MULTIPLE_THREADS_OFFSET,r0),r0; \ + bra 1f; \ + tst r0,r0; \ + 0: .word TLS_PRE_TCB_SIZE; \ + 1: + +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/vfork.S new file mode 100644 index 000000000..a45c09fd6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/vfork.S @@ -0,0 +1,71 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#define _ERRNO_H 1 +#include <bits/errno.h> +#include <tcb-offsets.h> + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + /* Save the PID value. */ + stc gbr, r2 + mov.w .L2, r0 + mov.l @(r0,r2), r4 + neg r4, r1 + tst r1, r1 + bf 1f + mov #1, r1 + rotr r1 +1: + mov.l r1, @(r0,r2) + + mov.w .L1, r3 + trapa #0x10 + mov r0, r1 + + /* Restore the old PID value in the parent. */ + tst r0, r0 + bt.s 2f + stc gbr, r2 + mov.w .L2, r0 + mov.l r4, @(r0,r2) + mov r1, r0 +2: + mov #-12, r2 + shad r2, r1 + not r1, r1 // r1=0 means r0 = -1 to -4095 + tst r1, r1 // i.e. error in linux + bf .Lpseudo_end + SYSCALL_ERROR_HANDLER +.Lpseudo_end: + rts + nop +.L1: + .word __NR_vfork +.L2: + .word PID - TLS_PRE_TCB_SIZE + .align 2 +PSEUDO_END (__vfork) +hidden_def (vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sigtimedwait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sigtimedwait.c new file mode 100644 index 000000000..5159bf9b8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sigtimedwait.c @@ -0,0 +1,88 @@ +/* Copyright (C) 1997,1998,2000,2002,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthreadP.h> +#include <errno.h> +#include <signal.h> +#include <string.h> + +#include <sysdep-cancel.h> +#include <sys/syscall.h> + +#ifdef __NR_rt_sigtimedwait + +static int +do_sigtimedwait (const sigset_t *set, siginfo_t *info, + const struct timespec *timeout) +{ +#ifdef SIGCANCEL + sigset_t tmpset; + if (set != NULL + && (__builtin_expect (__sigismember (set, SIGCANCEL), 0) +# ifdef SIGSETXID + || __builtin_expect (__sigismember (set, SIGSETXID), 0) +# endif + )) + { + /* Create a temporary mask without the bit for SIGCANCEL set. */ + // We are not copying more than we have to. + memcpy (&tmpset, set, _NSIG / 8); + __sigdelset (&tmpset, SIGCANCEL); +# ifdef SIGSETXID + __sigdelset (&tmpset, SIGSETXID); +# endif + set = &tmpset; + } +#endif + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + int result = INLINE_SYSCALL (rt_sigtimedwait, 4, set, + info, timeout, _NSIG / 8); + + /* The kernel generates a SI_TKILL code in si_code in case tkill is + used. tkill is transparently used in raise(). Since having + SI_TKILL as a code is useful in general we fold the results + here. */ + if (result != -1 && info != NULL && info->si_code == SI_TKILL) + info->si_code = SI_USER; + + return result; +} + + +/* Return any pending signal or wait for one for the given time. */ +int attribute_hidden +__sigtimedwait (const sigset_t *set, siginfo_t *info, + const struct timespec *timeout) +{ + if (SINGLE_THREAD_P) + return do_sigtimedwait (set, info, timeout); + + int oldtype = LIBC_CANCEL_ASYNC (); + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + int result = do_sigtimedwait (set, info, timeout); + + LIBC_CANCEL_RESET (oldtype); + + return result; +} +weak_alias (__sigtimedwait, sigtimedwait) +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sigwait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sigwait.c new file mode 100644 index 000000000..bde0a9292 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sigwait.c @@ -0,0 +1,2 @@ +#include <pthreadP.h> +#include "../../../../../../libc/signal/sigwait.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c new file mode 100644 index 000000000..6c47fdee6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c @@ -0,0 +1,88 @@ +/* Copyright (C) 1997,1998,2000,2002,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthreadP.h> +#include <errno.h> +#include <signal.h> +#define __need_NULL +#include <stddef.h> +#include <string.h> + +#include <sysdep-cancel.h> +#include <sys/syscall.h> + +#ifdef __NR_rt_sigtimedwait + +static int +do_sigwaitinfo (const sigset_t *set, siginfo_t *info) +{ +#ifdef SIGCANCEL + sigset_t tmpset; + if (set != NULL + && (__builtin_expect (__sigismember (set, SIGCANCEL), 0) +# ifdef SIGSETXID + || __builtin_expect (__sigismember (set, SIGSETXID), 0) +# endif + )) + { + /* Create a temporary mask without the bit for SIGCANCEL set. */ + // We are not copying more than we have to. + memcpy (&tmpset, set, _NSIG / 8); + __sigdelset (&tmpset, SIGCANCEL); +# ifdef SIGSETXID + __sigdelset (&tmpset, SIGSETXID); +# endif + set = &tmpset; + } +#endif + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + int result = INLINE_SYSCALL (rt_sigtimedwait, 4, set, + info, NULL, _NSIG / 8); + + /* The kernel generates a SI_TKILL code in si_code in case tkill is + used. tkill is transparently used in raise(). Since having + SI_TKILL as a code is useful in general we fold the results + here. */ + if (result != -1 && info != NULL && info->si_code == SI_TKILL) + info->si_code = SI_USER; + + return result; +} + + +/* Return any pending signal or wait for one for the given time. */ +int +__sigwaitinfo (const sigset_t *set, siginfo_t *info) +{ + if (SINGLE_THREAD_P) + return do_sigwaitinfo (set, info); + + int oldtype = LIBC_CANCEL_ASYNC (); + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + int result = do_sigwaitinfo (set, info); + + LIBC_CANCEL_RESET (oldtype); + + return result; +} +weak_alias (__sigwaitinfo, sigwaitinfo) +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sleep.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sleep.c new file mode 100644 index 000000000..9e948adce --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sleep.c @@ -0,0 +1,2 @@ +#include <pthreadP.h> +#include <../../../../../../libc/unistd/sleep.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/smp.h b/libpthread/nptl/sysdeps/unix/sysv/linux/smp.h new file mode 100644 index 000000000..fcc34f768 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/smp.h @@ -0,0 +1,28 @@ +/* Determine whether the host has multiple processors. Linux version. + Copyright (C) 1996, 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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. */ + +/* Test whether the machine has more than one processor. This is not the + best test but good enough. More complicated tests would require `malloc' + which is not available at that time. */ +static inline int +is_smp_system (void) +{ + /* Assume all machines are SMP and/or CMT and/or SMT. */ + return 1; +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Makefile new file mode 100644 index 000000000..43a6fad84 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../../../../ +top_builddir=../../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Makefile.arch b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Makefile.arch new file mode 100644 index 000000000..1e4f54488 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Makefile.arch @@ -0,0 +1,67 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_SSRC = pt-vfork.S clone.S +libpthread_CSRC = pthread_once.c lowlevellock.c \ + pthread_barrier_init.c pthread_barrier_wait.c pthread_barrier_destroy.c + +libc_a_CSRC = fork.c libc-lowlevellock.c +libc_a_SSRC = clone.S vfork.S + +CFLAGS-OMIT-fork.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-OMIT-libc-lowlevellock.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y) +CFLAGS-fork.c = -D__USE_STDIO_FUTEXES__ +endif + +ASFLAGS-pt-vfork.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT -DUSE___THREAD + +CFLAGS-pthread_once.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-lowlevellock.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + + +ASFLAGS-clone.S = -D_LIBC_REENTRANT +ASFLAGS-vfork.S = -D_LIBC_REENTRANT + +ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) +#Needed to use the correct SYSCALL_ERROR_HANDLER +ASFLAGS-clone.S += -DUSE___THREAD +ASFLAGS-vfork.S += -DUSE___THREAD +ASFLAGS-pt-vfork.S += -DUSE___THREAD +endif + +CFLAGS += $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +LINUX_ARCH_DIR:=$(top_srcdir)libpthread/nptl/sysdeps/unix/sysv/linux/sparc +LINUX_ARCH_OUT:=$(top_builddir)libpthread/nptl/sysdeps/unix/sysv/linux/sparc + +LINUX_ARCH_OBJ:=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libpthread_SSRC)) +LINUX_ARCH_OBJ+=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libpthread_CSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(LINUX_ARCH_OBJ:.o=.os) +else +libpthread-a-y += $(LINUX_ARCH_OBJ) +endif +libpthread-so-y += $(LINUX_ARCH_OBJ:.o=.oS) + +libpthread-nomulti-y+=$(LINUX_ARCH_OBJS) + +LIBC_LINUX_ARCH_OBJ:=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libc_a_CSRC)) +LIBC_LINUX_ARCH_OBJ+=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libc_a_SSRC)) + +libc-static-y+=$(LIBC_LINUX_ARCH_OBJ) +libc-shared-y+=$(LIBC_LINUX_ARCH_OBJ:.o=.oS) + +libc-nomulti-y+=$(LIBC_LINUX_ARCH_OBJ) + +objclean-y+=nptl_linux_arch_clean + +nptl_linux_arch_clean: + $(do_rm) $(addprefix $(LINUX_ARCH_OUT)/*., o os oS) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h new file mode 100644 index 000000000..6e356031d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h @@ -0,0 +1,100 @@ +/* Minimum guaranteed maximum values for system limits. Linux/SPARC version. + Copyright (C) 1993-1998,2000,2002-2004,2008 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 Library General Public License as + published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 +#ifndef ARG_MAX +# define __undef_ARG_MAX +#endif + +/* The kernel sources contain a file with all the needed information. */ +#include <linux/limits.h> + +/* 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 +/* Have to remove ARG_MAX? */ +#ifdef __undef_ARG_MAX +# undef ARG_MAX +# undef __undef_ARG_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. We are free to choose a reasonable value. */ +#define PTHREAD_STACK_MIN 24576 + +/* 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/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h new file mode 100644 index 000000000..faf058486 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h @@ -0,0 +1,221 @@ +/* Machine-specific pthread type layouts. SPARC version. + Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 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. */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#include <bits/wordsize.h> + +#if __WORDSIZE == 64 +# define __SIZEOF_PTHREAD_ATTR_T 56 +# define __SIZEOF_PTHREAD_MUTEX_T 40 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 56 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 32 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#else +# define __SIZEOF_PTHREAD_ATTR_T 36 +# define __SIZEOF_PTHREAD_MUTEX_T 24 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 32 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 20 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#endif + + +/* Thread identifiers. The structure of the attribute type is + deliberately not exposed. */ +typedef unsigned long int pthread_t; + + +typedef union +{ + char __size[__SIZEOF_PTHREAD_ATTR_T]; + long int __align; +} pthread_attr_t; + + +#if __WORDSIZE == 64 +typedef struct __pthread_internal_list +{ + struct __pthread_internal_list *__prev; + struct __pthread_internal_list *__next; +} __pthread_list_t; +#else +typedef struct __pthread_internal_slist +{ + struct __pthread_internal_slist *__next; +} __pthread_slist_t; +#endif + + +/* Data structures for mutex handling. The structure of the attribute + type is deliberately not exposed. */ +typedef union +{ + struct __pthread_mutex_s + { + int __lock; + unsigned int __count; + int __owner; +#if __WORDSIZE == 64 + unsigned int __nusers; +#endif + /* KIND must stay at this position in the structure to maintain + binary compatibility. */ + int __kind; +#if __WORDSIZE == 64 + int __spins; + __pthread_list_t __list; +# define __PTHREAD_MUTEX_HAVE_PREV 1 +#else + unsigned int __nusers; + __extension__ union + { + int __spins; + __pthread_slist_t __list; + }; +#endif + } __data; + char __size[__SIZEOF_PTHREAD_MUTEX_T]; + long int __align; +} pthread_mutex_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; + int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling. The structure of + the attribute type is deliberately not exposed. */ +typedef union +{ + struct + { + int __lock; + unsigned int __futex; + __extension__ unsigned long long int __total_seq; + __extension__ unsigned long long int __wakeup_seq; + __extension__ unsigned long long int __woken_seq; + void *__mutex; + unsigned int __nwaiters; + unsigned int __broadcast_seq; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_CONDATTR_T]; + int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling. The + structure of the attribute type is deliberately not exposed. */ +typedef union +{ +# if __WORDSIZE == 64 + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + int __writer; + int __shared; + unsigned long int __pad1; + unsigned long int __pad2; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned int __flags; + } __data; +# else + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + unsigned char __pad1; + unsigned char __pad2; + unsigned char __shared; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; + int __writer; + } __data; +# endif + char __size[__SIZEOF_PTHREAD_RWLOCK_T]; + long int __align; +} pthread_rwlock_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; + long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type. The structure of the type is + deliberately not exposed. */ +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIER_T]; + long int __align; +} pthread_barrier_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; + int __align; +} pthread_barrierattr_t; +#endif + + +#endif /* bits/pthreadtypes.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/semaphore.h new file mode 100644 index 000000000..8fd7d344e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/semaphore.h @@ -0,0 +1,41 @@ +/* Machine-specific POSIX semaphore type layouts. SPARC version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 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. */ + +#ifndef _SEMAPHORE_H +# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." +#endif + +#include <bits/wordsize.h> + +#if __WORDSIZE == 64 +# define __SIZEOF_SEM_T 32 +#else +# define __SIZEOF_SEM_T 16 +#endif + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + + +typedef union +{ + char __size[__SIZEOF_SEM_T]; + long int __align; +} sem_t; diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/clone.S new file mode 100644 index 000000000..dfc5e8261 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/clone.S @@ -0,0 +1,5 @@ +#if defined(__arch64__) +#include "./sparc64/clone.S" +#else +#include "./sparc32/clone.S" +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/fork.c new file mode 100644 index 000000000..1cd79110a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/fork.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 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 <sched.h> +#include <signal.h> +#include <sysdep.h> +#include <tls.h> + +#define ARCH_FORK() \ + INLINE_CLONE_SYSCALL (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, \ + 0, NULL, NULL, &THREAD_SELF->tid) + +#include "../fork.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/internaltypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/internaltypes.h new file mode 100644 index 000000000..4f400a3fe --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/internaltypes.h @@ -0,0 +1,34 @@ +#ifndef _INTERNALTYPES_H +#include "../internaltypes.h" + +union sparc_pthread_barrier +{ + struct pthread_barrier b; + struct sparc_pthread_barrier_s + { + unsigned int curr_event; + int lock; + unsigned int left; + unsigned int init_count; + unsigned char left_lock; + unsigned char pshared; + } s; +}; + +struct sparc_new_sem +{ + unsigned int value; + unsigned char lock; + unsigned char private; + unsigned char pad[2]; + unsigned long int nwaiters; +}; + +struct sparc_old_sem +{ + unsigned int value; + unsigned char lock; + unsigned char private; +}; + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/libc-lowlevellock.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/libc-lowlevellock.c new file mode 100644 index 000000000..b19282281 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/libc-lowlevellock.c @@ -0,0 +1,21 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras <paulus@au.ibm.com>, 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. */ + +/* No difference to lowlevellock.c, except we lose a couple of functions. */ +#include "lowlevellock.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.c new file mode 100644 index 000000000..0471d1f79 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.c @@ -0,0 +1,133 @@ +/* low level locking for pthread library. SPARC version. + Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras <paulus@au.ibm.com>, 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 <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <sys/time.h> +#include <tls.h> + + +void +__lll_lock_wait_private (int *futex) +{ + do + { + int oldval = atomic_compare_and_exchange_val_24_acq (futex, 2, 1); + if (oldval != 0) + lll_futex_wait (futex, 2, LLL_PRIVATE); + } + while (atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0); +} + + +/* These functions don't get included in libc.so */ +#ifdef IS_IN_libpthread +void +__lll_lock_wait (int *futex, int private) +{ + do + { + int oldval = atomic_compare_and_exchange_val_24_acq (futex, 2, 1); + if (oldval != 0) + lll_futex_wait (futex, 2, private); + } + while (atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0); +} + + +int +__lll_timedlock_wait (int *futex, const struct timespec *abstime, int private) +{ + /* Reject invalid timeouts. */ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + do + { + struct timeval tv; + struct timespec rt; + + /* Get the current time. */ + (void) gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + + /* Already timed out? */ + if (rt.tv_sec < 0) + return ETIMEDOUT; + + /* Wait. */ + int oldval = atomic_compare_and_exchange_val_24_acq (futex, 2, 1); + if (oldval != 0) + lll_futex_timed_wait (futex, 2, &rt, private); + } + while (atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0); + + return 0; +} + + +int +__lll_timedwait_tid (int *tidp, const struct timespec *abstime) +{ + int tid; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + /* Repeat until thread terminated. */ + while ((tid = *tidp) != 0) + { + struct timeval tv; + struct timespec rt; + + /* Get the current time. */ + (void) gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + + /* Already timed out? */ + if (rt.tv_sec < 0) + return ETIMEDOUT; + + /* Wait until thread terminates. The kernel so far does not use + the private futex operations for this. */ + if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT) + return ETIMEDOUT; + } + + return 0; +} +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h new file mode 100644 index 000000000..d8fe9be35 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h @@ -0,0 +1,297 @@ +/* Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 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 Libr \ary; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H 1 + +#include <time.h> +#include <sys/param.h> +#include <bits/pthreadtypes.h> +#include <atomic.h> +#include <sysdep.h> +#include <bits/kernel-features.h> + + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 +#define FUTEX_WAKE_OP 5 +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 +#define FUTEX_WAIT_BITSET 9 +#define FUTEX_WAKE_BITSET 10 +#define FUTEX_PRIVATE_FLAG 128 +#define FUTEX_CLOCK_REALTIME 256 + +#define FUTEX_BITSET_MATCH_ANY 0xffffffff + + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \ + & THREAD_GETMEM (THREAD_SELF, header.private_futex)))) +# endif +#endif + + +#define lll_futex_wait(futexp, val, private) \ + lll_futex_timed_wait (futexp, val, NULL, private) + +#define lll_futex_timed_wait(futexp, val, timespec, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAIT, private), \ + (val), (timespec)); \ + __ret; \ + }) + +#define lll_futex_wake(futexp, nr, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAKE, private), \ + (nr), 0); \ + __ret; \ + }) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_CMP_REQUEUE, private),\ + (nr_wake), (nr_move), (mutex), (val)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + +#define lll_robust_dead(futexv, private) \ + do \ + { \ + int *__futexp = &(futexv); \ + atomic_or (__futexp, FUTEX_OWNER_DIED); \ + lll_futex_wake (__futexp, 1, private); \ + } \ + while (0) + +/* Returns non-zero if error happened, zero if success. */ +#ifdef __sparc32_atomic_do_lock +/* Avoid FUTEX_WAKE_OP if supporting pre-v9 CPUs. */ +# define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) 1 +#else +# define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_WAKE_OP, private), \ + (nr_wake), (nr_wake2), (futexp2), \ + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) +#endif + +static inline int +__attribute__ ((always_inline)) +__lll_trylock (int *futex) +{ + return atomic_compare_and_exchange_val_24_acq (futex, 1, 0) != 0; +} +#define lll_trylock(futex) __lll_trylock (&(futex)) + +static inline int +__attribute__ ((always_inline)) +__lll_cond_trylock (int *futex) +{ + return atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0; +} +#define lll_cond_trylock(futex) __lll_cond_trylock (&(futex)) + +static inline int +__attribute__ ((always_inline)) +__lll_robust_trylock (int *futex, int id) +{ + return atomic_compare_and_exchange_val_acq (futex, id, 0) != 0; +} +#define lll_robust_trylock(futex, id) \ + __lll_robust_trylock (&(futex), id) + + +extern void __lll_lock_wait_private (int *futex) attribute_hidden; +extern void __lll_lock_wait (int *futex, int private) attribute_hidden; +extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden; + +static inline void +__attribute__ ((always_inline)) +__lll_lock (int *futex, int private) +{ + int val = atomic_compare_and_exchange_val_24_acq (futex, 1, 0); + + if (__builtin_expect (val != 0, 0)) + { + if (__builtin_constant_p (private) && private == LLL_PRIVATE) + __lll_lock_wait_private (futex); + else + __lll_lock_wait (futex, private); + } +} +#define lll_lock(futex, private) __lll_lock (&(futex), private) + +static inline int +__attribute__ ((always_inline)) +__lll_robust_lock (int *futex, int id, int private) +{ + int result = 0; + if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0) + result = __lll_robust_lock_wait (futex, private); + return result; +} +#define lll_robust_lock(futex, id, private) \ + __lll_robust_lock (&(futex), id, private) + +static inline void +__attribute__ ((always_inline)) +__lll_cond_lock (int *futex, int private) +{ + int val = atomic_compare_and_exchange_val_24_acq (futex, 2, 0); + + if (__builtin_expect (val != 0, 0)) + __lll_lock_wait (futex, private); +} +#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private) + +#define lll_robust_cond_lock(futex, id, private) \ + __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private) + + +extern int __lll_timedlock_wait (int *futex, const struct timespec *, + int private) attribute_hidden; +extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *, + int private) attribute_hidden; + +static inline int +__attribute__ ((always_inline)) +__lll_timedlock (int *futex, const struct timespec *abstime, int private) +{ + int val = atomic_compare_and_exchange_val_24_acq (futex, 1, 0); + int result = 0; + + if (__builtin_expect (val != 0, 0)) + result = __lll_timedlock_wait (futex, abstime, private); + return result; +} +#define lll_timedlock(futex, abstime, private) \ + __lll_timedlock (&(futex), abstime, private) + +static inline int +__attribute__ ((always_inline)) +__lll_robust_timedlock (int *futex, const struct timespec *abstime, + int id, int private) +{ + int result = 0; + if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0) + result = __lll_robust_timedlock_wait (futex, abstime, private); + return result; +} +#define lll_robust_timedlock(futex, abstime, id, private) \ + __lll_robust_timedlock (&(futex), abstime, id, private) + +#define lll_unlock(lock, private) \ + ((void) ({ \ + int *__futex = &(lock); \ + int __val = atomic_exchange_24_rel (__futex, 0); \ + if (__builtin_expect (__val > 1, 0)) \ + lll_futex_wake (__futex, 1, private); \ + })) + +#define lll_robust_unlock(lock, private) \ + ((void) ({ \ + int *__futex = &(lock); \ + int __val = atomic_exchange_rel (__futex, 0); \ + if (__builtin_expect (__val & FUTEX_WAITERS, 0)) \ + lll_futex_wake (__futex, 1, private); \ + })) + +#define lll_islocked(futex) \ + (futex != 0) + +/* Initializers for lock. */ +#define LLL_LOCK_INITIALIZER (0) +#define LLL_LOCK_INITIALIZER_LOCKED (1) + +/* The kernel notifies a process with uses CLONE_CLEARTID via futex + wakeup when the clone terminates. The memory location contains the + thread ID while the clone is running and is reset to zero + afterwards. */ +#define lll_wait_tid(tid) \ + do \ + { \ + __typeof (tid) __tid; \ + while ((__tid = (tid)) != 0) \ + lll_futex_wait (&(tid), __tid, LLL_SHARED); \ + } \ + while (0) + +extern int __lll_timedwait_tid (int *, const struct timespec *) + attribute_hidden; + +#define lll_timedwait_tid(tid, abstime) \ + ({ \ + int __res = 0; \ + if ((tid) != 0) \ + __res = __lll_timedwait_tid (&(tid), (abstime)); \ + __res; \ + }) + +#endif /* lowlevellock.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pt-vfork.S new file mode 100644 index 000000000..e8705c54b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pt-vfork.S @@ -0,0 +1,5 @@ +#if defined(__arch64__) +#include "sparc64/pt-vfork.S" +#else +#include "sparc32/pt-vfork.S" +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_barrier_destroy.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_barrier_destroy.c new file mode 100644 index 000000000..ca96379c9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_barrier_destroy.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2002, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include "pthreadP.h" +#include <lowlevellock.h> + +int +pthread_barrier_destroy ( + pthread_barrier_t *barrier) +{ + union sparc_pthread_barrier *ibarrier; + int result = EBUSY; + + ibarrier = (union sparc_pthread_barrier *) barrier; + + int private = ibarrier->s.pshared ? LLL_SHARED : LLL_PRIVATE; + + lll_lock (ibarrier->b.lock, private); + + if (__builtin_expect (ibarrier->b.left == ibarrier->b.init_count, 1)) + /* The barrier is not used anymore. */ + result = 0; + else + /* Still used, return with an error. */ + lll_unlock (ibarrier->b.lock, private); + + return result; +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_barrier_init.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_barrier_init.c new file mode 100644 index 000000000..8182f1cef --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_barrier_init.c @@ -0,0 +1,55 @@ +/* Copyright (C) 2002, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include "pthreadP.h" +#include <lowlevellock.h> + +int +pthread_barrier_init ( + pthread_barrier_t *barrier, + const pthread_barrierattr_t *attr, + unsigned int count) +{ + union sparc_pthread_barrier *ibarrier; + + if (__builtin_expect (count == 0, 0)) + return EINVAL; + + struct pthread_barrierattr *iattr = (struct pthread_barrierattr *) attr; + if (iattr != NULL) + { + if (iattr->pshared != PTHREAD_PROCESS_PRIVATE + && __builtin_expect (iattr->pshared != PTHREAD_PROCESS_SHARED, 0)) + /* Invalid attribute. */ + return EINVAL; + } + + ibarrier = (union sparc_pthread_barrier *) barrier; + + /* Initialize the individual fields. */ + ibarrier->b.lock = LLL_LOCK_INITIALIZER; + ibarrier->b.left = count; + ibarrier->b.init_count = count; + ibarrier->b.curr_event = 0; + ibarrier->s.left_lock = 0; + ibarrier->s.pshared = (iattr && iattr->pshared == PTHREAD_PROCESS_SHARED); + + return 0; +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_barrier_wait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_barrier_wait.c new file mode 100644 index 000000000..73eaa695e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_barrier_wait.c @@ -0,0 +1 @@ +#include "sparc32/pthread_barrier_wait.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_once.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_once.c new file mode 100644 index 000000000..a6a470c02 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_once.c @@ -0,0 +1,95 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 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 <lowlevellock.h> + + +unsigned long int __fork_generation attribute_hidden; + + +static void +clear_once_control (void *arg) +{ + pthread_once_t *once_control = (pthread_once_t *) arg; + + *once_control = 0; + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +} + + +int +attribute_hidden +__pthread_once (once_control, init_routine) + pthread_once_t *once_control; + void (*init_routine) (void); +{ + while (1) + { + int oldval, val, newval; + + val = *once_control; + do + { + /* Check if the initialized has already been done. */ + if ((val & 2) != 0) + return 0; + + oldval = val; + newval = (oldval & 3) | __fork_generation | 1; + val = atomic_compare_and_exchange_val_acq (once_control, newval, + oldval); + } + while (__builtin_expect (val != oldval, 0)); + + /* Check if another thread already runs the initializer. */ + if ((oldval & 1) != 0) + { + /* Check whether the initializer execution was interrupted + by a fork. */ + if (((oldval ^ newval) & -4) == 0) + { + /* Same generation, some other thread was faster. Wait. */ + lll_futex_wait (once_control, newval, LLL_PRIVATE); + continue; + } + } + + /* This thread is the first here. Do the initialization. + Register a cleanup handler so that in case the thread gets + interrupted the initialization can be restarted. */ + pthread_cleanup_push (clear_once_control, once_control); + + init_routine (); + + pthread_cleanup_pop (0); + + + /* Add one to *once_control. */ + atomic_increment (once_control); + + /* Wake up all other threads. */ + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); + break; + } + + return 0; +} +weak_alias (__pthread_once, pthread_once) +strong_alias (__pthread_once, __pthread_once_internal) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sem_init.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sem_init.c new file mode 100644 index 000000000..f694b5e93 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sem_init.c @@ -0,0 +1,57 @@ +/* Copyright (C) 2002, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <string.h> +#include <semaphore.h> +#include <lowlevellock.h> +#include "semaphoreP.h" +#include <bits/kernel-features.h> + + +int +__new_sem_init (sem, pshared, value) + sem_t *sem; + int pshared; + unsigned int value; +{ + /* Parameter sanity check. */ + if (__builtin_expect (value > SEM_VALUE_MAX, 0)) + { + __set_errno (EINVAL); + return -1; + } + + /* Map to the internal type. */ + struct sparc_new_sem *isem = (struct sparc_new_sem *) sem; + + /* Use the values the user provided. */ + memset (isem, '\0', sizeof (*isem)); + isem->value = value; +#ifdef __ASSUME_PRIVATE_FUTEX + isem->private = pshared ? 0 : FUTEX_PRIVATE_FLAG; +#else + isem->private = pshared ? 0 : THREAD_GETMEM (THREAD_SELF, + header.private_futex); +#endif + + return 0; +} +weak_alias(__new_sem_init, sem_init) + diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S new file mode 100644 index 000000000..a6142aafe --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <libc/sysdeps/linux/sparc/clone.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pt-vfork.S new file mode 100644 index 000000000..fb01242b5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pt-vfork.S @@ -0,0 +1,45 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <tcb-offsets.h> + + .text + .globl __syscall_error +ENTRY(__vfork) + ld [%g7 + PID], %o5 + sub %g0, %o5, %o4 + st %o4, [%g7 + PID] + + LOADSYSCALL(vfork) + ta 0x10 + bcc 2f + mov %o7, %g1 + st %o5, [%g7 + PID] + call __syscall_error + mov %g1, %o7 +2: sub %o1, 1, %o1 + andcc %o0, %o1, %o0 + bne,a 1f + st %o5, [%g7 + PID] +1: retl + nop +END(__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c new file mode 100644 index 000000000..302d1b371 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c @@ -0,0 +1,94 @@ +/* Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 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 <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <pthreadP.h> + +/* Wait on barrier. */ +int +pthread_barrier_wait ( + pthread_barrier_t *barrier) +{ + union sparc_pthread_barrier *ibarrier + = (union sparc_pthread_barrier *) barrier; + int result = 0; + int private = ibarrier->s.pshared ? LLL_SHARED : LLL_PRIVATE; + + /* Make sure we are alone. */ + lll_lock (ibarrier->b.lock, private); + + /* One more arrival. */ + --ibarrier->b.left; + + /* Are these all? */ + if (ibarrier->b.left == 0) + { + /* Yes. Increment the event counter to avoid invalid wake-ups and + tell the current waiters that it is their turn. */ + ++ibarrier->b.curr_event; + + /* Wake up everybody. */ + lll_futex_wake (&ibarrier->b.curr_event, INT_MAX, private); + + /* 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->b.curr_event; + + /* Before suspending, make the barrier available to others. */ + lll_unlock (ibarrier->b.lock, private); + + /* Wait for the event counter of the barrier to change. */ + do + lll_futex_wait (&ibarrier->b.curr_event, event, private); + while (event == ibarrier->b.curr_event); + } + + /* Make sure the init_count is stored locally or in a register. */ + unsigned int init_count = ibarrier->b.init_count; + + /* If this was the last woken thread, unlock. */ + if (__atomic_is_v9 || ibarrier->s.pshared == 0) + { + if (atomic_increment_val (&ibarrier->b.left) == init_count) + /* We are done. */ + lll_unlock (ibarrier->b.lock, private); + } + else + { + unsigned int left; + /* Slightly more complicated. On pre-v9 CPUs, atomic_increment_val + is only atomic for threads within the same process, not for + multiple processes. */ + __sparc32_atomic_do_lock24 (&ibarrier->s.left_lock); + left = ++ibarrier->b.left; + __sparc32_atomic_do_unlock24 (&ibarrier->s.left_lock); + if (left == init_count) + /* We are done. */ + lll_unlock (ibarrier->b.lock, private); + } + + return result; +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c new file mode 100644 index 000000000..940728eeb --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c @@ -0,0 +1,55 @@ +/* sem_post -- post to a POSIX semaphore. SPARC version. + Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 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 <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <internaltypes.h> +#include <semaphore.h> + +int +__new_sem_post (sem_t *sem) +{ + struct sparc_new_sem *isem = (struct sparc_new_sem *) sem; + int nr; + + if (__atomic_is_v9) + nr = atomic_increment_val (&isem->value); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + nr = ++(isem->value); + __sparc32_atomic_do_unlock24 (&isem->lock); + } + atomic_full_barrier (); + if (isem->nwaiters > 0) + { + int err = lll_futex_wake (&isem->value, 1, + isem->private ^ FUTEX_PRIVATE_FLAG); + if (__builtin_expect (err, 0) < 0) + { + __set_errno (-err); + return -1; + } + } + return 0; +} +weak_alias(__new_sem_post, sem_post) + diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c new file mode 100644 index 000000000..aa5bd80ed --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c @@ -0,0 +1,148 @@ +/* sem_timedwait -- wait on a semaphore. SPARC version. + Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras <paulus@au.ibm.com>, 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 <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <internaltypes.h> +#include <semaphore.h> + +#include <pthreadP.h> + + +extern void __sem_wait_cleanup (void *arg) attribute_hidden; + + +int +sem_timedwait (sem_t *sem, const struct timespec *abstime) +{ + struct sparc_new_sem *isem = (struct sparc_new_sem *) sem; + int err; + int val; + + if (__atomic_is_v9) + val = atomic_decrement_if_positive (&isem->value); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + val = isem->value; + if (val > 0) + isem->value = val - 1; + __sparc32_atomic_do_unlock24 (&isem->lock); + } + + if (val > 0) + return 0; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + { + __set_errno (EINVAL); + return -1; + } + + if (__atomic_is_v9) + atomic_increment (&isem->nwaiters); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + isem->nwaiters++; + __sparc32_atomic_do_unlock24 (&isem->lock); + } + + pthread_cleanup_push (__sem_wait_cleanup, isem); + + while (1) + { + struct timeval tv; + struct timespec rt; + int sec, nsec; + + /* Get the current time. */ + __gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + sec = abstime->tv_sec - tv.tv_sec; + nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (nsec < 0) + { + nsec += 1000000000; + --sec; + } + + /* Already timed out? */ + err = -ETIMEDOUT; + if (sec < 0) + { + __set_errno (ETIMEDOUT); + err = -1; + break; + } + + /* Do wait. */ + rt.tv_sec = sec; + rt.tv_nsec = nsec; + + /* Enable asynchronous cancellation. Required by the standard. */ + int oldtype = __pthread_enable_asynccancel (); + + err = lll_futex_timed_wait (&isem->value, 0, &rt, + isem->private ^ FUTEX_PRIVATE_FLAG); + + /* Disable asynchronous cancellation. */ + __pthread_disable_asynccancel (oldtype); + + if (err != 0 && err != -EWOULDBLOCK) + { + __set_errno (-err); + err = -1; + break; + } + + if (__atomic_is_v9) + val = atomic_decrement_if_positive (&isem->value); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + val = isem->value; + if (val > 0) + isem->value = val - 1; + __sparc32_atomic_do_unlock24 (&isem->lock); + } + + if (val > 0) + { + err = 0; + break; + } + } + + pthread_cleanup_pop (0); + + if (__atomic_is_v9) + atomic_decrement (&isem->nwaiters); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + isem->nwaiters--; + __sparc32_atomic_do_unlock24 (&isem->lock); + } + + return err; +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c new file mode 100644 index 000000000..d4e893805 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c @@ -0,0 +1,54 @@ +/* sem_trywait -- wait on a semaphore. SPARC version. + Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras <paulus@au.ibm.com>, 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 <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <internaltypes.h> +#include <semaphore.h> + + +int +__new_sem_trywait (sem_t *sem) +{ + struct sparc_old_sem *isem = (struct sparc_old_sem *) sem; + int val; + + if (isem->value > 0) + { + if (__atomic_is_v9) + val = atomic_decrement_if_positive (&isem->value); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + val = isem->value; + if (val > 0) + isem->value = val - 1; + __sparc32_atomic_do_unlock24 (&isem->lock); + } + if (val > 0) + return 0; + } + + __set_errno (EAGAIN); + return -1; +} +weak_alias(__new_sem_trywait, sem_trywait) + diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c new file mode 100644 index 000000000..cfe04a802 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c @@ -0,0 +1,127 @@ +/* sem_wait -- wait on a semaphore. Generic futex-using version. + Copyright (C) 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras <paulus@au.ibm.com>, 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 <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <internaltypes.h> +#include <semaphore.h> + +#include <pthreadP.h> + + +void +attribute_hidden +__sem_wait_cleanup (void *arg) +{ + struct sparc_new_sem *isem = (struct sparc_new_sem *) arg; + + if (__atomic_is_v9) + atomic_decrement (&isem->nwaiters); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + isem->nwaiters--; + __sparc32_atomic_do_unlock24 (&isem->lock); + } +} + + +int +__new_sem_wait (sem_t *sem) +{ + struct sparc_new_sem *isem = (struct sparc_new_sem *) sem; + int err; + int val; + + if (__atomic_is_v9) + val = atomic_decrement_if_positive (&isem->value); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + val = isem->value; + if (val > 0) + isem->value = val - 1; + else + isem->nwaiters++; + __sparc32_atomic_do_unlock24 (&isem->lock); + } + + if (val > 0) + return 0; + + if (__atomic_is_v9) + atomic_increment (&isem->nwaiters); + else + /* Already done above while still holding isem->lock. */; + + pthread_cleanup_push (__sem_wait_cleanup, isem); + + while (1) + { + /* Enable asynchronous cancellation. Required by the standard. */ + int oldtype = __pthread_enable_asynccancel (); + + err = lll_futex_wait (&isem->value, 0, + isem->private ^ FUTEX_PRIVATE_FLAG); + + /* Disable asynchronous cancellation. */ + __pthread_disable_asynccancel (oldtype); + + if (err != 0 && err != -EWOULDBLOCK) + { + __set_errno (-err); + err = -1; + break; + } + + if (__atomic_is_v9) + val = atomic_decrement_if_positive (&isem->value); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + val = isem->value; + if (val > 0) + isem->value = val - 1; + __sparc32_atomic_do_unlock24 (&isem->lock); + } + + if (val > 0) + { + err = 0; + break; + } + } + + pthread_cleanup_pop (0); + + if (__atomic_is_v9) + atomic_decrement (&isem->nwaiters); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + isem->nwaiters--; + __sparc32_atomic_do_unlock24 (&isem->lock); + } + + return err; +} +weak_alias(__new_sem_wait, sem_wait) + diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h new file mode 100644 index 000000000..1f55bd623 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h @@ -0,0 +1,112 @@ +/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <tls.h> +#include <sysdep.h> +#ifndef __ASSEMBLER__ +# include <pthreadP.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + .globl __syscall_error; \ +ENTRY(name) \ + ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1;\ + cmp %g1, 0; \ + bne 1f; \ +.type __##syscall_name##_nocancel,@function; \ +.globl __##syscall_name##_nocancel; \ +__##syscall_name##_nocancel: \ + mov SYS_ify(syscall_name), %g1; \ + ta 0x10; \ + bcc 8f; \ + mov %o7, %g1; \ + call __syscall_error; \ + mov %g1, %o7; \ +8: jmpl %o7 + 8, %g0; \ + nop; \ +.size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;\ +1: save %sp, -96, %sp; \ + cfi_def_cfa_register(%fp); \ + cfi_window_save; \ + cfi_register(%o7, %i7); \ + CENABLE; \ + nop; \ + mov %o0, %l0; \ + COPY_ARGS_##args \ + mov SYS_ify(syscall_name), %g1; \ + ta 0x10; \ + bcc 1f; \ + mov %o0, %l1; \ + CDISABLE; \ + mov %l0, %o0; \ + call __syscall_error; \ + mov %l1, %o0; \ + b 2f; \ + mov -1, %l1; \ +1: CDISABLE; \ + mov %l0, %o0; \ +2: jmpl %i7 + 8, %g0; \ + restore %g0, %l1, %o0; + + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel +# define CDISABLE call __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +# define CENABLE call __libc_enable_asynccancel +# define CDISABLE call __libc_disable_asynccancel +# elif defined IS_IN_librt +# define CENABLE call __librt_enable_asynccancel +# define CDISABLE call __librt_disable_asynccancel +# else +# error Unsupported library +# endif + +#define COPY_ARGS_0 /* Nothing */ +#define COPY_ARGS_1 COPY_ARGS_0 mov %i0, %o0; +#define COPY_ARGS_2 COPY_ARGS_1 mov %i1, %o1; +#define COPY_ARGS_3 COPY_ARGS_2 mov %i2, %o2; +#define COPY_ARGS_4 COPY_ARGS_3 mov %i3, %o3; +#define COPY_ARGS_5 COPY_ARGS_4 mov %i4, %o4; +#define COPY_ARGS_6 COPY_ARGS_5 mov %i5, %o5; + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1 +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S new file mode 100644 index 000000000..8ee98684d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S @@ -0,0 +1,49 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <tcb-offsets.h> + + .text + .globl __syscall_error +ENTRY(__vfork) + ld [%g7 + PID], %o5 + cmp %o5, 0 + bne 1f + sub %g0, %o5, %o4 + sethi %hi(0x80000000), %o4 +1: st %o4, [%g7 + PID] + + LOADSYSCALL(vfork) + ta 0x10 + bcc 2f + mov %o7, %g1 + st %o5, [%g7 + PID] + call __syscall_error + mov %g1, %o7 +2: sub %o1, 1, %o1 + andcc %o0, %o1, %o0 + bne,a 1f + st %o5, [%g7 + PID] +1: retl + nop +END(__vfork) + +libc_hidden_def (vfork) +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S new file mode 100644 index 000000000..64e3bfc12 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <libc/sysdeps/linux/sparc/sparcv9/clone.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/pt-vfork.S new file mode 100644 index 000000000..8941043c3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/pt-vfork.S @@ -0,0 +1,45 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <tcb-offsets.h> + + .text + .globl __syscall_error +ENTRY(__vfork) + ld [%g7 + PID], %o5 + sub %g0, %o5, %o4 + st %o4, [%g7 + PID] + + LOADSYSCALL(vfork) + ta 0x6d + bcc,pt %xcc, 2f + mov %o7, %g1 + st %o5, [%g7 + PID] + call __syscall_error + mov %g1, %o7 +2: sub %o1, 1, %o1 + andcc %o0, %o1, %o0 + bne,a,pt %icc, 1f + st %o5, [%g7 + PID] +1: retl + nop +END(__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h new file mode 100644 index 000000000..aec2d4a86 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h @@ -0,0 +1,110 @@ +/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <pthreadP.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + .globl __syscall_error; \ +ENTRY(name) \ + ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1;\ + brnz,pn %g1, 1f; \ +.type __##syscall_name##_nocancel,@function; \ +.globl __##syscall_name##_nocancel; \ +__##syscall_name##_nocancel: \ + mov SYS_ify(syscall_name), %g1; \ + ta 0x6d; \ + bcc,pt %xcc, 8f; \ + mov %o7, %g1; \ + call __syscall_error; \ + mov %g1, %o7; \ +8: jmpl %o7 + 8, %g0; \ + nop; \ +.size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;\ +1: save %sp, -192, %sp; \ + cfi_def_cfa_register(%fp); \ + cfi_window_save; \ + cfi_register(%o7, %i7); \ + CENABLE; \ + nop; \ + mov %o0, %l0; \ + COPY_ARGS_##args \ + mov SYS_ify(syscall_name), %g1; \ + ta 0x6d; \ + bcc,pt %xcc, 1f; \ + mov %o0, %l1; \ + CDISABLE; \ + mov %l0, %o0; \ + call __syscall_error; \ + mov %l1, %o0; \ + ba,pt %xcc, 2f; \ + mov -1, %l1; \ +1: CDISABLE; \ + mov %l0, %o0; \ +2: jmpl %i7 + 8, %g0; \ + restore %g0, %l1, %o0; + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel +# define CDISABLE call __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +# define CENABLE call __libc_enable_asynccancel +# define CDISABLE call __libc_disable_asynccancel +# elif defined IS_IN_librt +# define CENABLE call __librt_enable_asynccancel +# define CDISABLE call __librt_disable_asynccancel +# else +# error Unsupported library +# endif + +#define COPY_ARGS_0 /* Nothing */ +#define COPY_ARGS_1 COPY_ARGS_0 mov %i0, %o0; +#define COPY_ARGS_2 COPY_ARGS_1 mov %i1, %o1; +#define COPY_ARGS_3 COPY_ARGS_2 mov %i2, %o2; +#define COPY_ARGS_4 COPY_ARGS_3 mov %i3, %o3; +#define COPY_ARGS_5 COPY_ARGS_4 mov %i4, %o4; +#define COPY_ARGS_6 COPY_ARGS_5 mov %i5, %o5; + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1 +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_create.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_create.c new file mode 100644 index 000000000..0a9c3372b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_create.c @@ -0,0 +1 @@ +#include "../../x86_64/timer_create.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_delete.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_delete.c new file mode 100644 index 000000000..f0d4fd21d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_delete.c @@ -0,0 +1 @@ +#include "../../x86_64/timer_delete.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_getoverr.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_getoverr.c new file mode 100644 index 000000000..82121a7a2 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_getoverr.c @@ -0,0 +1 @@ +#include "../../x86_64/timer_getoverr.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_gettime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_gettime.c new file mode 100644 index 000000000..313c05fea --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_gettime.c @@ -0,0 +1 @@ +#include "../../x86_64/timer_gettime.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_settime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_settime.c new file mode 100644 index 000000000..76f549cb4 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_settime.c @@ -0,0 +1 @@ +#include "../../x86_64/timer_settime.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S new file mode 100644 index 000000000..b4e89aceb --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S @@ -0,0 +1,49 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <tcb-offsets.h> + + .text + .globl __syscall_error +ENTRY(__vfork) + ld [%g7 + PID], %o5 + sethi %hi(0x80000000), %o3 + cmp %o5, 0 + sub %g0, %o5, %o4 + move %icc, %o3, %o4 + st %o4, [%g7 + PID] + + LOADSYSCALL(vfork) + ta 0x6d + bcc,pt %xcc, 2f + mov %o7, %g1 + st %o5, [%g7 + PID] + call __syscall_error + mov %g1, %o7 +2: sub %o1, 1, %o1 + andcc %o0, %o1, %o0 + bne,a,pt %icc, 1f + st %o5, [%g7 + PID] +1: retl + nop +END(__vfork) + +hidden_def (vfork) +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sysdep-cancel.h new file mode 100644 index 000000000..5be9beb92 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sysdep-cancel.h @@ -0,0 +1,5 @@ +#if defined(__arch64__) +#include "sparc64/sysdep-cancel.h" +#else +#include "sparc32/sysdep-cancel.h" +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/vfork.S new file mode 100644 index 000000000..160cd0b10 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/vfork.S @@ -0,0 +1,5 @@ +#if defined(__arch64__) +#include "sparc64/vfork.S" +#else +#include "sparc32/vfork.S" +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/structsem.sym b/libpthread/nptl/sysdeps/unix/sysv/linux/structsem.sym new file mode 100644 index 000000000..0e2a15f2b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/structsem.sym @@ -0,0 +1,12 @@ +#include <limits.h> +#include <stddef.h> +#include <sched.h> +#include <bits/pthreadtypes.h> +#include "internaltypes.h" + +-- + +VALUE offsetof (struct new_sem, value) +PRIVATE offsetof (struct new_sem, private) +NWAITERS offsetof (struct new_sem, nwaiters) +SEM_VALUE_MAX SEM_VALUE_MAX diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_create.c b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_create.c new file mode 100644 index 000000000..a7da2a09a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_create.c @@ -0,0 +1,243 @@ +/* Copyright (C) 2003,2004, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> +#include <pthread.h> +#include <signal.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <sysdep.h> +#include <bits/kernel-features.h> +#include <internaltypes.h> +#include <pthreadP.h> +#include "kernel-posix-timers.h" +#include "kernel-posix-cpu-timers.h" + + +#ifdef __NR_timer_create +# ifndef __ASSUME_POSIX_TIMERS +static int compat_timer_create (clockid_t clock_id, struct sigevent *evp, + timer_t *timerid); +# define timer_create static compat_timer_create +# include <nptl/sysdeps/pthread/timer_create.c> +# undef timer_create + +/* Nonzero if the system calls are not available. */ +int __no_posix_timers attribute_hidden; +# endif + +# ifdef timer_create_alias +# define timer_create timer_create_alias +# endif + + +int +timer_create ( + clockid_t clock_id, + struct sigevent *evp, + timer_t *timerid) +{ +# undef timer_create +# ifndef __ASSUME_POSIX_TIMERS + if (__no_posix_timers >= 0) +# endif + { + clockid_t syscall_clockid = (clock_id == CLOCK_PROCESS_CPUTIME_ID + ? MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED) + : clock_id == CLOCK_THREAD_CPUTIME_ID + ? MAKE_THREAD_CPUCLOCK (0, CPUCLOCK_SCHED) + : clock_id); + + /* If the user wants notification via a thread we need to handle + this special. */ + if (evp == NULL + || __builtin_expect (evp->sigev_notify != SIGEV_THREAD, 1)) + { + struct sigevent local_evp; + + /* We avoid allocating too much memory by basically + using struct timer as a derived class with the + first two elements being in the superclass. We only + need these two elements here. */ + struct timer *newp = (struct timer *) malloc (offsetof (struct timer, + thrfunc)); + if (newp == NULL) + /* No more memory. */ + return -1; + + if (evp == NULL) + { + /* The kernel has to pass up the timer ID which is a + userlevel object. Therefore we cannot leave it up to + the kernel to determine it. */ + local_evp.sigev_notify = SIGEV_SIGNAL; + local_evp.sigev_signo = SIGALRM; + local_evp.sigev_value.sival_ptr = newp; + + evp = &local_evp; + } + + kernel_timer_t ktimerid; + int retval = INLINE_SYSCALL (timer_create, 3, syscall_clockid, evp, + &ktimerid); + +# ifndef __ASSUME_POSIX_TIMERS + if (retval != -1 || errno != ENOSYS) +# endif + { +# ifndef __ASSUME_POSIX_TIMERS + __no_posix_timers = 1; +# endif + + if (retval != -1) + { + newp->sigev_notify = (evp != NULL + ? evp->sigev_notify : SIGEV_SIGNAL); + newp->ktimerid = ktimerid; + + *timerid = (timer_t) newp; + } + else + { + /* Cannot allocate the timer, fail. */ + free (newp); + retval = -1; + } + + return retval; + } + + free (newp); + +# ifndef __ASSUME_POSIX_TIMERS + /* When we come here the syscall does not exist. Make sure we + do not try to use it again. */ + __no_posix_timers = -1; +# endif + } + else + { +# ifndef __ASSUME_POSIX_TIMERS + /* Make sure we have the necessary kernel support. */ + if (__no_posix_timers == 0) + { + INTERNAL_SYSCALL_DECL (err); + struct timespec ts; + int res; + res = INTERNAL_SYSCALL (clock_getres, err, 2, + CLOCK_REALTIME, &ts); + __no_posix_timers = (INTERNAL_SYSCALL_ERROR_P (res, err) + ? -1 : 1); + } + + if (__no_posix_timers > 0) +# endif + { + /* Create the helper thread. */ + pthread_once (&__helper_once, __start_helper_thread); + if (__helper_tid == 0) + { + /* No resources to start the helper thread. */ + __set_errno (EAGAIN); + return -1; + } + + struct timer *newp; + newp = (struct timer *) malloc (sizeof (struct timer)); + if (newp == NULL) + return -1; + + /* Copy the thread parameters the user provided. */ + newp->sival = evp->sigev_value; + newp->thrfunc = evp->sigev_notify_function; + newp->sigev_notify = SIGEV_THREAD; + + /* We cannot simply copy the thread attributes since the + implementation might keep internal information for + each instance. */ + (void) pthread_attr_init (&newp->attr); + if (evp->sigev_notify_attributes != NULL) + { + struct pthread_attr *nattr; + struct pthread_attr *oattr; + + nattr = (struct pthread_attr *) &newp->attr; + oattr = (struct pthread_attr *) evp->sigev_notify_attributes; + + nattr->schedparam = oattr->schedparam; + nattr->schedpolicy = oattr->schedpolicy; + nattr->flags = oattr->flags; + nattr->guardsize = oattr->guardsize; + nattr->stackaddr = oattr->stackaddr; + nattr->stacksize = oattr->stacksize; + } + + /* In any case set the detach flag. */ + (void) pthread_attr_setdetachstate (&newp->attr, + PTHREAD_CREATE_DETACHED); + + /* Create the event structure for the kernel timer. */ + struct sigevent sev = + { .sigev_value.sival_ptr = newp, + .sigev_signo = SIGTIMER, + .sigev_notify = SIGEV_SIGNAL | SIGEV_THREAD_ID, + ._sigev_un = { ._pad = { [0] = __helper_tid } } }; + + /* Create the timer. */ + INTERNAL_SYSCALL_DECL (err); + int res; + res = INTERNAL_SYSCALL (timer_create, err, 3, + syscall_clockid, &sev, &newp->ktimerid); + if (! INTERNAL_SYSCALL_ERROR_P (res, err)) + { + /* Add to the queue of active timers with thread + delivery. */ + pthread_mutex_lock (&__active_timer_sigev_thread_lock); + newp->next = __active_timer_sigev_thread; + __active_timer_sigev_thread = newp; + pthread_mutex_unlock (&__active_timer_sigev_thread_lock); + + *timerid = (timer_t) newp; + return 0; + } + + /* Free the resources. */ + free (newp); + + __set_errno (INTERNAL_SYSCALL_ERRNO (res, err)); + + return -1; + } + } + } + +# ifndef __ASSUME_POSIX_TIMERS + /* Compatibility code. */ + return compat_timer_create (clock_id, evp, timerid); +# endif +} +#else +# ifdef timer_create_alias +# define timer_create timer_create_alias +# endif +/* The new system calls are not available. Use the userlevel + implementation. */ +# include <nptl/sysdeps/pthread/timer_create.c> +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_delete.c b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_delete.c new file mode 100644 index 000000000..5ad40b99a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_delete.c @@ -0,0 +1,115 @@ +/* Copyright (C) 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> +#include <stdlib.h> +#include <time.h> +#include <sysdep.h> +#include <bits/kernel-features.h> +#include "kernel-posix-timers.h" + + +#ifdef __NR_timer_delete +# ifndef __ASSUME_POSIX_TIMERS +static int compat_timer_delete (timer_t timerid); +# define timer_delete static compat_timer_delete +# include <nptl/sysdeps/pthread/timer_delete.c> +# undef timer_delete +# endif + +# ifdef timer_delete_alias +# define timer_delete timer_delete_alias +# endif + + +int +timer_delete ( + timer_t timerid) +{ +# undef timer_delete +# ifndef __ASSUME_POSIX_TIMERS + if (__no_posix_timers >= 0) +# endif + { + struct timer *kt = (struct timer *) timerid; + + /* Delete the kernel timer object. */ + int res = INLINE_SYSCALL (timer_delete, 1, kt->ktimerid); + + if (res == 0) + { + if (kt->sigev_notify == SIGEV_THREAD) + { + /* Remove the timer from the list. */ + pthread_mutex_lock (&__active_timer_sigev_thread_lock); + if (__active_timer_sigev_thread == kt) + __active_timer_sigev_thread = kt->next; + else + { + struct timer *prevp = __active_timer_sigev_thread; + while (prevp->next != NULL) + if (prevp->next == kt) + { + prevp->next = kt->next; + break; + } + else + prevp = prevp->next; + } + pthread_mutex_unlock (&__active_timer_sigev_thread_lock); + } + +# ifndef __ASSUME_POSIX_TIMERS + /* We know the syscall support is available. */ + __no_posix_timers = 1; +# endif + + /* Free the memory. */ + (void) free (kt); + + return 0; + } + + /* The kernel timer is not known or something else bad happened. + Return the error. */ +# ifndef __ASSUME_POSIX_TIMERS + if (errno != ENOSYS) + { + __no_posix_timers = 1; +# endif + return -1; +# ifndef __ASSUME_POSIX_TIMERS + } + + __no_posix_timers = -1; +# endif + } + +# ifndef __ASSUME_POSIX_TIMERS + return compat_timer_delete (timerid); +# endif +} +#else +# ifdef timer_delete_alias +# define timer_delete timer_delete_alias +# endif +/* The new system calls are not available. Use the userlevel + implementation. */ +# include <nptl/sysdeps/pthread/timer_delete.c> +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_getoverr.c b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_getoverr.c new file mode 100644 index 000000000..62a558aef --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_getoverr.c @@ -0,0 +1,81 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> +#include <time.h> +#include <sysdep.h> +#include <bits/kernel-features.h> +#include "kernel-posix-timers.h" + + +#ifdef __NR_timer_getoverrun +# ifndef __ASSUME_POSIX_TIMERS +static int compat_timer_getoverrun (timer_t timerid); +# define timer_getoverrun static compat_timer_getoverrun +# include <nptl/sysdeps/pthread/timer_getoverr.c> +# undef timer_getoverrun +# endif + +# ifdef timer_getoverrun_alias +# define timer_getoverrun timer_getoverrun_alias +# endif + + +int +timer_getoverrun ( + timer_t timerid) +{ +# undef timer_getoverrun +# ifndef __ASSUME_POSIX_TIMERS + if (__no_posix_timers >= 0) +# endif + { + struct timer *kt = (struct timer *) timerid; + + /* Get the information from the kernel. */ + int res = INLINE_SYSCALL (timer_getoverrun, 1, kt->ktimerid); + +# ifndef __ASSUME_POSIX_TIMERS + if (res != -1 || errno != ENOSYS) + { + /* We know the syscall support is available. */ + __no_posix_timers = 1; +# endif + return res; +# ifndef __ASSUME_POSIX_TIMERS + } +# endif + +# ifndef __ASSUME_POSIX_TIMERS + __no_posix_timers = -1; +# endif + } + +# ifndef __ASSUME_POSIX_TIMERS + return compat_timer_getoverrun (timerid); +# endif +} +#else +# ifdef timer_getoverrun_alias +# define timer_getoverrun timer_getoverrun_alias +# endif +/* The new system calls are not available. Use the userlevel + implementation. */ +# include <nptl/sysdeps/pthread/timer_getoverr.c> +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_gettime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_gettime.c new file mode 100644 index 000000000..31401b19b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_gettime.c @@ -0,0 +1,83 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> +#include <stdlib.h> +#include <time.h> +#include <sysdep.h> +#include <bits/kernel-features.h> +#include "kernel-posix-timers.h" + + +#ifdef __NR_timer_gettime +# ifndef __ASSUME_POSIX_TIMERS +static int compat_timer_gettime (timer_t timerid, struct itimerspec *value); +# define timer_gettime static compat_timer_gettime +# include <nptl/sysdeps/pthread/timer_gettime.c> +# undef timer_gettime +# endif + +# ifdef timer_gettime_alias +# define timer_gettime timer_gettime_alias +# endif + + +int +timer_gettime ( + timer_t timerid, + struct itimerspec *value) +{ +# undef timer_gettime +# ifndef __ASSUME_POSIX_TIMERS + if (__no_posix_timers >= 0) +# endif + { + struct timer *kt = (struct timer *) timerid; + + /* Delete the kernel timer object. */ + int res = INLINE_SYSCALL (timer_gettime, 2, kt->ktimerid, value); + +# ifndef __ASSUME_POSIX_TIMERS + if (res != -1 || errno != ENOSYS) + { + /* We know the syscall support is available. */ + __no_posix_timers = 1; +# endif + return res; +# ifndef __ASSUME_POSIX_TIMERS + } +# endif + +# ifndef __ASSUME_POSIX_TIMERS + __no_posix_timers = -1; +# endif + } + +# ifndef __ASSUME_POSIX_TIMERS + return compat_timer_gettime (timerid, value); +# endif +} +#else +# ifdef timer_gettime_alias +# define timer_gettime timer_gettime_alias +# endif +/* The new system calls are not available. Use the userlevel + implementation. */ +# include <nptl/sysdeps/pthread/timer_gettime.c> +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_routines.c b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_routines.c new file mode 100644 index 000000000..2681961bf --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_routines.c @@ -0,0 +1,204 @@ +/* Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> +#include <setjmp.h> +#include <signal.h> +#include <stdbool.h> +#include <sysdep.h> +#include <bits/kernel-features.h> +#include <pthreadP.h> +#include "kernel-posix-timers.h" + + +/* List of active SIGEV_THREAD timers. */ +struct timer *__active_timer_sigev_thread; +/* Lock for the __active_timer_sigev_thread. */ +pthread_mutex_t __active_timer_sigev_thread_lock = PTHREAD_MUTEX_INITIALIZER; + + +struct thread_start_data +{ + void (*thrfunc) (sigval_t); + sigval_t sival; +}; + + +#ifdef __NR_timer_create +/* Helper thread to call the user-provided function. */ +static void * +timer_sigev_thread (void *arg) +{ + /* The parent thread has all signals blocked. This is a bit + surprising for user code, although valid. We unblock all + signals. */ + sigset_t ss; + sigemptyset (&ss); + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, NULL, _NSIG / 8); + + struct thread_start_data *td = (struct thread_start_data *) arg; + + void (*thrfunc) (sigval_t) = td->thrfunc; + sigval_t sival = td->sival; + + /* The TD object was allocated in timer_helper_thread. */ + free (td); + + /* Call the user-provided function. */ + thrfunc (sival); + + return NULL; +} + + +/* Helper function to support starting threads for SIGEV_THREAD. */ +static void * +timer_helper_thread (void *arg) +{ + /* Wait for the SIGTIMER signal, allowing the setXid signal, and + none else. */ + sigset_t ss; + sigemptyset (&ss); + __sigaddset (&ss, SIGTIMER); + + /* Endless loop of waiting for signals. The loop is only ended when + the thread is canceled. */ + while (1) + { + siginfo_t si; + + /* sigwaitinfo cannot be used here, since it deletes + SIGCANCEL == SIGTIMER from the set. */ + + int oldtype = LIBC_CANCEL_ASYNC (); + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + int result = INLINE_SYSCALL (rt_sigtimedwait, 4, &ss, &si, NULL, + _NSIG / 8); + + LIBC_CANCEL_RESET (oldtype); + + if (result > 0) + { + if (si.si_code == SI_TIMER) + { + struct timer *tk = (struct timer *) si.si_ptr; + + /* Check the timer is still used and will not go away + while we are reading the values here. */ + pthread_mutex_lock (&__active_timer_sigev_thread_lock); + + struct timer *runp = __active_timer_sigev_thread; + while (runp != NULL) + if (runp == tk) + break; + else + runp = runp->next; + + if (runp != NULL) + { + struct thread_start_data *td = malloc (sizeof (*td)); + + /* There is not much we can do if the allocation fails. */ + if (td != NULL) + { + /* This is the signal we are waiting for. */ + td->thrfunc = tk->thrfunc; + td->sival = tk->sival; + + pthread_t th; + (void) pthread_create (&th, &tk->attr, + timer_sigev_thread, td); + } + } + + pthread_mutex_unlock (&__active_timer_sigev_thread_lock); + } + else if (si.si_code == SI_TKILL) + /* The thread is canceled. */ + pthread_exit (NULL); + } + } +} + + +/* Control variable for helper thread creation. */ +pthread_once_t __helper_once attribute_hidden; + + +/* TID of the helper thread. */ +pid_t __helper_tid attribute_hidden; + + +/* Reset variables so that after a fork a new helper thread gets started. */ +static void +reset_helper_control (void) +{ + __helper_once = PTHREAD_ONCE_INIT; + __helper_tid = 0; +} + + +void +attribute_hidden +__start_helper_thread (void) +{ + /* The helper thread needs only very little resources + and should go away automatically when canceled. */ + pthread_attr_t attr; + (void) pthread_attr_init (&attr); + (void) pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN); + + /* Block all signals in the helper thread but SIGSETXID. To do this + thoroughly we temporarily have to block all signals here. The + helper can lose wakeups if SIGCANCEL is not blocked throughout, + but sigfillset omits it SIGSETXID. So, we add SIGCANCEL back + explicitly here. */ + sigset_t ss; + sigset_t oss; + sigfillset (&ss); + __sigaddset (&ss, SIGCANCEL); + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, &oss, _NSIG / 8); + + /* Create the helper thread for this timer. */ + pthread_t th; + int res = pthread_create (&th, &attr, timer_helper_thread, NULL); + if (res == 0) + /* We managed to start the helper thread. */ + __helper_tid = ((struct pthread *) th)->tid; + + /* Restore the signal mask. */ + INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &oss, NULL, + _NSIG / 8); + + /* No need for the attribute anymore. */ + (void) pthread_attr_destroy (&attr); + + /* We have to make sure that after fork()ing a new helper thread can + be created. */ + pthread_atfork (NULL, NULL, reset_helper_control); +} +#endif + +#ifndef __ASSUME_POSIX_TIMERS +# include <nptl/sysdeps/pthread/timer_routines.c> +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c new file mode 100644 index 000000000..8c6ad91fa --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c @@ -0,0 +1,88 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> +#include <stdlib.h> +#include <time.h> +#include <sysdep.h> +#include <bits/kernel-features.h> +#include "kernel-posix-timers.h" + + +#ifdef __NR_timer_settime +# ifndef __ASSUME_POSIX_TIMERS +static int compat_timer_settime (timer_t timerid, int flags, + const struct itimerspec *value, + struct itimerspec *ovalue); +# define timer_settime static compat_timer_settime +# include <nptl/sysdeps/pthread/timer_settime.c> +# undef timer_settime +# endif + +# ifdef timer_settime_alias +# define timer_settime timer_settime_alias +# endif + + +int +timer_settime ( + timer_t timerid, + int flags, + const struct itimerspec *value, + struct itimerspec *ovalue) +{ +# undef timer_settime +# ifndef __ASSUME_POSIX_TIMERS + if (__no_posix_timers >= 0) +# endif + { + struct timer *kt = (struct timer *) timerid; + + /* Delete the kernel timer object. */ + int res = INLINE_SYSCALL (timer_settime, 4, kt->ktimerid, flags, + value, ovalue); + +# ifndef __ASSUME_POSIX_TIMERS + if (res != -1 || errno != ENOSYS) + { + /* We know the syscall support is available. */ + __no_posix_timers = 1; +# endif + return res; +# ifndef __ASSUME_POSIX_TIMERS + } +# endif + +# ifndef __ASSUME_POSIX_TIMERS + __no_posix_timers = -1; +# endif + } + +# ifndef __ASSUME_POSIX_TIMERS + return compat_timer_settime (timerid, flags, value, ovalue); +# endif +} +#else +# ifdef timer_settime_alias +# define timer_settime timer_settime_alias +# endif +/* The new system calls are not available. Use the userlevel + implementation. */ +# include <nptl/sysdeps/pthread/timer_settime.c> +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c new file mode 100644 index 000000000..7eb095fd3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c @@ -0,0 +1,123 @@ +/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdlib.h> +#include <fork.h> +#include <atomic.h> +#include <tls.h> + + +void +__unregister_atfork ( + void *dso_handle) +{ + /* Check whether there is any entry in the list which we have to + remove. It is likely that this is not the case so don't bother + getting the lock. + + We do not worry about other threads adding entries for this DSO + right this moment. If this happens this is a race and we can do + whatever we please. The program will crash anyway seen. */ + struct fork_handler *runp = __fork_handlers; + struct fork_handler *lastp = NULL; + + while (runp != NULL) + if (runp->dso_handle == dso_handle) + break; + else + { + lastp = runp; + runp = runp->next; + } + + if (runp == NULL) + /* Nothing to do. */ + return; + + /* Get the lock to not conflict with additions or deletions. Note + that there couldn't have been another thread deleting something. + The __unregister_atfork function is only called from the + dlclose() code which itself serializes the operations. */ + lll_lock (__fork_lock, LLL_PRIVATE); + + /* We have to create a new list with all the entries we don't remove. */ + struct deleted_handler + { + struct fork_handler *handler; + struct deleted_handler *next; + } *deleted = NULL; + + /* Remove the entries for the DSO which is unloaded from the list. + It's a single linked list so readers are. */ + do + { + again: + if (runp->dso_handle == dso_handle) + { + if (lastp == NULL) + { + /* We have to use an atomic operation here because + __linkin_atfork also uses one. */ + if (catomic_compare_and_exchange_bool_acq (&__fork_handlers, + runp->next, runp) + != 0) + { + runp = __fork_handlers; + goto again; + } + } + else + lastp->next = runp->next; + + /* We cannot overwrite the ->next element now. Put the deleted + entries in a separate list. */ + struct deleted_handler *newp = alloca (sizeof (*newp)); + newp->handler = runp; + newp->next = deleted; + deleted = newp; + } + else + lastp = runp; + + runp = runp->next; + } + while (runp != NULL); + + /* Release the lock. */ + lll_unlock (__fork_lock, LLL_PRIVATE); + + /* Walk the list of all entries which have to be deleted. */ + while (deleted != NULL) + { + /* We need to be informed by possible current users. */ + deleted->handler->need_signal = 1; + /* Make sure this gets written out first. */ + atomic_write_barrier (); + + /* Decrement the reference counter. If it does not reach zero + wait for the last user. */ + atomic_decrement (&deleted->handler->refcntr); + unsigned int val; + while ((val = deleted->handler->refcntr) != 0) + lll_futex_wait (&deleted->handler->refcntr, val, LLL_PRIVATE); + + deleted = deleted->next; + } +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/unwindbuf.sym b/libpthread/nptl/sysdeps/unix/sysv/linux/unwindbuf.sym new file mode 100644 index 000000000..8044b4078 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/unwindbuf.sym @@ -0,0 +1,7 @@ +#include <pthread.h> +#include <stddef.h> + +-- + +UNWINDBUFSIZE sizeof (__pthread_unwind_buf_t) +UWJMPBUF offsetof (__pthread_unwind_buf_t, __cancel_jmp_buf) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/waitpid.S b/libpthread/nptl/sysdeps/unix/sysv/linux/waitpid.S new file mode 100644 index 000000000..f55d34629 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/waitpid.S @@ -0,0 +1,19 @@ +#include <sysdep-cancel.h> + +/* +extern pid_t __waitpid_nocancel (pid_t, int *, int) attribute_hidden; +*/ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + + +PSEUDO (__waitpid, waitpid, 3) +ret +PSEUDO_END(__waitpid) + +libc_hidden_def (__waitpid) +weak_alias (__waitpid, waitpid) +libc_hidden_weak (waitpid) +weak_alias (__waitpid, __libc_waitpid) +libc_hidden_weak (__libc_waitpid) + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/write.S b/libpthread/nptl/sysdeps/unix/sysv/linux/write.S new file mode 100644 index 000000000..43de3320d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/write.S @@ -0,0 +1,19 @@ +#include <sysdep-cancel.h> + +/* +extern int __write_nocancel (int, const void *, size_t) attribute_hidden; +*/ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +PSEUDO (__libc_write, write, 3) +ret +PSEUDO_END(__libc_write) + +libc_hidden_def (__write_nocancel) +libc_hidden_def (__libc_write) +weak_alias (__libc_write, __write) +libc_hidden_weak (__write) +weak_alias (__libc_write, write) +libc_hidden_weak (write) + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile new file mode 100644 index 000000000..43a6fad84 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../../../../ +top_builddir=../../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile.arch b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile.arch new file mode 100644 index 000000000..53a87728f --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile.arch @@ -0,0 +1,78 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# +LINUX_ARCH_DIR:=$(top_srcdir)libpthread/nptl/sysdeps/unix/sysv/linux/x86_64 +LINUX_ARCH_OUT:=$(top_builddir)libpthread/nptl/sysdeps/unix/sysv/linux/x86_64 + + +libpthread_SSRC = pt-vfork.S clone.S pthread_once.S +libpthread_CSRC = pthread_spin_init.c pt-__syscall_error.c + +libc_a_CSRC = fork.c +libc_a_SSRC = clone.S vfork.S + +libpthread_SSRC += lowlevellock.S pthread_barrier_wait.S pthread_cond_signal.S pthread_cond_broadcast.S \ + sem_post.S sem_timedwait.S lowlevelrobustlock.S \ + sem_trywait.S sem_wait.S pthread_rwlock_rdlock.S pthread_rwlock_wrlock.S \ + pthread_rwlock_timedrdlock.S pthread_rwlock_timedwrlock.S pthread_rwlock_unlock.S \ + pthread_spin_unlock.S +# pthread_cond_timedwait.S pthread_cond_wait.S +libc_a_SSRC += libc-lowlevellock.S + + +CFLAGS-OMIT-fork.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 +CFLAGS-pt-__syscall_error.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 + +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y) +CFLAGS-fork.c = -D__USE_STDIO_FUTEXES__ +endif + +ASFLAGS-pt-vfork.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-lowlevellock.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_once.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT -DUSE___THREAD + + +ASFLAGS-clone.S = -D_LIBC_REENTRANT +ASFLAGS-vfork.S = -D_LIBC_REENTRANT +ASFLAGS-libc-lowlevellock.S = -D_LIBC_REENTRANT + +ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) +#Needed to use the correct SYSCALL_ERROR_HANDLER +ASFLAGS-clone.S += -DUSE___THREAD +ASFLAGS-vfork.S += -DUSE___THREAD +ASFLAGS-sem_wait.S += -DUSE___THREAD +ASFLAGS-sem_trywait.S += -DUSE___THREAD +ASFLAGS-sem_timedwait.S += -DUSE___THREAD +ASFLAGS-sem_post.S += -DUSE___THREAD +endif + +CFLAGS += $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +LINUX_ARCH_OBJ:=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libpthread_SSRC)) +LINUX_ARCH_OBJ+=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libpthread_CSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(LINUX_ARCH_OBJ:.o=.os) +else +libpthread-a-y += $(LINUX_ARCH_OBJ) +endif +libpthread-so-y += $(LINUX_ARCH_OBJ:.o=.oS) + +libpthread-nomulti-y+=$(LINUX_ARCH_OBJS) + +LIBC_LINUX_ARCH_OBJ:=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libc_a_CSRC)) +LIBC_LINUX_ARCH_OBJ+=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libc_a_SSRC)) + +libc-static-y+=$(LIBC_LINUX_ARCH_OBJ) +libc-shared-y+=$(LIBC_LINUX_ARCH_OBJ:.o=.oS) + +libc-nomulti-y+=$(LIBC_LINUX_ARCH_OBJ) + +objclean-y+=nptl_linux_arch_clean + +nptl_linux_arch_clean: + $(do_rm) $(addprefix $(LINUX_ARCH_OUT)/*., o os oS) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h new file mode 100644 index 000000000..7a09c8119 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h @@ -0,0 +1,225 @@ +/* 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 <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#include <bits/wordsize.h> + +#if __WORDSIZE == 64 +# define __SIZEOF_PTHREAD_ATTR_T 56 +# define __SIZEOF_PTHREAD_MUTEX_T 40 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 56 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 32 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#else +# define __SIZEOF_PTHREAD_ATTR_T 36 +# define __SIZEOF_PTHREAD_MUTEX_T 24 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 32 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 20 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#endif + + +/* Thread identifiers. The structure of the attribute type is not + exposed on purpose. */ +typedef unsigned long int pthread_t; + + +typedef union +{ + char __size[__SIZEOF_PTHREAD_ATTR_T]; + long int __align; +} pthread_attr_t; + + +#if __WORDSIZE == 64 +typedef struct __pthread_internal_list +{ + struct __pthread_internal_list *__prev; + struct __pthread_internal_list *__next; +} __pthread_list_t; +#else +typedef struct __pthread_internal_slist +{ + struct __pthread_internal_slist *__next; +} __pthread_slist_t; +#endif + + +/* Data structures for mutex handling. The structure of the attribute + type is not exposed on purpose. */ +typedef union +{ + struct __pthread_mutex_s + { + int __lock; + unsigned int __count; + int __owner; +#if __WORDSIZE == 64 + unsigned int __nusers; +#endif + /* KIND must stay at this position in the structure to maintain + binary compatibility. */ + int __kind; +#if __WORDSIZE == 64 + int __spins; + __pthread_list_t __list; +# define __PTHREAD_MUTEX_HAVE_PREV 1 +#else + unsigned int __nusers; + __extension__ union + { + int __spins; + __pthread_slist_t __list; + }; +#endif + } __data; + char __size[__SIZEOF_PTHREAD_MUTEX_T]; + long int __align; +} pthread_mutex_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; + int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling. The structure of + the attribute type is not exposed on purpose. */ +typedef union +{ + struct + { + int __lock; + unsigned int __futex; + __extension__ unsigned long long int __total_seq; + __extension__ unsigned long long int __wakeup_seq; + __extension__ unsigned long long int __woken_seq; + void *__mutex; + unsigned int __nwaiters; + unsigned int __broadcast_seq; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_CONDATTR_T]; + int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling. The + structure of the attribute type is not exposed on purpose. */ +typedef union +{ +# if __WORDSIZE == 64 + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + int __writer; + int __shared; + unsigned long int __pad1; + unsigned long int __pad2; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned int __flags; + } __data; +# else + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; + unsigned char __shared; + unsigned char __pad1; + unsigned char __pad2; + int __writer; + } __data; +# endif + char __size[__SIZEOF_PTHREAD_RWLOCK_T]; + long int __align; +} pthread_rwlock_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; + long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type. The structure of the type is + deliberately not exposed. */ +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIER_T]; + long int __align; +} pthread_barrier_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; + int __align; +} pthread_barrierattr_t; +#endif + + +#if __WORDSIZE == 32 +/* Extra attributes for the cleanup functions. */ +# define __cleanup_fct_attribute __attribute__ ((__regparm__ (1))) +#endif + +#endif /* bits/pthreadtypes.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h new file mode 100644 index 000000000..e973bc5bf --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SEMAPHORE_H +# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." +#endif + +#include <bits/wordsize.h> + +#if __WORDSIZE == 64 +# define __SIZEOF_SEM_T 32 +#else +# define __SIZEOF_SEM_T 16 +#endif + + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + + +typedef union +{ + char __size[__SIZEOF_SEM_T]; + long int __align; +} sem_t; diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/cancellation.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/cancellation.S new file mode 100644 index 000000000..680696200 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/cancellation.S @@ -0,0 +1,116 @@ +/* Copyright (C) 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2009. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <tcb-offsets.h> +#include <kernel-features.h> +#include "lowlevellock.h" + +#ifdef IS_IN_libpthread +# ifdef SHARED +# define __pthread_unwind __GI___pthread_unwind +# endif +#else +# ifndef SHARED + .weak __pthread_unwind +# endif +#endif + + +#ifdef __ASSUME_PRIVATE_FUTEX +# define LOAD_PRIVATE_FUTEX_WAIT(reg) \ + movl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg +#else +# if FUTEX_WAIT == 0 +# define LOAD_PRIVATE_FUTEX_WAIT(reg) \ + movl %fs:PRIVATE_FUTEX, reg +# else +# define LOAD_PRIVATE_FUTEX_WAIT(reg) \ + movl %fs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAIT, reg +# endif +#endif + +/* It is crucial that the functions in this file don't modify registers + other than %rax and %r11. The syscall wrapper code depends on this + because it doesn't explicitly save the other registers which hold + relevant values. */ + .text + + .hidden __pthread_enable_asynccancel +ENTRY(__pthread_enable_asynccancel) + movl %fs:CANCELHANDLING, %eax +2: movl %eax, %r11d + orl $TCB_CANCELTYPE_BITMASK, %r11d + cmpl %eax, %r11d + je 1f + + lock + cmpxchgl %r11d, %fs:CANCELHANDLING + jnz 2b + + andl $(TCB_CANCELSTATE_BITMASK|TCB_CANCELTYPE_BITMASK|TCB_CANCELED_BITMASK|TCB_EXITING_BITMASK|TCB_CANCEL_RESTMASK|TCB_TERMINATED_BITMASK), %r11d + cmpl $(TCB_CANCELTYPE_BITMASK|TCB_CANCELED_BITMASK), %r11d + je 3f + +1: ret + +3: movq $TCB_PTHREAD_CANCELED, %fs:RESULT + lock + orl $TCB_EXITING_BITMASK, %fs:CANCELHANDLING + movq %fs:CLEANUP_JMP_BUF, %rdi +#ifdef SHARED + call __pthread_unwind@PLT +#else + call __pthread_unwind +#endif + hlt +END(__pthread_enable_asynccancel) + + + .hidden __pthread_disable_asynccancel +ENTRY(__pthread_disable_asynccancel) + testl $TCB_CANCELTYPE_BITMASK, %edi + jnz 1f + + movl %fs:CANCELHANDLING, %eax +2: movl %eax, %r11d + andl $~TCB_CANCELTYPE_BITMASK, %r11d + lock + cmpxchgl %r11d, %fs:CANCELHANDLING + jnz 2b + + movl %r11d, %eax +3: andl $(TCB_CANCELING_BITMASK|TCB_CANCELED_BITMASK), %eax + cmpl $TCB_CANCELING_BITMASK, %eax + je 4f +1: ret + + /* Performance doesn't matter in this loop. We will + delay until the thread is canceled. And we will unlikely + enter the loop twice. */ +4: movq %fs:0, %rdi + movl $__NR_futex, %eax + xorq %r10, %r10 + addq $CANCELHANDLING, %rdi + LOAD_PRIVATE_FUTEX_WAIT (%esi) + syscall + movl %fs:CANCELHANDLING, %eax + jmp 3b +END(__pthread_disable_asynccancel) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/clone.S new file mode 100644 index 000000000..efbaee3d1 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/clone.S @@ -0,0 +1,3 @@ +#include <tcb-offsets.h> +#define RESET_PID +#include <libc/sysdeps/linux/x86_64/clone.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/compat-timer.h b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/compat-timer.h new file mode 100644 index 000000000..02485daa5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/compat-timer.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <signal.h> +#include <time.h> +#include <sys/types.h> + +#define OLD_TIMER_MAX 256 + +extern timer_t __compat_timer_list[OLD_TIMER_MAX] attribute_hidden; + + +extern int __timer_create_new (clockid_t clock_id, struct sigevent *evp, + timer_t *timerid); +extern int __timer_delete_new (timer_t timerid); +extern int __timer_getoverrun_new (timer_t timerid); +extern int __timer_gettime_new (timer_t timerid, struct itimerspec *value); +extern int __timer_settime_new (timer_t timerid, int flags, + const struct itimerspec *value, + struct itimerspec *ovalue); + + +extern int __timer_create_old (clockid_t clock_id, struct sigevent *evp, + int *timerid); +extern int __timer_delete_old (int timerid); +extern int __timer_getoverrun_old (int timerid); +extern int __timer_gettime_old (int timerid, struct itimerspec *value); +extern int __timer_settime_old (int timerid, int flags, + const struct itimerspec *value, + struct itimerspec *ovalue); diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/fork.c new file mode 100644 index 000000000..c828e158d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/fork.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 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 <sched.h> +#include <signal.h> +#include <sysdep.h> +#include <tls.h> + + +#define ARCH_FORK() \ + INLINE_SYSCALL (clone, 4, \ + CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0, \ + NULL, &THREAD_SELF->tid) + +#include "../fork.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S new file mode 100644 index 000000000..110058850 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S @@ -0,0 +1,22 @@ +/* Copyright (C) 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2009. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __pthread_enable_asynccancel __libc_enable_asynccancel +#define __pthread_disable_asynccancel __libc_disable_asynccancel +#include "cancellation.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S new file mode 100644 index 000000000..ce8ad27aa --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "lowlevellock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S new file mode 100644 index 000000000..ce4192b5d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S @@ -0,0 +1,22 @@ +/* Copyright (C) 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2009. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __pthread_enable_asynccancel __librt_enable_asynccancel +#define __pthread_disable_asynccancel __librt_disable_asynccancel +#include "cancellation.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S new file mode 100644 index 000000000..f87532359 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S @@ -0,0 +1,457 @@ +/* Copyright (C) 2002-2006, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include <bits/kernel-features.h> +#include <lowlevellock.h> +#include <tcb-offsets.h> + + .text + +#ifdef __ASSUME_PRIVATE_FUTEX +# define LOAD_PRIVATE_FUTEX_WAIT(reg) \ + movl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg +# define LOAD_PRIVATE_FUTEX_WAKE(reg) \ + movl $(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg +# define LOAD_FUTEX_WAIT(reg) \ + xorl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg +# define LOAD_FUTEX_WAIT_ABS(reg) \ + xorl $(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME), reg +# define LOAD_FUTEX_WAKE(reg) \ + xorl $(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg +#else +# if FUTEX_WAIT == 0 +# define LOAD_PRIVATE_FUTEX_WAIT(reg) \ + movl %fs:PRIVATE_FUTEX, reg +# else +# define LOAD_PRIVATE_FUTEX_WAIT(reg) \ + movl %fs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAIT, reg +# endif +# define LOAD_PRIVATE_FUTEX_WAKE(reg) \ + movl %fs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAKE, reg +# if FUTEX_WAIT == 0 +# define LOAD_FUTEX_WAIT(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %fs:PRIVATE_FUTEX, reg +# else +# define LOAD_FUTEX_WAIT(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %fs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAIT, reg +# endif +# define LOAD_FUTEX_WAIT_ABS(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %fs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME, reg +# define LOAD_FUTEX_WAKE(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %fs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAKE, reg +#endif + + +/* For the calculation see asm/vsyscall.h. */ +#define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000 + + + .globl __lll_lock_wait_private + .type __lll_lock_wait_private,@function + .hidden __lll_lock_wait_private + .align 16 +__lll_lock_wait_private: + cfi_startproc + pushq %r10 + cfi_adjust_cfa_offset(8) + pushq %rdx + cfi_adjust_cfa_offset(8) + cfi_offset(%r10, -16) + cfi_offset(%rdx, -24) + xorq %r10, %r10 /* No timeout. */ + movl $2, %edx + LOAD_PRIVATE_FUTEX_WAIT (%esi) + + cmpl %edx, %eax /* NB: %edx == 2 */ + jne 2f + +1: movl $SYS_futex, %eax + syscall + +2: movl %edx, %eax + xchgl %eax, (%rdi) /* NB: lock is implied */ + + testl %eax, %eax + jnz 1b + + popq %rdx + cfi_adjust_cfa_offset(-8) + cfi_restore(%rdx) + popq %r10 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r10) + retq + cfi_endproc + .size __lll_lock_wait_private,.-__lll_lock_wait_private + +#ifdef NOT_IN_libc + .globl __lll_lock_wait + .type __lll_lock_wait,@function + .hidden __lll_lock_wait + .align 16 +__lll_lock_wait: + cfi_startproc + pushq %r10 + cfi_adjust_cfa_offset(8) + pushq %rdx + cfi_adjust_cfa_offset(8) + cfi_offset(%r10, -16) + cfi_offset(%rdx, -24) + xorq %r10, %r10 /* No timeout. */ + movl $2, %edx + LOAD_FUTEX_WAIT (%esi) + + cmpl %edx, %eax /* NB: %edx == 2 */ + jne 2f + +1: movl $SYS_futex, %eax + syscall + +2: movl %edx, %eax + xchgl %eax, (%rdi) /* NB: lock is implied */ + + testl %eax, %eax + jnz 1b + + popq %rdx + cfi_adjust_cfa_offset(-8) + cfi_restore(%rdx) + popq %r10 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r10) + retq + cfi_endproc + .size __lll_lock_wait,.-__lll_lock_wait + + /* %rdi: futex + %rsi: flags + %rdx: timeout + %eax: futex value + */ + .globl __lll_timedlock_wait + .type __lll_timedlock_wait,@function + .hidden __lll_timedlock_wait + .align 16 +__lll_timedlock_wait: + cfi_startproc +# ifndef __ASSUME_FUTEX_CLOCK_REALTIME +# ifdef __PIC__ + cmpl $0, __have_futex_clock_realtime(%rip) +# else + cmpl $0, __have_futex_clock_realtime +# endif + je .Lreltmo +# endif + + pushq %r9 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r9, 0) + movq %rdx, %r10 + movl $0xffffffff, %r9d + LOAD_FUTEX_WAIT_ABS (%esi) + + movl $2, %edx + cmpl %edx, %eax + jne 2f + +1: movl $SYS_futex, %eax + movl $2, %edx + syscall + +2: xchgl %edx, (%rdi) /* NB: lock is implied */ + + testl %edx, %edx + jz 3f + + cmpl $-ETIMEDOUT, %eax + je 4f + cmpl $-EINVAL, %eax + jne 1b +4: movl %eax, %edx + negl %edx + +3: movl %edx, %eax + popq %r9 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r9) + retq + +# ifndef __ASSUME_FUTEX_CLOCK_REALTIME +.Lreltmo: + /* Check for a valid timeout value. */ + cmpq $1000000000, 8(%rdx) + jae 3f + + pushq %r8 + cfi_adjust_cfa_offset(8) + pushq %r9 + cfi_adjust_cfa_offset(8) + pushq %r12 + cfi_adjust_cfa_offset(8) + pushq %r13 + cfi_adjust_cfa_offset(8) + pushq %r14 + cfi_adjust_cfa_offset(8) + cfi_offset(%r8, -16) + cfi_offset(%r9, -24) + cfi_offset(%r12, -32) + cfi_offset(%r13, -40) + cfi_offset(%r14, -48) + pushq %rsi + cfi_adjust_cfa_offset(8) + + /* Stack frame for the timespec and timeval structs. */ + subq $24, %rsp + cfi_adjust_cfa_offset(24) + + movq %rdi, %r12 + movq %rdx, %r13 + + movl $2, %edx + xchgl %edx, (%r12) + + testl %edx, %edx + je 6f + +1: + /* Get current time. */ + movq %rsp, %rdi + xorl %esi, %esi + movq $VSYSCALL_ADDR_vgettimeofday, %rax + /* This is a regular function call, all caller-save registers + might be clobbered. */ + callq *%rax + + /* Compute relative timeout. */ + movq 8(%rsp), %rax + movl $1000, %edi + mul %rdi /* Milli seconds to nano seconds. */ + movq (%r13), %rdi + movq 8(%r13), %rsi + subq (%rsp), %rdi + subq %rax, %rsi + jns 4f + addq $1000000000, %rsi + decq %rdi +4: testq %rdi, %rdi + js 2f /* Time is already up. */ + + /* Store relative timeout. */ + movq %rdi, (%rsp) + movq %rsi, 8(%rsp) + + /* Futex call. */ + movl $2, %edx + movl $1, %eax + movq %rsp, %r10 + movl 24(%rsp), %esi + LOAD_FUTEX_WAIT (%esi) + movq %r12, %rdi + movl $SYS_futex, %eax + syscall + + /* NB: %edx == 2 */ + xchgl %edx, (%r12) + + testl %edx, %edx + je 6f + + cmpl $-ETIMEDOUT, %eax + jne 1b +2: movl $ETIMEDOUT, %edx + +6: addq $32, %rsp + cfi_adjust_cfa_offset(-32) + popq %r14 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r14) + popq %r13 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r13) + popq %r12 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r12) + popq %r9 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r9) + popq %r8 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r8) + movl %edx, %eax + retq + +3: movl $EINVAL, %eax + retq +# endif + cfi_endproc + .size __lll_timedlock_wait,.-__lll_timedlock_wait +#endif + + + .globl __lll_unlock_wake_private + .type __lll_unlock_wake_private,@function + .hidden __lll_unlock_wake_private + .align 16 +__lll_unlock_wake_private: + cfi_startproc + pushq %rsi + cfi_adjust_cfa_offset(8) + pushq %rdx + cfi_adjust_cfa_offset(8) + cfi_offset(%rsi, -16) + cfi_offset(%rdx, -24) + + movl $0, (%rdi) + LOAD_PRIVATE_FUTEX_WAKE (%esi) + movl $1, %edx /* Wake one thread. */ + movl $SYS_futex, %eax + syscall + + popq %rdx + cfi_adjust_cfa_offset(-8) + cfi_restore(%rdx) + popq %rsi + cfi_adjust_cfa_offset(-8) + cfi_restore(%rsi) + retq + cfi_endproc + .size __lll_unlock_wake_private,.-__lll_unlock_wake_private + +#ifdef NOT_IN_libc + .globl __lll_unlock_wake + .type __lll_unlock_wake,@function + .hidden __lll_unlock_wake + .align 16 +__lll_unlock_wake: + cfi_startproc + pushq %rsi + cfi_adjust_cfa_offset(8) + pushq %rdx + cfi_adjust_cfa_offset(8) + cfi_offset(%rsi, -16) + cfi_offset(%rdx, -24) + + movl $0, (%rdi) + LOAD_FUTEX_WAKE (%esi) + movl $1, %edx /* Wake one thread. */ + movl $SYS_futex, %eax + syscall + + popq %rdx + cfi_adjust_cfa_offset(-8) + cfi_restore(%rdx) + popq %rsi + cfi_adjust_cfa_offset(-8) + cfi_restore(%rsi) + retq + cfi_endproc + .size __lll_unlock_wake,.-__lll_unlock_wake + + .globl __lll_timedwait_tid + .type __lll_timedwait_tid,@function + .hidden __lll_timedwait_tid + .align 16 +__lll_timedwait_tid: + cfi_startproc + pushq %r12 + cfi_adjust_cfa_offset(8) + pushq %r13 + cfi_adjust_cfa_offset(8) + cfi_offset(%r12, -16) + cfi_offset(%r13, -24) + + movq %rdi, %r12 + movq %rsi, %r13 + + subq $16, %rsp + cfi_adjust_cfa_offset(16) + + /* Get current time. */ +2: movq %rsp, %rdi + xorl %esi, %esi + movq $VSYSCALL_ADDR_vgettimeofday, %rax + callq *%rax + + /* Compute relative timeout. */ + movq 8(%rsp), %rax + movl $1000, %edi + mul %rdi /* Milli seconds to nano seconds. */ + movq (%r13), %rdi + movq 8(%r13), %rsi + subq (%rsp), %rdi + subq %rax, %rsi + jns 5f + addq $1000000000, %rsi + decq %rdi +5: testq %rdi, %rdi + js 6f /* Time is already up. */ + + movq %rdi, (%rsp) /* Store relative timeout. */ + movq %rsi, 8(%rsp) + + movl (%r12), %edx + testl %edx, %edx + jz 4f + + movq %rsp, %r10 + /* XXX The kernel so far uses global futex for the wakeup at + all times. */ +#if FUTEX_WAIT == 0 + xorl %esi, %esi +#else + movl $FUTEX_WAIT, %esi +#endif + movq %r12, %rdi + movl $SYS_futex, %eax + syscall + + cmpl $0, (%rdi) + jne 1f +4: xorl %eax, %eax + +8: addq $16, %rsp + cfi_adjust_cfa_offset(-16) + popq %r13 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r13) + popq %r12 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r12) + retq + + cfi_adjust_cfa_offset(32) +1: cmpq $-ETIMEDOUT, %rax + jne 2b + +6: movl $ETIMEDOUT, %eax + jmp 8b + cfi_endproc + .size __lll_timedwait_tid,.-__lll_timedwait_tid +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h new file mode 100644 index 000000000..7c042fc80 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h @@ -0,0 +1,598 @@ +/* Copyright (C) 2002-2004, 2006-2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H 1 + +#ifndef __ASSEMBLER__ +# include <time.h> +# include <sys/param.h> +# include <bits/pthreadtypes.h> +# include <bits/kernel-features.h> +# include <tcb-offsets.h> + +# ifndef LOCK_INSTR +# ifdef UP +# define LOCK_INSTR /* nothing */ +# else +# define LOCK_INSTR "lock;" +# endif +# endif +#else +# ifndef LOCK +# ifdef UP +# define LOCK +# else +# define LOCK lock +# endif +# endif +#endif + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_CMP_REQUEUE 4 +#define FUTEX_WAKE_OP 5 +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 +#define FUTEX_WAIT_BITSET 9 +#define FUTEX_WAKE_BITSET 10 +#define FUTEX_WAIT_REQUEUE_PI 11 +#define FUTEX_CMP_REQUEUE_PI 12 +#define FUTEX_PRIVATE_FLAG 128 +#define FUTEX_CLOCK_REALTIME 256 + +#define FUTEX_BITSET_MATCH_ANY 0xffffffff + +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + +#ifndef __ASSEMBLER__ + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ({ unsigned int __fl = ((private) ^ FUTEX_PRIVATE_FLAG); \ + __asm__ ("andl %%fs:%P1, %0" : "+r" (__fl) \ + : "i" (offsetof (struct pthread, header.private_futex))); \ + __fl | (fl); })) +# endif +#endif + +/* Initializer for lock. */ +#define LLL_LOCK_INITIALIZER (0) +#define LLL_LOCK_INITIALIZER_LOCKED (1) +#define LLL_LOCK_INITIALIZER_WAITERS (2) + +/* Delay in spinlock loop. */ +#define BUSY_WAIT_NOP __asm__ ("rep; nop") + + +#define LLL_STUB_UNWIND_INFO_START \ + ".section .eh_frame,\"a\",@progbits\n" \ +"7:\t" ".long 9f-8f # Length of Common Information Entry\n" \ +"8:\t" ".long 0x0 # CIE Identifier Tag\n\t" \ + ".byte 0x1 # CIE Version\n\t" \ + ".ascii \"zR\\0\" # CIE Augmentation\n\t" \ + ".uleb128 0x1 # CIE Code Alignment Factor\n\t" \ + ".sleb128 -8 # CIE Data Alignment Factor\n\t" \ + ".byte 0x10 # CIE RA Column\n\t" \ + ".uleb128 0x1 # Augmentation size\n\t" \ + ".byte 0x1b # FDE Encoding (pcrel sdata4)\n\t" \ + ".byte 0x12 # DW_CFA_def_cfa_sf\n\t" \ + ".uleb128 0x7\n\t" \ + ".sleb128 16\n\t" \ + ".align 8\n" \ +"9:\t" ".long 23f-10f # FDE Length\n" \ +"10:\t" ".long 10b-7b # FDE CIE offset\n\t" \ + ".long 1b-. # FDE initial location\n\t" \ + ".long 6b-1b # FDE address range\n\t" \ + ".uleb128 0x0 # Augmentation size\n\t" \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x10\n\t" \ + ".uleb128 12f-11f\n" \ +"11:\t" ".byte 0x80 # DW_OP_breg16\n\t" \ + ".sleb128 4b-1b\n" +#define LLL_STUB_UNWIND_INFO_END \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x10\n\t" \ + ".uleb128 14f-13f\n" \ +"13:\t" ".byte 0x80 # DW_OP_breg16\n\t" \ + ".sleb128 4b-2b\n" \ +"14:\t" ".byte 0x40 + (3b-2b) # DW_CFA_advance_loc\n\t" \ + ".byte 0x0e # DW_CFA_def_cfa_offset\n\t" \ + ".uleb128 0\n\t" \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x10\n\t" \ + ".uleb128 16f-15f\n" \ +"15:\t" ".byte 0x80 # DW_OP_breg16\n\t" \ + ".sleb128 4b-3b\n" \ +"16:\t" ".byte 0x40 + (4b-3b-1) # DW_CFA_advance_loc\n\t" \ + ".byte 0x0e # DW_CFA_def_cfa_offset\n\t" \ + ".uleb128 128\n\t" \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x10\n\t" \ + ".uleb128 20f-17f\n" \ +"17:\t" ".byte 0x80 # DW_OP_breg16\n\t" \ + ".sleb128 19f-18f\n\t" \ + ".byte 0x0d # DW_OP_const4s\n" \ +"18:\t" ".4byte 4b-.\n\t" \ + ".byte 0x1c # DW_OP_minus\n\t" \ + ".byte 0x0d # DW_OP_const4s\n" \ +"19:\t" ".4byte 24f-.\n\t" \ + ".byte 0x22 # DW_OP_plus\n" \ +"20:\t" ".byte 0x40 + (5b-4b+1) # DW_CFA_advance_loc\n\t" \ + ".byte 0x13 # DW_CFA_def_cfa_offset_sf\n\t" \ + ".sleb128 16\n\t" \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x10\n\t" \ + ".uleb128 22f-21f\n" \ +"21:\t" ".byte 0x80 # DW_OP_breg16\n\t" \ + ".sleb128 4b-5b\n" \ +"22:\t" ".align 8\n" \ +"23:\t" ".previous\n" + +/* Unwind info for + 1: leaq ..., %rdi + 2: subq $128, %rsp + 3: callq ... + 4: addq $128, %rsp + 5: jmp 24f + 6: + snippet. */ +#define LLL_STUB_UNWIND_INFO_5 \ +LLL_STUB_UNWIND_INFO_START \ +"12:\t" ".byte 0x40 + (2b-1b) # DW_CFA_advance_loc\n\t" \ +LLL_STUB_UNWIND_INFO_END + +/* Unwind info for + 1: leaq ..., %rdi + 0: movq ..., %rdx + 2: subq $128, %rsp + 3: callq ... + 4: addq $128, %rsp + 5: jmp 24f + 6: + snippet. */ +#define LLL_STUB_UNWIND_INFO_6 \ +LLL_STUB_UNWIND_INFO_START \ +"12:\t" ".byte 0x40 + (0b-1b) # DW_CFA_advance_loc\n\t" \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x10\n\t" \ + ".uleb128 26f-25f\n" \ +"25:\t" ".byte 0x80 # DW_OP_breg16\n\t" \ + ".sleb128 4b-0b\n" \ +"26:\t" ".byte 0x40 + (2b-0b) # DW_CFA_advance_loc\n\t" \ +LLL_STUB_UNWIND_INFO_END + + +#define lll_futex_wait(futex, val, private) \ + lll_futex_timed_wait(futex, val, NULL, private) + + +#define lll_futex_timed_wait(futex, val, timeout, private) \ + ({ \ + register const struct timespec *__to __asm__ ("r10") = timeout; \ + int __status; \ + register __typeof (val) _val __asm__ ("edx") = (val); \ + __asm__ __volatile ("syscall" \ + : "=a" (__status) \ + : "0" (SYS_futex), "D" (futex), \ + "S" (__lll_private_flag (FUTEX_WAIT, private)), \ + "d" (_val), "r" (__to) \ + : "memory", "cc", "r11", "cx"); \ + __status; \ + }) + + +#define lll_futex_wake(futex, nr, private) \ + do { \ + int __ignore; \ + register __typeof (nr) _nr __asm__ ("edx") = (nr); \ + __asm__ __volatile ("syscall" \ + : "=a" (__ignore) \ + : "0" (SYS_futex), "D" (futex), \ + "S" (__lll_private_flag (FUTEX_WAKE, private)), \ + "d" (_nr) \ + : "memory", "cc", "r10", "r11", "cx"); \ + } while (0) + + +/* NB: in the lll_trylock macro we simply return the value in %eax + after the cmpxchg instruction. In case the operation succeded this + value is zero. In case the operation failed, the cmpxchg instruction + has loaded the current value of the memory work which is guaranteed + to be nonzero. */ +#if defined NOT_IN_libc || defined UP +# define __lll_trylock_asm LOCK_INSTR "cmpxchgl %2, %1" +#else +# define __lll_trylock_asm "cmpl $0, __libc_multiple_threads(%%rip)\n\t" \ + "je 0f\n\t" \ + "lock; cmpxchgl %2, %1\n\t" \ + "jmp 1f\n\t" \ + "0:\tcmpxchgl %2, %1\n\t" \ + "1:" +#endif + +#define lll_trylock(futex) \ + ({ int ret; \ + __asm__ __volatile (__lll_trylock_asm \ + : "=a" (ret), "=m" (futex) \ + : "r" (LLL_LOCK_INITIALIZER_LOCKED), "m" (futex), \ + "0" (LLL_LOCK_INITIALIZER) \ + : "memory"); \ + ret; }) + +#define lll_robust_trylock(futex, id) \ + ({ int ret; \ + __asm__ __volatile (LOCK_INSTR "cmpxchgl %2, %1" \ + : "=a" (ret), "=m" (futex) \ + : "r" (id), "m" (futex), "0" (LLL_LOCK_INITIALIZER) \ + : "memory"); \ + ret; }) + +#define lll_cond_trylock(futex) \ + ({ int ret; \ + __asm__ __volatile (LOCK_INSTR "cmpxchgl %2, %1" \ + : "=a" (ret), "=m" (futex) \ + : "r" (LLL_LOCK_INITIALIZER_WAITERS), \ + "m" (futex), "0" (LLL_LOCK_INITIALIZER) \ + : "memory"); \ + ret; }) + +#if defined NOT_IN_libc || defined UP +# define __lll_lock_asm_start LOCK_INSTR "cmpxchgl %4, %2\n\t" \ + "jnz 1f\n\t" +#else +# define __lll_lock_asm_start "cmpl $0, __libc_multiple_threads(%%rip)\n\t" \ + "je 0f\n\t" \ + "lock; cmpxchgl %4, %2\n\t" \ + "jnz 1f\n\t" \ + "jmp 24f\n" \ + "0:\tcmpxchgl %4, %2\n\t" \ + "jnz 1f\n\t" +#endif + +#define lll_lock(futex, private) \ + (void) \ + ({ int ignore1, ignore2, ignore3; \ + if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \ + __asm__ __volatile (__lll_lock_asm_start \ + ".subsection 1\n\t" \ + ".type _L_lock_%=, @function\n" \ + "_L_lock_%=:\n" \ + "1:\tleaq %2, %%rdi\n" \ + "2:\tsubq $128, %%rsp\n" \ + "3:\tcallq __lll_lock_wait_private\n" \ + "4:\taddq $128, %%rsp\n" \ + "5:\tjmp 24f\n" \ + "6:\t.size _L_lock_%=, 6b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_5 \ + "24:" \ + : "=S" (ignore1), "=&D" (ignore2), "=m" (futex), \ + "=a" (ignore3) \ + : "0" (1), "m" (futex), "3" (0) \ + : "cx", "r11", "cc", "memory"); \ + else \ + __asm__ __volatile (__lll_lock_asm_start \ + ".subsection 1\n\t" \ + ".type _L_lock_%=, @function\n" \ + "_L_lock_%=:\n" \ + "1:\tleaq %2, %%rdi\n" \ + "2:\tsubq $128, %%rsp\n" \ + "3:\tcallq __lll_lock_wait\n" \ + "4:\taddq $128, %%rsp\n" \ + "5:\tjmp 24f\n" \ + "6:\t.size _L_lock_%=, 6b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_5 \ + "24:" \ + : "=S" (ignore1), "=D" (ignore2), "=m" (futex), \ + "=a" (ignore3) \ + : "1" (1), "m" (futex), "3" (0), "0" (private) \ + : "cx", "r11", "cc", "memory"); \ + }) \ + +#define lll_robust_lock(futex, id, private) \ + ({ int result, ignore1, ignore2; \ + __asm__ __volatile (LOCK_INSTR "cmpxchgl %4, %2\n\t" \ + "jnz 1f\n\t" \ + ".subsection 1\n\t" \ + ".type _L_robust_lock_%=, @function\n" \ + "_L_robust_lock_%=:\n" \ + "1:\tleaq %2, %%rdi\n" \ + "2:\tsubq $128, %%rsp\n" \ + "3:\tcallq __lll_robust_lock_wait\n" \ + "4:\taddq $128, %%rsp\n" \ + "5:\tjmp 24f\n" \ + "6:\t.size _L_robust_lock_%=, 6b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_5 \ + "24:" \ + : "=S" (ignore1), "=D" (ignore2), "=m" (futex), \ + "=a" (result) \ + : "1" (id), "m" (futex), "3" (0), "0" (private) \ + : "cx", "r11", "cc", "memory"); \ + result; }) + +#define lll_cond_lock(futex, private) \ + (void) \ + ({ int ignore1, ignore2, ignore3; \ + __asm__ __volatile (LOCK_INSTR "cmpxchgl %4, %2\n\t" \ + "jnz 1f\n\t" \ + ".subsection 1\n\t" \ + ".type _L_cond_lock_%=, @function\n" \ + "_L_cond_lock_%=:\n" \ + "1:\tleaq %2, %%rdi\n" \ + "2:\tsubq $128, %%rsp\n" \ + "3:\tcallq __lll_lock_wait\n" \ + "4:\taddq $128, %%rsp\n" \ + "5:\tjmp 24f\n" \ + "6:\t.size _L_cond_lock_%=, 6b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_5 \ + "24:" \ + : "=S" (ignore1), "=D" (ignore2), "=m" (futex), \ + "=a" (ignore3) \ + : "1" (2), "m" (futex), "3" (0), "0" (private) \ + : "cx", "r11", "cc", "memory"); \ + }) + +#define lll_robust_cond_lock(futex, id, private) \ + ({ int result, ignore1, ignore2; \ + __asm__ __volatile (LOCK_INSTR "cmpxchgl %4, %2\n\t" \ + "jnz 1f\n\t" \ + ".subsection 1\n\t" \ + ".type _L_robust_cond_lock_%=, @function\n" \ + "_L_robust_cond_lock_%=:\n" \ + "1:\tleaq %2, %%rdi\n" \ + "2:\tsubq $128, %%rsp\n" \ + "3:\tcallq __lll_robust_lock_wait\n" \ + "4:\taddq $128, %%rsp\n" \ + "5:\tjmp 24f\n" \ + "6:\t.size _L_robust_cond_lock_%=, 6b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_5 \ + "24:" \ + : "=S" (ignore1), "=D" (ignore2), "=m" (futex), \ + "=a" (result) \ + : "1" (id | FUTEX_WAITERS), "m" (futex), "3" (0), \ + "0" (private) \ + : "cx", "r11", "cc", "memory"); \ + result; }) + +#define lll_timedlock(futex, timeout, private) \ + ({ int result, ignore1, ignore2, ignore3; \ + __asm__ __volatile (LOCK_INSTR "cmpxchgl %1, %4\n\t" \ + "jnz 1f\n\t" \ + ".subsection 1\n\t" \ + ".type _L_timedlock_%=, @function\n" \ + "_L_timedlock_%=:\n" \ + "1:\tleaq %4, %%rdi\n" \ + "0:\tmovq %8, %%rdx\n" \ + "2:\tsubq $128, %%rsp\n" \ + "3:\tcallq __lll_timedlock_wait\n" \ + "4:\taddq $128, %%rsp\n" \ + "5:\tjmp 24f\n" \ + "6:\t.size _L_timedlock_%=, 6b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_6 \ + "24:" \ + : "=a" (result), "=D" (ignore1), "=S" (ignore2), \ + "=&d" (ignore3), "=m" (futex) \ + : "0" (0), "1" (1), "m" (futex), "m" (timeout), \ + "2" (private) \ + : "memory", "cx", "cc", "r10", "r11"); \ + result; }) + +#define lll_robust_timedlock(futex, timeout, id, private) \ + ({ int result, ignore1, ignore2, ignore3; \ + __asm__ __volatile (LOCK_INSTR "cmpxchgl %1, %4\n\t" \ + "jnz 1f\n\t" \ + ".subsection 1\n\t" \ + ".type _L_robust_timedlock_%=, @function\n" \ + "_L_robust_timedlock_%=:\n" \ + "1:\tleaq %4, %%rdi\n" \ + "0:\tmovq %8, %%rdx\n" \ + "2:\tsubq $128, %%rsp\n" \ + "3:\tcallq __lll_robust_timedlock_wait\n" \ + "4:\taddq $128, %%rsp\n" \ + "5:\tjmp 24f\n" \ + "6:\t.size _L_robust_timedlock_%=, 6b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_6 \ + "24:" \ + : "=a" (result), "=D" (ignore1), "=S" (ignore2), \ + "=&d" (ignore3), "=m" (futex) \ + : "0" (0), "1" (id), "m" (futex), "m" (timeout), \ + "2" (private) \ + : "memory", "cx", "cc", "r10", "r11"); \ + result; }) + +#if defined NOT_IN_libc || defined UP +# define __lll_unlock_asm_start LOCK_INSTR "decl %0\n\t" \ + "jne 1f\n\t" +#else +# define __lll_unlock_asm_start "cmpl $0, __libc_multiple_threads(%%rip)\n\t" \ + "je 0f\n\t" \ + "lock; decl %0\n\t" \ + "jne 1f\n\t" \ + "jmp 24f\n\t" \ + "0:\tdecl %0\n\t" \ + "jne 1f\n\t" +#endif + +#define lll_unlock(futex, private) \ + (void) \ + ({ int ignore; \ + if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \ + __asm__ __volatile (__lll_unlock_asm_start \ + ".subsection 1\n\t" \ + ".type _L_unlock_%=, @function\n" \ + "_L_unlock_%=:\n" \ + "1:\tleaq %0, %%rdi\n" \ + "2:\tsubq $128, %%rsp\n" \ + "3:\tcallq __lll_unlock_wake_private\n" \ + "4:\taddq $128, %%rsp\n" \ + "5:\tjmp 24f\n" \ + "6:\t.size _L_unlock_%=, 6b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_5 \ + "24:" \ + : "=m" (futex), "=&D" (ignore) \ + : "m" (futex) \ + : "ax", "cx", "r11", "cc", "memory"); \ + else \ + __asm__ __volatile (__lll_unlock_asm_start \ + ".subsection 1\n\t" \ + ".type _L_unlock_%=, @function\n" \ + "_L_unlock_%=:\n" \ + "1:\tleaq %0, %%rdi\n" \ + "2:\tsubq $128, %%rsp\n" \ + "3:\tcallq __lll_unlock_wake\n" \ + "4:\taddq $128, %%rsp\n" \ + "5:\tjmp 24f\n" \ + "6:\t.size _L_unlock_%=, 6b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_5 \ + "24:" \ + : "=m" (futex), "=&D" (ignore) \ + : "m" (futex), "S" (private) \ + : "ax", "cx", "r11", "cc", "memory"); \ + }) + +#define lll_robust_unlock(futex, private) \ + do \ + { \ + int ignore; \ + __asm__ __volatile (LOCK_INSTR "andl %2, %0\n\t" \ + "jne 1f\n\t" \ + ".subsection 1\n\t" \ + ".type _L_robust_unlock_%=, @function\n" \ + "_L_robust_unlock_%=:\n" \ + "1:\tleaq %0, %%rdi\n" \ + "2:\tsubq $128, %%rsp\n" \ + "3:\tcallq __lll_unlock_wake\n" \ + "4:\taddq $128, %%rsp\n" \ + "5:\tjmp 24f\n" \ + "6:\t.size _L_robust_unlock_%=, 6b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_5 \ + "24:" \ + : "=m" (futex), "=&D" (ignore) \ + : "i" (FUTEX_WAITERS), "m" (futex), \ + "S" (private) \ + : "ax", "cx", "r11", "cc", "memory"); \ + } \ + while (0) + +#define lll_robust_dead(futex, private) \ + do \ + { \ + int ignore; \ + __asm__ __volatile (LOCK_INSTR "orl %3, (%2)\n\t" \ + "syscall" \ + : "=m" (futex), "=a" (ignore) \ + : "D" (&(futex)), "i" (FUTEX_OWNER_DIED), \ + "S" (__lll_private_flag (FUTEX_WAKE, private)), \ + "1" (__NR_futex), "d" (1) \ + : "cx", "r11", "cc", "memory"); \ + } \ + while (0) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(ftx, nr_wake, nr_move, mutex, val, private) \ + ({ 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" (__lll_private_flag (FUTEX_CMP_REQUEUE, \ + private)), "d" (nr_wake), \ + "r" (__nr_move), "r" (__mutex), "r" (__val) \ + : "cx", "r11", "cc", "memory"); \ + __res < 0; }) + +#define lll_islocked(futex) \ + (futex != LLL_LOCK_INITIALIZER) + + +/* The kernel notifies a process with uses CLONE_CLEARTID via futex + wakeup when the clone terminates. The memory location contains the + thread ID while the clone is running and is reset to zero + afterwards. + + The macro parameter must not have any side effect. */ +#define lll_wait_tid(tid) \ + do { \ + int __ignore; \ + register __typeof (tid) _tid __asm__ ("edx") = (tid); \ + if (_tid != 0) \ + __asm__ __volatile ("xorq %%r10, %%r10\n\t" \ + "1:\tmovq %2, %%rax\n\t" \ + "syscall\n\t" \ + "cmpl $0, (%%rdi)\n\t" \ + "jne 1b" \ + : "=&a" (__ignore) \ + : "S" (FUTEX_WAIT), "i" (SYS_futex), "D" (&tid), \ + "d" (_tid) \ + : "memory", "cc", "r10", "r11", "cx"); \ + } while (0) + +extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime) + attribute_hidden; +#define lll_timedwait_tid(tid, abstime) \ + ({ \ + int __result = 0; \ + if (tid != 0) \ + { \ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) \ + __result = EINVAL; \ + else \ + __result = __lll_timedwait_tid (&tid, abstime); \ + } \ + __result; }) + +#endif /* !__ASSEMBLER__ */ + +#endif /* lowlevellock.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S new file mode 100644 index 000000000..2eb8e29fa --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S @@ -0,0 +1,306 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2009 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include <lowlevellock.h> +#include <lowlevelrobustlock.h> +#include <bits/kernel-features.h> + + .text + +#define FUTEX_WAITERS 0x80000000 +#define FUTEX_OWNER_DIED 0x40000000 + +#ifdef __ASSUME_PRIVATE_FUTEX +# define LOAD_FUTEX_WAIT(reg) \ + xorl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg +# define LOAD_FUTEX_WAIT_ABS(reg) \ + xorl $(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME), reg +#else +# if FUTEX_WAIT == 0 +# define LOAD_FUTEX_WAIT(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %fs:PRIVATE_FUTEX, reg +# else +# define LOAD_FUTEX_WAIT(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %fs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAIT, reg +# endif +# define LOAD_FUTEX_WAIT_ABS(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %fs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME, reg +#endif + +/* For the calculation see asm/vsyscall.h. */ +#define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000 + + + .globl __lll_robust_lock_wait + .type __lll_robust_lock_wait,@function + .hidden __lll_robust_lock_wait + .align 16 +__lll_robust_lock_wait: + cfi_startproc + pushq %r10 + cfi_adjust_cfa_offset(8) + pushq %rdx + cfi_adjust_cfa_offset(8) + cfi_offset(%r10, -16) + cfi_offset(%rdx, -24) + + xorq %r10, %r10 /* No timeout. */ + LOAD_FUTEX_WAIT (%esi) + +4: movl %eax, %edx + orl $FUTEX_WAITERS, %edx + + testl $FUTEX_OWNER_DIED, %eax + jnz 3f + + cmpl %edx, %eax + je 1f + + LOCK + cmpxchgl %edx, (%rdi) + jnz 2f + +1: movl $SYS_futex, %eax + syscall + + movl (%rdi), %eax + +2: testl %eax, %eax + jne 4b + + movl %fs:TID, %edx + orl $FUTEX_WAITERS, %edx + LOCK + cmpxchgl %edx, (%rdi) + jnz 4b + /* NB: %rax == 0 */ + +3: popq %rdx + cfi_adjust_cfa_offset(-8) + cfi_restore(%rdx) + popq %r10 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r10) + retq + cfi_endproc + .size __lll_robust_lock_wait,.-__lll_robust_lock_wait + + + .globl __lll_robust_timedlock_wait + .type __lll_robust_timedlock_wait,@function + .hidden __lll_robust_timedlock_wait + .align 16 +__lll_robust_timedlock_wait: + cfi_startproc +# ifndef __ASSUME_FUTEX_CLOCK_REALTIME +# ifdef __PIC__ + cmpl $0, __have_futex_clock_realtime(%rip) +# else + cmpl $0, __have_futex_clock_realtime +# endif + je .Lreltmo +# endif + + pushq %r9 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r9, 0) + movq %rdx, %r10 + movl $0xffffffff, %r9d + LOAD_FUTEX_WAIT_ABS (%esi) + +1: testl $FUTEX_OWNER_DIED, %eax + jnz 3f + + movl %eax, %edx + orl $FUTEX_WAITERS, %edx + + cmpl %eax, %edx + je 5f + + LOCK + cmpxchgl %edx, (%rdi) + movq $0, %rcx /* Must use mov to avoid changing cc. */ + jnz 6f + +5: movl $SYS_futex, %eax + syscall + movl %eax, %ecx + + movl (%rdi), %eax + +6: testl %eax, %eax + jne 2f + + movl %fs:TID, %edx + orl $FUTEX_WAITERS, %edx + LOCK + cmpxchgl %edx, (%rdi) + jnz 2f + +3: popq %r9 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r9) + retq + + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r9, 0) + /* Check whether the time expired. */ +2: cmpl $-ETIMEDOUT, %ecx + je 4f + cmpl $-EINVAL, %ecx + jne 1b + +4: movl %ecx, %eax + negl %eax + jmp 3b + cfi_adjust_cfa_offset(-8) + cfi_restore(%r9) + + +# ifndef __ASSUME_FUTEX_CLOCK_REALTIME +.Lreltmo: + /* Check for a valid timeout value. */ + cmpq $1000000000, 8(%rdx) + jae 3f + + pushq %r8 + cfi_adjust_cfa_offset(8) + pushq %r9 + cfi_adjust_cfa_offset(8) + pushq %r12 + cfi_adjust_cfa_offset(8) + pushq %r13 + cfi_adjust_cfa_offset(8) + cfi_offset(%r8, -16) + cfi_offset(%r9, -24) + cfi_offset(%r12, -32) + cfi_offset(%r13, -40) + pushq %rsi + cfi_adjust_cfa_offset(8) + + /* Stack frame for the timespec and timeval structs. */ + subq $32, %rsp + cfi_adjust_cfa_offset(32) + + movq %rdi, %r12 + movq %rdx, %r13 + +1: movq %rax, 16(%rsp) + + /* Get current time. */ + movq %rsp, %rdi + xorl %esi, %esi + movq $VSYSCALL_ADDR_vgettimeofday, %rax + /* This is a regular function call, all caller-save registers + might be clobbered. */ + callq *%rax + + /* Compute relative timeout. */ + movq 8(%rsp), %rax + movl $1000, %edi + mul %rdi /* Milli seconds to nano seconds. */ + movq (%r13), %rdi + movq 8(%r13), %rsi + subq (%rsp), %rdi + subq %rax, %rsi + jns 4f + addq $1000000000, %rsi + decq %rdi +4: testq %rdi, %rdi + js 8f /* Time is already up. */ + + /* Futex call. */ + movq %rdi, (%rsp) /* Store relative timeout. */ + movq %rsi, 8(%rsp) + + movq 16(%rsp), %rdx + movl %edx, %eax + orl $FUTEX_WAITERS, %edx + + testl $FUTEX_OWNER_DIED, %eax + jnz 6f + + cmpl %eax, %edx + je 2f + + LOCK + cmpxchgl %edx, (%r12) + movq $0, %rcx /* Must use mov to avoid changing cc. */ + jnz 5f + +2: movq %rsp, %r10 + movl 32(%rsp), %esi + LOAD_FUTEX_WAIT (%esi) + movq %r12, %rdi + movl $SYS_futex, %eax + syscall + movq %rax, %rcx + + movl (%r12), %eax + +5: testl %eax, %eax + jne 7f + + movl %fs:TID, %edx + orl $FUTEX_WAITERS, %edx + LOCK + cmpxchgl %edx, (%r12) + jnz 7f + +6: addq $40, %rsp + cfi_adjust_cfa_offset(-40) + popq %r13 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r13) + popq %r12 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r12) + popq %r9 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r9) + popq %r8 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r8) + retq + +3: movl $EINVAL, %eax + retq + + cfi_adjust_cfa_offset(72) + cfi_offset(%r8, -16) + cfi_offset(%r9, -24) + cfi_offset(%r12, -32) + cfi_offset(%r13, -40) + /* Check whether the time expired. */ +7: cmpl $-ETIMEDOUT, %ecx + jne 1b + +8: movl $ETIMEDOUT, %eax + jmp 6b +#endif + cfi_endproc + .size __lll_robust_timedlock_wait,.-__lll_robust_timedlock_wait diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pt-__syscall_error.c b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pt-__syscall_error.c new file mode 100644 index 000000000..2ab81490c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pt-__syscall_error.c @@ -0,0 +1 @@ +#include <../../../../../../../libc/sysdeps/linux/x86_64/__syscall_error.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pt-vfork.S new file mode 100644 index 000000000..df4949615 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pt-vfork.S @@ -0,0 +1,33 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <tcb-offsets.h> + +#define SAVE_PID \ + movl %fs:PID, %esi; \ + movl %esi, %edx; \ + negl %edx; \ + movl %edx, %fs:PID + +#define RESTORE_PID \ + testq %rax, %rax; \ + je 1f; \ + movl %esi, %fs:PID; \ +1: + +#include <../../../../../../../libc/sysdeps/linux/x86_64/vfork.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S new file mode 100644 index 000000000..15ad534fa --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S @@ -0,0 +1,161 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelbarrier.h> + + + .text + + .globl pthread_barrier_wait + .type pthread_barrier_wait,@function + .align 16 +pthread_barrier_wait: + /* Get the mutex. */ + xorl %eax, %eax + movl $1, %esi + LOCK + cmpxchgl %esi, MUTEX(%rdi) + jnz 1f + + /* One less waiter. If this was the last one needed wake + everybody. */ +2: decl LEFT(%rdi) + je 3f + + /* There are more threads to come. */ +#if CURR_EVENT == 0 + movl (%rdi), %edx +#else + movl CURR_EVENT(%rdi), %edx +#endif + + /* Release the mutex. */ + LOCK + decl MUTEX(%rdi) + jne 6f + + /* Wait for the remaining threads. The call will return immediately + if the CURR_EVENT memory has meanwhile been changed. */ +7: +#if FUTEX_WAIT == 0 + movl PRIVATE(%rdi), %esi +#else + movl $FUTEX_WAIT, %esi + orl PRIVATE(%rdi), %esi +#endif + xorq %r10, %r10 +8: movl $SYS_futex, %eax + syscall + + /* Don't return on spurious wakeups. The syscall does not change + any register except %eax so there is no need to reload any of + them. */ +#if CURR_EVENT == 0 + cmpl %edx, (%rdi) +#else + cmpl %edx, CURR_EVENT(%rdi) +#endif + je 8b + + /* Increment LEFT. If this brings the count back to the + initial count unlock the object. */ + movl $1, %edx + movl INIT_COUNT(%rdi), %eax + LOCK + xaddl %edx, LEFT(%rdi) + subl $1, %eax + cmpl %eax, %edx + jne,pt 10f + + /* Release the mutex. We cannot release the lock before + waking the waiting threads since otherwise a new thread might + arrive and gets waken up, too. */ + LOCK + decl MUTEX(%rdi) + jne 9f + +10: xorl %eax, %eax /* != PTHREAD_BARRIER_SERIAL_THREAD */ + + retq + + /* The necessary number of threads arrived. */ +3: +#if CURR_EVENT == 0 + incl (%rdi) +#else + incl CURR_EVENT(%rdi) +#endif + + /* Wake up all waiters. The count is a signed number in the kernel + so 0x7fffffff is the highest value. */ + movl $0x7fffffff, %edx + movl $FUTEX_WAKE, %esi + orl PRIVATE(%rdi), %esi + movl $SYS_futex, %eax + syscall + + /* Increment LEFT. If this brings the count back to the + initial count unlock the object. */ + movl $1, %edx + movl INIT_COUNT(%rdi), %eax + LOCK + xaddl %edx, LEFT(%rdi) + subl $1, %eax + cmpl %eax, %edx + jne,pt 5f + + /* Release the mutex. We cannot release the lock before + waking the waiting threads since otherwise a new thread might + arrive and gets waken up, too. */ + LOCK + decl MUTEX(%rdi) + jne 4f + +5: orl $-1, %eax /* == PTHREAD_BARRIER_SERIAL_THREAD */ + + retq + +1: movl PRIVATE(%rdi), %esi + addq $MUTEX, %rdi + xorl $LLL_SHARED, %esi + callq __lll_lock_wait + subq $MUTEX, %rdi + jmp 2b + +4: movl PRIVATE(%rdi), %esi + addq $MUTEX, %rdi + xorl $LLL_SHARED, %esi + callq __lll_unlock_wake + jmp 5b + +6: movl PRIVATE(%rdi), %esi + addq $MUTEX, %rdi + xorl $LLL_SHARED, %esi + callq __lll_unlock_wake + subq $MUTEX, %rdi + jmp 7b + +9: movl PRIVATE(%rdi), %esi + addq $MUTEX, %rdi + xorl $LLL_SHARED, %esi + callq __lll_unlock_wake + jmp 10b + .size pthread_barrier_wait,.-pthread_barrier_wait diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S new file mode 100644 index 000000000..523bfdbdf --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S @@ -0,0 +1,178 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2009 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelcond.h> +#include <bits/kernel-features.h> +#include <pthread-pi-defines.h> +#include <pthread-errnos.h> + + + .text + + /* int pthread_cond_broadcast (pthread_cond_t *cond) */ + .globl __pthread_cond_broadcast + .type __pthread_cond_broadcast, @function + .hidden __pthread_cond_broadcast + .align 16 +__pthread_cond_broadcast: + + /* Get internal lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, cond_lock(%rdi) +#endif + jnz 1f + +2: addq $cond_futex, %rdi + movq total_seq-cond_futex(%rdi), %r9 + cmpq wakeup_seq-cond_futex(%rdi), %r9 + jna 4f + + /* Cause all currently waiting threads to recognize they are + woken up. */ + movq %r9, wakeup_seq-cond_futex(%rdi) + movq %r9, woken_seq-cond_futex(%rdi) + addq %r9, %r9 + movl %r9d, (%rdi) + incl broadcast_seq-cond_futex(%rdi) + + /* Get the address of the mutex used. */ + movq dep_mutex-cond_futex(%rdi), %r8 + + /* Unlock. */ + LOCK + decl cond_lock-cond_futex(%rdi) + jne 7f + +8: cmpq $-1, %r8 + je 9f + + /* Do not use requeue for pshared condvars. */ + testl $PS_BIT, MUTEX_KIND(%r8) + jne 9f + + /* Requeue to a PI mutex if the PI bit is set. */ + movl MUTEX_KIND(%r8), %eax + andl $(ROBUST_BIT|PI_BIT), %eax + cmpl $PI_BIT, %eax + je 81f + + /* Wake up all threads. */ +#ifdef __ASSUME_PRIVATE_FUTEX + movl $(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), %esi +#else + movl %fs:PRIVATE_FUTEX, %esi + orl $FUTEX_CMP_REQUEUE, %esi +#endif + movl $SYS_futex, %eax + movl $1, %edx + movl $0x7fffffff, %r10d + syscall + + /* For any kind of error, which mainly is EAGAIN, we try again + with WAKE. The general test also covers running on old + kernels. */ + cmpq $-4095, %rax + jae 9f + +10: xorl %eax, %eax + retq + + /* Wake up all threads. */ +81: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi + movl $SYS_futex, %eax + movl $1, %edx + movl $0x7fffffff, %r10d + syscall + + /* For any kind of error, which mainly is EAGAIN, we try again + with WAKE. The general test also covers running on old + kernels. */ + cmpq $-4095, %rax + jb 10b + jmp 9f + + .align 16 + /* Unlock. */ +4: LOCK + decl cond_lock-cond_futex(%rdi) + jne 5f + +6: xorl %eax, %eax + retq + + /* Initial locking failed. */ +1: +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_lock_wait +#if cond_lock != 0 + subq $cond_lock, %rdi +#endif + jmp 2b + + /* Unlock in loop requires wakeup. */ +5: addq $cond_lock-cond_futex, %rdi + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_unlock_wake + jmp 6b + + /* Unlock in loop requires wakeup. */ +7: addq $cond_lock-cond_futex, %rdi + cmpq $-1, %r8 + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_unlock_wake + subq $cond_lock-cond_futex, %rdi + jmp 8b + +9: /* The futex requeue functionality is not available. */ + cmpq $-1, %r8 + movl $0x7fffffff, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE, %eax + movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi + cmove %eax, %esi +#else + movl $0, %eax + movl %fs:PRIVATE_FUTEX, %esi + cmove %eax, %esi + orl $FUTEX_WAKE, %esi +#endif + movl $SYS_futex, %eax + syscall + jmp 10b + .size __pthread_cond_broadcast, .-__pthread_cond_broadcast +weak_alias(__pthread_cond_broadcast, pthread_cond_broadcast) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S new file mode 100644 index 000000000..cb1eb57c5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S @@ -0,0 +1,161 @@ +/* Copyright (C) 2002-2005, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelcond.h> +#include <pthread-pi-defines.h> +#include <bits/kernel-features.h> +#include <pthread-errnos.h> + + + .text + + /* int pthread_cond_signal (pthread_cond_t *cond) */ + .globl __pthread_cond_signal + .type __pthread_cond_signal, @function + .hidden __pthread_cond_signal + .align 16 +__pthread_cond_signal: + + /* Get internal lock. */ + movq %rdi, %r8 + movl $1, %esi + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, cond_lock(%rdi) +#endif + jnz 1f + +2: addq $cond_futex, %rdi + movq total_seq(%r8), %rcx + cmpq wakeup_seq(%r8), %rcx + jbe 4f + + /* Bump the wakeup number. */ + addq $1, wakeup_seq(%r8) + addl $1, (%rdi) + + /* Wake up one thread. */ + cmpq $-1, dep_mutex(%r8) + movl $FUTEX_WAKE_OP, %esi + movl $1, %edx + movl $SYS_futex, %eax + je 8f + + /* Get the address of the mutex used. */ + movq dep_mutex(%r8), %rcx + movl MUTEX_KIND(%rcx), %r11d + andl $(ROBUST_BIT|PI_BIT), %r11d + cmpl $PI_BIT, %r11d + je 9f + +#ifdef __ASSUME_PRIVATE_FUTEX + movl $(FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG), %esi +#else + orl %fs:PRIVATE_FUTEX, %esi +#endif + +8: movl $1, %r10d +#if cond_lock != 0 + addq $cond_lock, %r8 +#endif + movl $FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, %r9d + syscall +#if cond_lock != 0 + subq $cond_lock, %r8 +#endif + /* For any kind of error, we try again with WAKE. + The general test also covers running on old kernels. */ + cmpq $-4095, %rax + jae 7f + + xorl %eax, %eax + retq + + /* Wake up one thread and requeue none in the PI Mutex case. */ +9: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi + movq %rcx, %r8 + xorq %r10, %r10 + movl (%rdi), %r9d // XXX Can this be right? + syscall + + leaq -cond_futex(%rdi), %r8 + + /* For any kind of error, we try again with WAKE. + The general test also covers running on old kernels. */ + cmpq $-4095, %rax + jb 4f + +7: +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %esi +#else + andl %fs:PRIVATE_FUTEX, %esi +#endif + orl $FUTEX_WAKE, %esi + movl $SYS_futex, %eax + /* %rdx should be 1 already from $FUTEX_WAKE_OP syscall. + movl $1, %edx */ + syscall + + /* Unlock. */ +4: LOCK +#if cond_lock == 0 + decl (%r8) +#else + decl cond_lock(%r8) +#endif + jne 5f + +6: xorl %eax, %eax + retq + + /* Initial locking failed. */ +1: +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_lock_wait +#if cond_lock != 0 + subq $cond_lock, %rdi +#endif + jmp 2b + + /* Unlock in loop requires wakeup. */ +5: + movq %r8, %rdi +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_unlock_wake + jmp 6b + .size __pthread_cond_signal, .-__pthread_cond_signal +weak_alias(__pthread_cond_signal, pthread_cond_signal) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S new file mode 100644 index 000000000..7365b5c09 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S @@ -0,0 +1,804 @@ +/* Copyright (C) 2002-2005, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelcond.h> +#include <pthread-pi-defines.h> +#include <pthread-errnos.h> +#include <bits/kernel-features.h> +#include <tcb-offsets.h> + +/* For the calculation see asm/vsyscall.h. */ +#define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000 + + + .text + + +/* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime) */ + .globl __pthread_cond_timedwait + .type __pthread_cond_timedwait, @function + .hidden __pthread_cond_timedwait + .align 16 +__pthread_cond_timedwait: +.LSTARTCODE: + cfi_startproc + + pushq %r12 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r12, 0) + pushq %r13 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r13, 0) + pushq %r14 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r14, 0) + pushq %r15 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r15, 0) +#ifdef __ASSUME_FUTEX_CLOCK_REALTIME +# define FRAME_SIZE 32 +#else +# define FRAME_SIZE 48 +#endif + subq $FRAME_SIZE, %rsp + cfi_adjust_cfa_offset(FRAME_SIZE) + cfi_remember_state + + cmpq $1000000000, 8(%rdx) + movl $EINVAL, %eax + jae 48f + + /* Stack frame: + + rsp + 48 + +--------------------------+ + rsp + 32 | timeout value | + +--------------------------+ + rsp + 24 | old wake_seq value | + +--------------------------+ + rsp + 16 | mutex pointer | + +--------------------------+ + rsp + 8 | condvar pointer | + +--------------------------+ + rsp + 4 | old broadcast_seq value | + +--------------------------+ + rsp + 0 | old cancellation mode | + +--------------------------+ + */ + + cmpq $-1, dep_mutex(%rdi) + + /* Prepare structure passed to cancellation handler. */ + movq %rdi, 8(%rsp) + movq %rsi, 16(%rsp) + movq %rdx, %r13 + + je 22f + movq %rsi, dep_mutex(%rdi) + +22: +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +# ifdef __PIC__ + cmpl $0, __have_futex_clock_realtime(%rip) +# else + cmpl $0, __have_futex_clock_realtime +# endif + je .Lreltmo +#endif + + /* Get internal lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, cond_lock(%rdi) +#endif + jnz 31f + + /* Unlock the mutex. */ +32: movq 16(%rsp), %rdi + xorl %esi, %esi + callq __pthread_mutex_unlock_usercnt + + testl %eax, %eax + jne 46f + + movq 8(%rsp), %rdi + incq total_seq(%rdi) + incl cond_futex(%rdi) + addl $(1 << nwaiters_shift), cond_nwaiters(%rdi) + + /* Get and store current wakeup_seq value. */ + movq 8(%rsp), %rdi + movq wakeup_seq(%rdi), %r9 + movl broadcast_seq(%rdi), %edx + movq %r9, 24(%rsp) + movl %edx, 4(%rsp) + +38: movl cond_futex(%rdi), %r12d + + /* Unlock. */ + LOCK +#if cond_lock == 0 + decl (%rdi) +#else + decl cond_lock(%rdi) +#endif + jne 33f + +.LcleanupSTART1: +34: callq __pthread_enable_asynccancel + movl %eax, (%rsp) + + movq %r13, %r10 + movl $FUTEX_WAIT_BITSET, %esi + cmpq $-1, dep_mutex(%rdi) + je 60f + + movq dep_mutex(%rdi), %r8 + /* Requeue to a non-robust PI mutex if the PI bit is set and + the robust bit is not set. */ + movl MUTEX_KIND(%r8), %eax + andl $(ROBUST_BIT|PI_BIT), %eax + cmpl $PI_BIT, %eax + jne 61f + + movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi + xorl %eax, %eax + /* The following only works like this because we only support + two clocks, represented using a single bit. */ + testl $1, cond_nwaiters(%rdi) + movl $FUTEX_CLOCK_REALTIME, %edx + cmove %edx, %eax + orl %eax, %esi + movq %r12, %rdx + addq $cond_futex, %rdi + movl $SYS_futex, %eax + syscall + + movl $1, %r15d +#ifdef __ASSUME_REQUEUE_PI + jmp 62f +#else + cmpq $-4095, %rax + jnae 62f + + subq $cond_futex, %rdi +#endif + +61: movl $(FUTEX_WAIT_BITSET|FUTEX_PRIVATE_FLAG), %esi +60: xorl %r15d, %r15d + xorl %eax, %eax + /* The following only works like this because we only support + two clocks, represented using a single bit. */ + testl $1, cond_nwaiters(%rdi) + movl $FUTEX_CLOCK_REALTIME, %edx + movl $0xffffffff, %r9d + cmove %edx, %eax + orl %eax, %esi + movq %r12, %rdx + addq $cond_futex, %rdi + movl $SYS_futex, %eax + syscall +62: movq %rax, %r14 + + movl (%rsp), %edi + callq __pthread_disable_asynccancel +.LcleanupEND1: + + /* Lock. */ + movq 8(%rsp), %rdi + movl $1, %esi + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, cond_lock(%rdi) +#endif + jne 35f + +36: movl broadcast_seq(%rdi), %edx + + movq woken_seq(%rdi), %rax + + movq wakeup_seq(%rdi), %r9 + + cmpl 4(%rsp), %edx + jne 53f + + cmpq 24(%rsp), %r9 + jbe 45f + + cmpq %rax, %r9 + ja 39f + +45: cmpq $-ETIMEDOUT, %r14 + jne 38b + +99: incq wakeup_seq(%rdi) + incl cond_futex(%rdi) + movl $ETIMEDOUT, %r14d + jmp 44f + +53: xorq %r14, %r14 + jmp 54f + +39: xorq %r14, %r14 +44: incq woken_seq(%rdi) + +54: subl $(1 << nwaiters_shift), cond_nwaiters(%rdi) + + /* Wake up a thread which wants to destroy the condvar object. */ + cmpq $0xffffffffffffffff, total_seq(%rdi) + jne 55f + movl cond_nwaiters(%rdi), %eax + andl $~((1 << nwaiters_shift) - 1), %eax + jne 55f + + addq $cond_nwaiters, %rdi + cmpq $-1, dep_mutex-cond_nwaiters(%rdi) + movl $1, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE, %eax + movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi + cmove %eax, %esi +#else + movl $0, %eax + movl %fs:PRIVATE_FUTEX, %esi + cmove %eax, %esi + orl $FUTEX_WAKE, %esi +#endif + movl $SYS_futex, %eax + syscall + subq $cond_nwaiters, %rdi + +55: LOCK +#if cond_lock == 0 + decl (%rdi) +#else + decl cond_lock(%rdi) +#endif + jne 40f + + /* If requeue_pi is used the kernel performs the locking of the + mutex. */ +41: movq 16(%rsp), %rdi + testl %r15d, %r15d + jnz 64f + + callq __pthread_mutex_cond_lock + +63: testq %rax, %rax + cmoveq %r14, %rax + +48: addq $FRAME_SIZE, %rsp + cfi_adjust_cfa_offset(-FRAME_SIZE) + popq %r15 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r15) + popq %r14 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r14) + popq %r13 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r13) + popq %r12 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r12) + + retq + + cfi_restore_state + +64: callq __pthread_mutex_cond_lock_adjust + movq %r14, %rax + jmp 48b + + /* Initial locking failed. */ +31: +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_lock_wait + jmp 32b + + /* Unlock in loop requires wakeup. */ +33: +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_unlock_wake + jmp 34b + + /* Locking in loop failed. */ +35: +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_lock_wait +#if cond_lock != 0 + subq $cond_lock, %rdi +#endif + jmp 36b + + /* Unlock after loop requires wakeup. */ +40: +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_unlock_wake + jmp 41b + + /* The initial unlocking of the mutex failed. */ +46: movq 8(%rsp), %rdi + movq %rax, (%rsp) + LOCK +#if cond_lock == 0 + decl (%rdi) +#else + decl cond_lock(%rdi) +#endif + jne 47f + +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_unlock_wake + +47: movq (%rsp), %rax + jmp 48b + + +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +.Lreltmo: + xorl %r15d, %r15d + + /* Get internal lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +# if cond_lock == 0 + cmpxchgl %esi, (%rdi) +# else + cmpxchgl %esi, cond_lock(%rdi) +# endif + jnz 1f + + /* Unlock the mutex. */ +2: movq 16(%rsp), %rdi + xorl %esi, %esi + callq __pthread_mutex_unlock_usercnt + + testl %eax, %eax + jne 46b + + movq 8(%rsp), %rdi + incq total_seq(%rdi) + incl cond_futex(%rdi) + addl $(1 << nwaiters_shift), cond_nwaiters(%rdi) + + /* Get and store current wakeup_seq value. */ + movq 8(%rsp), %rdi + movq wakeup_seq(%rdi), %r9 + movl broadcast_seq(%rdi), %edx + movq %r9, 24(%rsp) + movl %edx, 4(%rsp) + + /* Get the current time. */ +8: +# ifdef __NR_clock_gettime + /* Get the clock number. Note that the field in the condvar + structure stores the number minus 1. */ + movq 8(%rsp), %rdi + movl cond_nwaiters(%rdi), %edi + andl $((1 << nwaiters_shift) - 1), %edi + /* Only clocks 0 and 1 are allowed so far. Both are handled in the + kernel. */ + leaq 32(%rsp), %rsi +# ifdef SHARED + movq __vdso_clock_gettime@GOTPCREL(%rip), %rax + movq (%rax), %rax + PTR_DEMANGLE (%rax) + jz 26f + call *%rax + jmp 27f +# endif +26: movl $__NR_clock_gettime, %eax + syscall +27: +# ifndef __ASSUME_POSIX_TIMERS + cmpq $-ENOSYS, %rax + je 19f +# endif + + /* Compute relative timeout. */ + movq (%r13), %rcx + movq 8(%r13), %rdx + subq 32(%rsp), %rcx + subq 40(%rsp), %rdx +# else + leaq 24(%rsp), %rdi + xorl %esi, %esi + movq $VSYSCALL_ADDR_vgettimeofday, %rax + callq *%rax + + /* Compute relative timeout. */ + movq 40(%rsp), %rax + movl $1000, %edx + mul %rdx /* Milli seconds to nano seconds. */ + movq (%r13), %rcx + movq 8(%r13), %rdx + subq 32(%rsp), %rcx + subq %rax, %rdx +# endif + jns 12f + addq $1000000000, %rdx + decq %rcx +12: testq %rcx, %rcx + movq 8(%rsp), %rdi + movq $-ETIMEDOUT, %r14 + js 6f + + /* Store relative timeout. */ +21: movq %rcx, 32(%rsp) + movq %rdx, 40(%rsp) + + movl cond_futex(%rdi), %r12d + + /* Unlock. */ + LOCK +# if cond_lock == 0 + decl (%rdi) +# else + decl cond_lock(%rdi) +# endif + jne 3f + +.LcleanupSTART2: +4: callq __pthread_enable_asynccancel + movl %eax, (%rsp) + + leaq 32(%rsp), %r10 + cmpq $-1, dep_mutex(%rdi) + movq %r12, %rdx +# ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAIT, %eax + movl $(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), %esi + cmove %eax, %esi +# else + movl $0, %eax + movl %fs:PRIVATE_FUTEX, %esi + cmove %eax, %esi +# if FUTEX_WAIT != 0 + orl $FUTEX_WAIT, %esi +# endif +# endif + addq $cond_futex, %rdi + movl $SYS_futex, %eax + syscall + movq %rax, %r14 + + movl (%rsp), %edi + callq __pthread_disable_asynccancel +.LcleanupEND2: + + /* Lock. */ + movq 8(%rsp), %rdi + movl $1, %esi + xorl %eax, %eax + LOCK +# if cond_lock == 0 + cmpxchgl %esi, (%rdi) +# else + cmpxchgl %esi, cond_lock(%rdi) +# endif + jne 5f + +6: movl broadcast_seq(%rdi), %edx + + movq woken_seq(%rdi), %rax + + movq wakeup_seq(%rdi), %r9 + + cmpl 4(%rsp), %edx + jne 53b + + cmpq 24(%rsp), %r9 + jbe 15f + + cmpq %rax, %r9 + ja 39b + +15: cmpq $-ETIMEDOUT, %r14 + jne 8b + + jmp 99b + + /* Initial locking failed. */ +1: +# if cond_lock != 0 + addq $cond_lock, %rdi +# endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_lock_wait + jmp 2b + + /* Unlock in loop requires wakeup. */ +3: +# if cond_lock != 0 + addq $cond_lock, %rdi +# endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_unlock_wake + jmp 4b + + /* Locking in loop failed. */ +5: +# if cond_lock != 0 + addq $cond_lock, %rdi +# endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_lock_wait +# if cond_lock != 0 + subq $cond_lock, %rdi +# endif + jmp 6b + +# if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS + /* clock_gettime not available. */ +19: leaq 32(%rsp), %rdi + xorl %esi, %esi + movq $VSYSCALL_ADDR_vgettimeofday, %rax + callq *%rax + + /* Compute relative timeout. */ + movq 40(%rsp), %rax + movl $1000, %edx + mul %rdx /* Milli seconds to nano seconds. */ + movq (%r13), %rcx + movq 8(%r13), %rdx + subq 32(%rsp), %rcx + subq %rax, %rdx + jns 20f + addq $1000000000, %rdx + decq %rcx +20: testq %rcx, %rcx + movq 8(%rsp), %rdi + movq $-ETIMEDOUT, %r14 + js 6b + jmp 21b +# endif +#endif + .size __pthread_cond_timedwait, .-__pthread_cond_timedwait +weak_alias(__pthread_cond_timedwait, pthread_cond_timedwait) + + + .align 16 + .type __condvar_cleanup2, @function +__condvar_cleanup2: + /* Stack frame: + + rsp + 72 + +--------------------------+ + rsp + 64 | %r12 | + +--------------------------+ + rsp + 56 | %r13 | + +--------------------------+ + rsp + 48 | %r14 | + +--------------------------+ + rsp + 24 | unused | + +--------------------------+ + rsp + 16 | mutex pointer | + +--------------------------+ + rsp + 8 | condvar pointer | + +--------------------------+ + rsp + 4 | old broadcast_seq value | + +--------------------------+ + rsp + 0 | old cancellation mode | + +--------------------------+ + */ + + movq %rax, 24(%rsp) + + /* Get internal lock. */ + movq 8(%rsp), %rdi + movl $1, %esi + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, cond_lock(%rdi) +#endif + jz 1f + +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_lock_wait +#if cond_lock != 0 + subq $cond_lock, %rdi +#endif + +1: movl broadcast_seq(%rdi), %edx + cmpl 4(%rsp), %edx + jne 3f + + /* We increment the wakeup_seq counter only if it is lower than + total_seq. If this is not the case the thread was woken and + then canceled. In this case we ignore the signal. */ + movq total_seq(%rdi), %rax + cmpq wakeup_seq(%rdi), %rax + jbe 6f + incq wakeup_seq(%rdi) + incl cond_futex(%rdi) +6: incq woken_seq(%rdi) + +3: subl $(1 << nwaiters_shift), cond_nwaiters(%rdi) + + /* Wake up a thread which wants to destroy the condvar object. */ + xorq %r12, %r12 + cmpq $0xffffffffffffffff, total_seq(%rdi) + jne 4f + movl cond_nwaiters(%rdi), %eax + andl $~((1 << nwaiters_shift) - 1), %eax + jne 4f + + cmpq $-1, dep_mutex(%rdi) + leaq cond_nwaiters(%rdi), %rdi + movl $1, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE, %eax + movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi + cmove %eax, %esi +#else + movl $0, %eax + movl %fs:PRIVATE_FUTEX, %esi + cmove %eax, %esi + orl $FUTEX_WAKE, %esi +#endif + movl $SYS_futex, %eax + syscall + subq $cond_nwaiters, %rdi + movl $1, %r12d + +4: LOCK +#if cond_lock == 0 + decl (%rdi) +#else + decl cond_lock(%rdi) +#endif + je 2f +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_unlock_wake + + /* Wake up all waiters to make sure no signal gets lost. */ +2: testq %r12, %r12 + jnz 5f + addq $cond_futex, %rdi + cmpq $-1, dep_mutex-cond_futex(%rdi) + movl $0x7fffffff, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE, %eax + movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi + cmove %eax, %esi +#else + movl $0, %eax + movl %fs:PRIVATE_FUTEX, %esi + cmove %eax, %esi + orl $FUTEX_WAKE, %esi +#endif + movl $SYS_futex, %eax + syscall + +5: movq 16(%rsp), %rdi + callq __pthread_mutex_cond_lock + + movq 24(%rsp), %rdi + movq FRAME_SIZE(%rsp), %r15 + movq FRAME_SIZE+8(%rsp), %r14 + movq FRAME_SIZE+16(%rsp), %r13 + movq FRAME_SIZE+24(%rsp), %r12 +.LcallUR: + call _Unwind_Resume@PLT + hlt +.LENDCODE: + cfi_endproc + .size __condvar_cleanup2, .-__condvar_cleanup2 + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte DW_EH_PE_omit # @LPStart format + .byte DW_EH_PE_omit # @TType format + .byte DW_EH_PE_uleb128 # call-site format + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART1-.LSTARTCODE + .uleb128 .LcleanupEND1-.LcleanupSTART1 + .uleb128 __condvar_cleanup2-.LSTARTCODE + .uleb128 0 +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME + .uleb128 .LcleanupSTART2-.LSTARTCODE + .uleb128 .LcleanupEND2-.LcleanupSTART2 + .uleb128 __condvar_cleanup2-.LSTARTCODE + .uleb128 0 +#endif + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +.Lcstend: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 8 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 8 +DW.ref.__gcc_personality_v0: + .quad __gcc_personality_v0 +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S new file mode 100644 index 000000000..45ce84e65 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S @@ -0,0 +1,487 @@ +/* Copyright (C) 2002-2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelcond.h> +#include <tcb-offsets.h> +#include <pthread-pi-defines.h> + +#include <bits/kernel-features.h> + + + .text + +/* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */ + .globl __pthread_cond_wait + .type __pthread_cond_wait, @function + .hidden __pthread_cond_wait + .align 16 +__pthread_cond_wait: +.LSTARTCODE: + cfi_startproc + +#define FRAME_SIZE 32 + leaq -FRAME_SIZE(%rsp), %rsp + cfi_adjust_cfa_offset(FRAME_SIZE) + + /* Stack frame: + + rsp + 32 + +--------------------------+ + rsp + 24 | old wake_seq value | + +--------------------------+ + rsp + 16 | mutex pointer | + +--------------------------+ + rsp + 8 | condvar pointer | + +--------------------------+ + rsp + 4 | old broadcast_seq value | + +--------------------------+ + rsp + 0 | old cancellation mode | + +--------------------------+ + */ + + cmpq $-1, dep_mutex(%rdi) + + /* Prepare structure passed to cancellation handler. */ + movq %rdi, 8(%rsp) + movq %rsi, 16(%rsp) + + je 15f + movq %rsi, dep_mutex(%rdi) + + /* Get internal lock. */ +15: movl $1, %esi + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, cond_lock(%rdi) +#endif + jne 1f + + /* Unlock the mutex. */ +2: movq 16(%rsp), %rdi + xorl %esi, %esi + callq __pthread_mutex_unlock_usercnt + + testl %eax, %eax + jne 12f + + movq 8(%rsp), %rdi + incq total_seq(%rdi) + incl cond_futex(%rdi) + addl $(1 << nwaiters_shift), cond_nwaiters(%rdi) + + /* Get and store current wakeup_seq value. */ + movq 8(%rsp), %rdi + movq wakeup_seq(%rdi), %r9 + movl broadcast_seq(%rdi), %edx + movq %r9, 24(%rsp) + movl %edx, 4(%rsp) + + /* Unlock. */ +8: movl cond_futex(%rdi), %edx + LOCK +#if cond_lock == 0 + decl (%rdi) +#else + decl cond_lock(%rdi) +#endif + jne 3f + +.LcleanupSTART: +4: callq __pthread_enable_asynccancel + movl %eax, (%rsp) + + xorq %r10, %r10 + cmpq $-1, dep_mutex(%rdi) + leaq cond_futex(%rdi), %rdi + movl $FUTEX_WAIT, %esi + je 60f + + movq dep_mutex-cond_futex(%rdi), %r8 + /* Requeue to a non-robust PI mutex if the PI bit is set and + the robust bit is not set. */ + movl MUTEX_KIND(%r8), %eax + andl $(ROBUST_BIT|PI_BIT), %eax + cmpl $PI_BIT, %eax + jne 61f + + movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi + movl $SYS_futex, %eax + syscall + + movl $1, %r8d +#ifdef __ASSUME_REQUEUE_PI + jmp 62f +#else + cmpq $-4095, %rax + jnae 62f + +# ifndef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAIT, %esi +# endif +#endif + +61: +#ifdef __ASSUME_PRIVATE_FUTEX + movl $(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), %esi +#else + orl %fs:PRIVATE_FUTEX, %esi +#endif +60: xorl %r8d, %r8d + movl $SYS_futex, %eax + syscall + +62: movl (%rsp), %edi + callq __pthread_disable_asynccancel +.LcleanupEND: + + /* Lock. */ + movq 8(%rsp), %rdi + movl $1, %esi + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, cond_lock(%rdi) +#endif + jnz 5f + +6: movl broadcast_seq(%rdi), %edx + + movq woken_seq(%rdi), %rax + + movq wakeup_seq(%rdi), %r9 + + cmpl 4(%rsp), %edx + jne 16f + + cmpq 24(%rsp), %r9 + jbe 8b + + cmpq %rax, %r9 + jna 8b + + incq woken_seq(%rdi) + + /* Unlock */ +16: subl $(1 << nwaiters_shift), cond_nwaiters(%rdi) + + /* Wake up a thread which wants to destroy the condvar object. */ + cmpq $0xffffffffffffffff, total_seq(%rdi) + jne 17f + movl cond_nwaiters(%rdi), %eax + andl $~((1 << nwaiters_shift) - 1), %eax + jne 17f + + addq $cond_nwaiters, %rdi + cmpq $-1, dep_mutex-cond_nwaiters(%rdi) + movl $1, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE, %eax + movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi + cmove %eax, %esi +#else + movl $0, %eax + movl %fs:PRIVATE_FUTEX, %esi + cmove %eax, %esi + orl $FUTEX_WAKE, %esi +#endif + movl $SYS_futex, %eax + syscall + subq $cond_nwaiters, %rdi + +17: LOCK +#if cond_lock == 0 + decl (%rdi) +#else + decl cond_lock(%rdi) +#endif + jne 10f + + /* If requeue_pi is used the kernel performs the locking of the + mutex. */ +11: movq 16(%rsp), %rdi + testl %r8d, %r8d + jnz 18f + + callq __pthread_mutex_cond_lock + +14: leaq FRAME_SIZE(%rsp), %rsp + cfi_adjust_cfa_offset(-FRAME_SIZE) + + /* We return the result of the mutex_lock operation. */ + retq + + cfi_adjust_cfa_offset(FRAME_SIZE) + +18: callq __pthread_mutex_cond_lock_adjust + xorl %eax, %eax + jmp 14b + + /* Initial locking failed. */ +1: +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_lock_wait + jmp 2b + + /* Unlock in loop requires wakeup. */ +3: +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + /* The call preserves %rdx. */ + callq __lll_unlock_wake +#if cond_lock != 0 + subq $cond_lock, %rdi +#endif + jmp 4b + + /* Locking in loop failed. */ +5: +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_lock_wait +#if cond_lock != 0 + subq $cond_lock, %rdi +#endif + jmp 6b + + /* Unlock after loop requires wakeup. */ +10: +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_unlock_wake + jmp 11b + + /* The initial unlocking of the mutex failed. */ +12: movq %rax, %r10 + movq 8(%rsp), %rdi + LOCK +#if cond_lock == 0 + decl (%rdi) +#else + decl cond_lock(%rdi) +#endif + je 13f + +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_unlock_wake + +13: movq %r10, %rax + jmp 14b + .size __pthread_cond_wait, .-__pthread_cond_wait +weak_alias(__pthread_cond_wait, pthread_cond_wait) + + + .align 16 + .type __condvar_cleanup1, @function + .globl __condvar_cleanup1 + .hidden __condvar_cleanup1 +__condvar_cleanup1: + /* Stack frame: + + rsp + 32 + +--------------------------+ + rsp + 24 | unused | + +--------------------------+ + rsp + 16 | mutex pointer | + +--------------------------+ + rsp + 8 | condvar pointer | + +--------------------------+ + rsp + 4 | old broadcast_seq value | + +--------------------------+ + rsp + 0 | old cancellation mode | + +--------------------------+ + */ + + movq %rax, 24(%rsp) + + /* Get internal lock. */ + movq 8(%rsp), %rdi + movl $1, %esi + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, cond_lock(%rdi) +#endif + jz 1f + +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_lock_wait +#if cond_lock != 0 + subq $cond_lock, %rdi +#endif + +1: movl broadcast_seq(%rdi), %edx + cmpl 4(%rsp), %edx + jne 3f + + /* We increment the wakeup_seq counter only if it is lower than + total_seq. If this is not the case the thread was woken and + then canceled. In this case we ignore the signal. */ + movq total_seq(%rdi), %rax + cmpq wakeup_seq(%rdi), %rax + jbe 6f + incq wakeup_seq(%rdi) + incl cond_futex(%rdi) +6: incq woken_seq(%rdi) + +3: subl $(1 << nwaiters_shift), cond_nwaiters(%rdi) + + /* Wake up a thread which wants to destroy the condvar object. */ + xorl %ecx, %ecx + cmpq $0xffffffffffffffff, total_seq(%rdi) + jne 4f + movl cond_nwaiters(%rdi), %eax + andl $~((1 << nwaiters_shift) - 1), %eax + jne 4f + + cmpq $-1, dep_mutex(%rdi) + leaq cond_nwaiters(%rdi), %rdi + movl $1, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE, %eax + movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi + cmove %eax, %esi +#else + movl $0, %eax + movl %fs:PRIVATE_FUTEX, %esi + cmove %eax, %esi + orl $FUTEX_WAKE, %esi +#endif + movl $SYS_futex, %eax + syscall + subq $cond_nwaiters, %rdi + movl $1, %ecx + +4: LOCK +#if cond_lock == 0 + decl (%rdi) +#else + decl cond_lock(%rdi) +#endif + je 2f +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + /* The call preserves %rcx. */ + callq __lll_unlock_wake + + /* Wake up all waiters to make sure no signal gets lost. */ +2: testl %ecx, %ecx + jnz 5f + addq $cond_futex, %rdi + cmpq $-1, dep_mutex-cond_futex(%rdi) + movl $0x7fffffff, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE, %eax + movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi + cmove %eax, %esi +#else + movl $0, %eax + movl %fs:PRIVATE_FUTEX, %esi + cmove %eax, %esi + orl $FUTEX_WAKE, %esi +#endif + movl $SYS_futex, %eax + syscall + +5: movq 16(%rsp), %rdi + callq __pthread_mutex_cond_lock + + movq 24(%rsp), %rdi +.LcallUR: + call _Unwind_Resume@PLT + hlt +.LENDCODE: + cfi_endproc + .size __condvar_cleanup1, .-__condvar_cleanup1 + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte DW_EH_PE_omit # @LPStart format + .byte DW_EH_PE_omit # @TType format + .byte DW_EH_PE_uleb128 # call-site format + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 __condvar_cleanup1-.LSTARTCODE + .uleb128 0 + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +.Lcstend: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 8 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 8 +DW.ref.__gcc_personality_v0: + .quad __gcc_personality_v0 +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S new file mode 100644 index 000000000..b0e3516e7 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S @@ -0,0 +1,190 @@ +/* Copyright (C) 2002, 2003, 2005, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <bits/kernel-features.h> +#include <tcb-offsets.h> +#include <lowlevellock.h> + + + .comm __fork_generation, 4, 4 + + .text + + + .globl __pthread_once + .type __pthread_once,@function + .hidden __pthread_once + .align 16 +__pthread_once: +.LSTARTCODE: + cfi_startproc + testl $2, (%rdi) + jz 1f + xorl %eax, %eax + retq + + /* Preserve the function pointer. */ +1: pushq %rsi + cfi_adjust_cfa_offset(8) + xorq %r10, %r10 + + /* Not yet initialized or initialization in progress. + Get the fork generation counter now. */ +6: movl (%rdi), %eax + +5: movl %eax, %edx + + testl $2, %eax + jnz 4f + + andl $3, %edx + orl __fork_generation(%rip), %edx + orl $1, %edx + + LOCK + cmpxchgl %edx, (%rdi) + jnz 5b + + /* Check whether another thread already runs the initializer. */ + testl $1, %eax + jz 3f /* No -> do it. */ + + /* Check whether the initializer execution was interrupted + by a fork. */ + xorl %edx, %eax + testl $0xfffffffc, %eax + jnz 3f /* Different for generation -> run initializer. */ + + /* Somebody else got here first. Wait. */ +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAIT|FUTEX_PRIVATE_FLAG, %esi +#else +# if FUTEX_WAIT == 0 + movl %fs:PRIVATE_FUTEX, %esi +# else + movl $FUTEX_WAIT, %esi + orl %fs:PRIVATE_FUTEX, %esi +# endif +#endif + movl $SYS_futex, %eax + syscall + jmp 6b + + /* Preserve the pointer to the control variable. */ +3: pushq %rdi + cfi_adjust_cfa_offset(8) + pushq %rdi + cfi_adjust_cfa_offset(8) + +.LcleanupSTART: + callq *16(%rsp) +.LcleanupEND: + + /* Get the control variable address back. */ + popq %rdi + cfi_adjust_cfa_offset(-8) + + /* Sucessful run of the initializer. Signal that we are done. */ + LOCK + incl (%rdi) + + addq $8, %rsp + cfi_adjust_cfa_offset(-8) + + /* Wake up all other threads. */ + movl $0x7fffffff, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %esi +#else + movl $FUTEX_WAKE, %esi + orl %fs:PRIVATE_FUTEX, %esi +#endif + movl $SYS_futex, %eax + syscall + +4: addq $8, %rsp + cfi_adjust_cfa_offset(-8) + xorl %eax, %eax + retq + .size __pthread_once,.-__pthread_once + + + .globl __pthread_once_internal +__pthread_once_internal = __pthread_once + + .globl pthread_once +pthread_once = __pthread_once + + + .type clear_once_control,@function + .align 16 +clear_once_control: + cfi_adjust_cfa_offset(3 * 8) + movq (%rsp), %rdi + movq %rax, %r8 + movl $0, (%rdi) + + movl $0x7fffffff, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %esi +#else + movl $FUTEX_WAKE, %esi + orl %fs:PRIVATE_FUTEX, %esi +#endif + movl $SYS_futex, %eax + syscall + + movq %r8, %rdi +.LcallUR: + call _Unwind_Resume@PLT + hlt +.LENDCODE: + cfi_endproc + .size clear_once_control,.-clear_once_control + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte DW_EH_PE_omit # @LPStart format + .byte DW_EH_PE_omit # @TType format + .byte DW_EH_PE_uleb128 # call-site format + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 clear_once_control-.LSTARTCODE + .uleb128 0 + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +.Lcstend: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 8 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 8 +DW.ref.__gcc_personality_v0: + .quad __gcc_personality_v0 +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S new file mode 100644 index 000000000..2d42ec15e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S @@ -0,0 +1,180 @@ +/* Copyright (C) 2002, 2003, 2005, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <bits/kernel-features.h> +#include <tcb-offsets.h> + + + .text + + .globl __pthread_rwlock_rdlock + .type __pthread_rwlock_rdlock,@function + .hidden __pthread_rwlock_rdlock + .align 16 +__pthread_rwlock_rdlock: + cfi_startproc + xorq %r10, %r10 + + /* Get the lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, MUTEX(%rdi) +#endif + jnz 1f + +2: movl WRITER(%rdi), %eax + testl %eax, %eax + jne 14f + cmpl $0, WRITERS_QUEUED(%rdi) + je 5f + cmpl $0, FLAGS(%rdi) + je 5f + +3: incl READERS_QUEUED(%rdi) + je 4f + + movl READERS_WAKEUP(%rdi), %edx + + LOCK +#if MUTEX == 0 + decl (%rdi) +#else + decl MUTEX(%rdi) +#endif + jne 10f + +11: +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %esi + xorl PSHARED(%rdi), %esi +#else +# if FUTEX_WAIT == 0 + movl PSHARED(%rdi), %esi +# else + movl $FUTEX_WAIT, %esi + orl PSHARED(%rdi), %esi +# endif + xorl %fs:PRIVATE_FUTEX, %esi +#endif + addq $READERS_WAKEUP, %rdi + movl $SYS_futex, %eax + syscall + + subq $READERS_WAKEUP, %rdi + + /* Reget the lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, MUTEX(%rdi) +#endif + jnz 12f + +13: decl READERS_QUEUED(%rdi) + jmp 2b + +5: xorl %edx, %edx + incl NR_READERS(%rdi) + je 8f +9: LOCK +#if MUTEX == 0 + decl (%rdi) +#else + decl MUTEX(%rdi) +#endif + jne 6f +7: + + movq %rdx, %rax + retq + +1: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_lock_wait +#if MUTEX != 0 + subq $MUTEX, %rdi +#endif + jmp 2b + +14: cmpl %fs:TID, %eax + jne 3b + /* Deadlock detected. */ + movl $EDEADLK, %edx + jmp 9b + +6: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_unlock_wake +#if MUTEX != 0 + subq $MUTEX, %rdi +#endif + jmp 7b + + /* Overflow. */ +8: decl NR_READERS(%rdi) + movl $EAGAIN, %edx + jmp 9b + + /* Overflow. */ +4: decl READERS_QUEUED(%rdi) + movl $EAGAIN, %edx + jmp 9b + +10: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_unlock_wake +#if MUTEX != 0 + subq $MUTEX, %rdi +#endif + jmp 11b + +12: movl PSHARED(%rdi), %esi +#if MUTEX == 0 + addq $MUTEX, %rdi +#endif + callq __lll_lock_wait +#if MUTEX != 0 + subq $MUTEX, %rdi +#endif + jmp 13b + cfi_endproc + .size __pthread_rwlock_rdlock,.-__pthread_rwlock_rdlock + + .globl pthread_rwlock_rdlock +pthread_rwlock_rdlock = __pthread_rwlock_rdlock + + .globl __pthread_rwlock_rdlock_internal +__pthread_rwlock_rdlock_internal = __pthread_rwlock_rdlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S new file mode 100644 index 000000000..3629ffbe5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S @@ -0,0 +1,276 @@ +/* Copyright (C) 2002-2005, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <bits/kernel-features.h> +#include <tcb-offsets.h> + + +/* For the calculation see asm/vsyscall.h. */ +#define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000 + + .text + + .globl pthread_rwlock_timedrdlock + .type pthread_rwlock_timedrdlock,@function + .align 16 +pthread_rwlock_timedrdlock: + cfi_startproc + pushq %r12 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r12, 0) + pushq %r13 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r13, 0) +#ifdef __ASSUME_FUTEX_CLOCK_REALTIME +# define VALREG %edx +#else + pushq %r14 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r14, 0) + + subq $16, %rsp + cfi_adjust_cfa_offset(16) +# define VALREG %r14d +#endif + + movq %rdi, %r12 + movq %rsi, %r13 + + /* Get the lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, MUTEX(%rdi) +#endif + jnz 1f + +2: movl WRITER(%r12), %eax + testl %eax, %eax + jne 14f + cmpl $0, WRITERS_QUEUED(%r12) + je 5f + cmpl $0, FLAGS(%r12) + je 5f + + /* Check the value of the timeout parameter. */ +3: cmpq $1000000000, 8(%r13) + jae 19f + + incl READERS_QUEUED(%r12) + je 4f + + movl READERS_WAKEUP(%r12), VALREG + + /* Unlock. */ + LOCK +#if MUTEX == 0 + decl (%r12) +#else + decl MUTEX(%r12) +#endif + jne 10f + +11: +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +# ifdef __PIC__ + cmpl $0, __have_futex_clock_realtime(%rip) +# else + cmpl $0, __have_futex_clock_realtime +# endif + je .Lreltmo +#endif + + movl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, %esi + xorl PSHARED(%r12), %esi + movq %r13, %r10 + movl $0xffffffff, %r9d +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME + movl %r14d, %edx +#endif +21: leaq READERS_WAKEUP(%r12), %rdi + movl $SYS_futex, %eax + syscall + movq %rax, %rdx + +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME + .subsection 2 +.Lreltmo: + /* Get current time. */ + movq %rsp, %rdi + xorl %esi, %esi + movq $VSYSCALL_ADDR_vgettimeofday, %rax + callq *%rax + + /* Compute relative timeout. */ + movq 8(%rsp), %rax + movl $1000, %edi + mul %rdi /* Milli seconds to nano seconds. */ + movq (%r13), %rcx + movq 8(%r13), %rdi + subq (%rsp), %rcx + subq %rax, %rdi + jns 15f + addq $1000000000, %rdi + decq %rcx +15: testq %rcx, %rcx + js 16f /* Time is already up. */ + + /* Futex call. */ + movq %rcx, (%rsp) /* Store relative timeout. */ + movq %rdi, 8(%rsp) + +# ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %esi + xorl PSHARED(%r12), %esi +# else +# if FUTEX_WAIT == 0 + movl PSHARED(%r12), %esi +# else + movl $FUTEX_WAIT, %esi + orl PSHARED(%r12), %esi +# endif + xorl %fs:PRIVATE_FUTEX, %esi +# endif + movq %rsp, %r10 + movl %r14d, %edx + + jmp 21b + .previous +#endif + +17: /* Reget the lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %esi, (%r12) +#else + cmpxchgl %esi, MUTEX(%r12) +#endif + jnz 12f + +13: decl READERS_QUEUED(%r12) + cmpq $-ETIMEDOUT, %rdx + jne 2b + +18: movl $ETIMEDOUT, %edx + jmp 9f + + +5: xorl %edx, %edx + incl NR_READERS(%r12) + je 8f +9: LOCK +#if MUTEX == 0 + decl (%r12) +#else + decl MUTEX(%r12) +#endif + jne 6f + +7: movq %rdx, %rax + +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME + addq $16, %rsp + cfi_adjust_cfa_offset(-16) + popq %r14 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r14) +#endif + popq %r13 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r13) + popq %r12 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r12) + retq + +#ifdef __ASSUME_PRIVATE_FUTEX + cfi_adjust_cfa_offset(16) + cfi_rel_offset(%r12, 8) + cfi_rel_offset(%r13, 0) +#else + cfi_adjust_cfa_offset(40) + cfi_offset(%r12, -16) + cfi_offset(%r13, -24) + cfi_offset(%r14, -32) +#endif +1: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_lock_wait + jmp 2b + +14: cmpl %fs:TID, %eax + jne 3b + movl $EDEADLK, %edx + jmp 9b + +6: movl PSHARED(%r12), %esi +#if MUTEX == 0 + movq %r12, %rdi +#else + leal MUTEX(%r12), %rdi +#endif + callq __lll_unlock_wake + jmp 7b + + /* Overflow. */ +8: decl NR_READERS(%r12) + movl $EAGAIN, %edx + jmp 9b + + /* Overflow. */ +4: decl READERS_QUEUED(%r12) + movl $EAGAIN, %edx + jmp 9b + +10: movl PSHARED(%r12), %esi +#if MUTEX == 0 + movq %r12, %rdi +#else + leaq MUTEX(%r12), %rdi +#endif + callq __lll_unlock_wake + jmp 11b + +12: movl PSHARED(%r12), %esi +#if MUTEX == 0 + movq %r12, %rdi +#else + leaq MUTEX(%r12), %rdi +#endif + callq __lll_lock_wait + jmp 13b + +16: movq $-ETIMEDOUT, %rdx + jmp 17b + +19: movl $EINVAL, %edx + jmp 9b + cfi_endproc + .size pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S new file mode 100644 index 000000000..23e1ee155 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S @@ -0,0 +1,268 @@ +/* Copyright (C) 2002, 2003, 2005, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <bits/kernel-features.h> +#include <tcb-offsets.h> + + +/* For the calculation see asm/vsyscall.h. */ +#define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000 + + .text + + .globl pthread_rwlock_timedwrlock + .type pthread_rwlock_timedwrlock,@function + .align 16 +pthread_rwlock_timedwrlock: + cfi_startproc + pushq %r12 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r12, 0) + pushq %r13 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r13, 0) +#ifdef __ASSUME_FUTEX_CLOCK_REALTIME +# define VALREG %edx +#else + pushq %r14 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r14, 0) + + subq $16, %rsp + cfi_adjust_cfa_offset(16) +# define VALREG %r14d +#endif + + movq %rdi, %r12 + movq %rsi, %r13 + + /* Get the lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, MUTEX(%rdi) +#endif + jnz 1f + +2: movl WRITER(%r12), %eax + testl %eax, %eax + jne 14f + cmpl $0, NR_READERS(%r12) + je 5f + + /* Check the value of the timeout parameter. */ +3: cmpq $1000000000, 8(%r13) + jae 19f + + incl WRITERS_QUEUED(%r12) + je 4f + + movl WRITERS_WAKEUP(%r12), VALREG + + LOCK +#if MUTEX == 0 + decl (%r12) +#else + decl MUTEX(%r12) +#endif + jne 10f + +11: +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +# ifdef __PIC__ + cmpl $0, __have_futex_clock_realtime(%rip) +# else + cmpl $0, __have_futex_clock_realtime +# endif + je .Lreltmo +#endif + + movl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, %esi + xorl PSHARED(%r12), %esi + movq %r13, %r10 + movl $0xffffffff, %r9d +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME + movl %r14d, %edx +#endif +21: leaq WRITERS_WAKEUP(%r12), %rdi + movl $SYS_futex, %eax + syscall + movq %rax, %rdx + +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME + .subsection 2 +.Lreltmo: + /* Get current time. */ + movq %rsp, %rdi + xorl %esi, %esi + movq $VSYSCALL_ADDR_vgettimeofday, %rax + callq *%rax + + /* Compute relative timeout. */ + movq 8(%rsp), %rax + movl $1000, %edi + mul %rdi /* Milli seconds to nano seconds. */ + movq (%r13), %rcx + movq 8(%r13), %rdi + subq (%rsp), %rcx + subq %rax, %rdi + jns 15f + addq $1000000000, %rdi + decq %rcx +15: testq %rcx, %rcx + js 16f /* Time is already up. */ + + /* Futex call. */ + movq %rcx, (%rsp) /* Store relative timeout. */ + movq %rdi, 8(%rsp) + +# ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %esi + xorl PSHARED(%r12), %esi +# else +# if FUTEX_WAIT == 0 + movl PSHARED(%r12), %esi +# else + movl $FUTEX_WAIT, %esi + orl PSHARED(%r12), %esi +# endif + xorl %fs:PRIVATE_FUTEX, %esi +# endif + movq %rsp, %r10 + movl %r14d, %edx + + jmp 21b + .previous +#endif + +17: /* Reget the lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %esi, (%r12) +#else + cmpxchgl %esi, MUTEX(%r12) +#endif + jnz 12f + +13: decl WRITERS_QUEUED(%r12) + cmpq $-ETIMEDOUT, %rdx + jne 2b + +18: movl $ETIMEDOUT, %edx + jmp 9f + + +5: xorl %edx, %edx + movl %fs:TID, %eax + movl %eax, WRITER(%r12) +9: LOCK +#if MUTEX == 0 + decl (%r12) +#else + decl MUTEX(%r12) +#endif + jne 6f + +7: movq %rdx, %rax + +#ifndef __ASSUME_PRIVATE_FUTEX + addq $16, %rsp + cfi_adjust_cfa_offset(-16) + popq %r14 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r14) +#endif + popq %r13 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r13) + popq %r12 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r12) + retq + +#ifdef __ASSUME_PRIVATE_FUTEX + cfi_adjust_cfa_offset(16) + cfi_rel_offset(%r12, 8) + cfi_rel_offset(%r13, 0) +#else + cfi_adjust_cfa_offset(40) + cfi_offset(%r12, -16) + cfi_offset(%r13, -24) + cfi_offset(%r14, -32) +#endif +1: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_lock_wait + jmp 2b + +14: cmpl %fs:TID, %eax + jne 3b +20: movl $EDEADLK, %edx + jmp 9b + +6: movl PSHARED(%r12), %esi +#if MUTEX == 0 + movq %r12, %rdi +#else + leal MUTEX(%r12), %rdi +#endif + callq __lll_unlock_wake + jmp 7b + + /* Overflow. */ +4: decl WRITERS_QUEUED(%r12) + movl $EAGAIN, %edx + jmp 9b + +10: movl PSHARED(%r12), %esi +#if MUTEX == 0 + movq %r12, %rdi +#else + leaq MUTEX(%r12), %rdi +#endif + callq __lll_unlock_wake + jmp 11b + +12: movl PSHARED(%r12), %esi +#if MUTEX == 0 + movq %r12, %rdi +#else + leaq MUTEX(%r12), %rdi +#endif + callq __lll_lock_wait + jmp 13b + +16: movq $-ETIMEDOUT, %rdx + jmp 17b + +19: movl $EINVAL, %edx + jmp 9b + cfi_endproc + .size pthread_rwlock_timedwrlock,.-pthread_rwlock_timedwrlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S new file mode 100644 index 000000000..c2741134c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S @@ -0,0 +1,131 @@ +/* Copyright (C) 2002, 2003, 2005, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelrwlock.h> +#include <bits/kernel-features.h> + + + .text + + .globl __pthread_rwlock_unlock + .type __pthread_rwlock_unlock,@function + .hidden __pthread_rwlock_unlock + .align 16 +__pthread_rwlock_unlock: + cfi_startproc + /* Get the lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, MUTEX(%rdi) +#endif + jnz 1f + +2: cmpl $0, WRITER(%rdi) + jne 5f + decl NR_READERS(%rdi) + jnz 6f + +5: movl $0, WRITER(%rdi) + + movl $1, %edx + leaq WRITERS_WAKEUP(%rdi), %r10 + cmpl $0, WRITERS_QUEUED(%rdi) + jne 0f + + /* If also no readers waiting nothing to do. */ + cmpl $0, READERS_QUEUED(%rdi) + je 6f + + movl $0x7fffffff, %edx + leaq READERS_WAKEUP(%rdi), %r10 + +0: incl (%r10) + LOCK +#if MUTEX == 0 + decl (%rdi) +#else + decl MUTEX(%rdi) +#endif + jne 7f + +8: +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_PRIVATE_FLAG|FUTEX_WAKE, %esi + xorl PSHARED(%rdi), %esi +#else + movl $FUTEX_WAKE, %esi + orl PSHARED(%rdi), %esi + xorl %fs:PRIVATE_FUTEX, %esi +#endif + movl $SYS_futex, %eax + movq %r10, %rdi + syscall + + xorl %eax, %eax + retq + + .align 16 +6: LOCK +#if MUTEX == 0 + decl (%rdi) +#else + decl MUTEX(%rdi) +#endif + jne 3f + +4: xorl %eax, %eax + retq + +1: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_lock_wait +#if MUTEX != 0 + subq $MUTEX, %rdi +#endif + jmp 2b + +3: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_unlock_wake + jmp 4b + +7: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_unlock_wake + jmp 8b + cfi_endproc + .size __pthread_rwlock_unlock,.-__pthread_rwlock_unlock + + .globl pthread_rwlock_unlock +pthread_rwlock_unlock = __pthread_rwlock_unlock + + .globl __pthread_rwlock_unlock_internal +__pthread_rwlock_unlock_internal = __pthread_rwlock_unlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S new file mode 100644 index 000000000..182745ed9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S @@ -0,0 +1,168 @@ +/* Copyright (C) 2002, 2003, 2005, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <bits/kernel-features.h> +#include <tcb-offsets.h> + + + .text + + .globl __pthread_rwlock_wrlock + .type __pthread_rwlock_wrlock,@function + .hidden __pthread_rwlock_wrlock + .align 16 +__pthread_rwlock_wrlock: + cfi_startproc + xorq %r10, %r10 + + /* Get the lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, MUTEX(%rdi) +#endif + jnz 1f + +2: movl WRITER(%rdi), %eax + testl %eax, %eax + jne 14f + cmpl $0, NR_READERS(%rdi) + je 5f + +3: incl WRITERS_QUEUED(%rdi) + je 4f + + movl WRITERS_WAKEUP(%rdi), %edx + + LOCK +#if MUTEX == 0 + decl (%rdi) +#else + decl MUTEX(%rdi) +#endif + jne 10f + +11: +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %esi + xorl PSHARED(%rdi), %esi +#else +# if FUTEX_WAIT == 0 + movl PSHARED(%rdi), %esi +# else + movl $FUTEX_WAIT, %esi + orl PSHARED(%rdi), %esi +# endif + xorl %fs:PRIVATE_FUTEX, %esi +#endif + addq $WRITERS_WAKEUP, %rdi + movl $SYS_futex, %eax + syscall + + subq $WRITERS_WAKEUP, %rdi + + /* Reget the lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, MUTEX(%rdi) +#endif + jnz 12f + +13: decl WRITERS_QUEUED(%rdi) + jmp 2b + +5: xorl %edx, %edx + movl %fs:TID, %eax + movl %eax, WRITER(%rdi) +9: LOCK +#if MUTEX == 0 + decl (%rdi) +#else + decl MUTEX(%rdi) +#endif + jne 6f +7: + + movq %rdx, %rax + retq + +1: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_lock_wait +#if MUTEX != 0 + subq $MUTEX, %rdi +#endif + jmp 2b + +14: cmpl %fs:TID, %eax + jne 3b + movl $EDEADLK, %edx + jmp 9b + +6: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_unlock_wake + jmp 7b + +4: decl WRITERS_QUEUED(%rdi) + movl $EAGAIN, %edx + jmp 9b + +10: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_unlock_wake +#if MUTEX != 0 + subq $MUTEX, %rdi +#endif + jmp 11b + +12: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_lock_wait +#if MUTEX != 0 + subq $MUTEX, %rdi +#endif + jmp 13b + cfi_endproc + .size __pthread_rwlock_wrlock,.-__pthread_rwlock_wrlock + + .globl pthread_rwlock_wrlock +pthread_rwlock_wrlock = __pthread_rwlock_wrlock + + .globl __pthread_rwlock_wrlock_internal +__pthread_rwlock_wrlock_internal = __pthread_rwlock_wrlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_setaffinity.c b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_setaffinity.c new file mode 100644 index 000000000..640d3044f --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_setaffinity.c @@ -0,0 +1,14 @@ +#include <tls.h> + +#define RESET_VGETCPU_CACHE() \ + do { \ + asm volatile ("movl %0, %%fs:%P1\n\t" \ + "movl %0, %%fs:%P2" \ + : \ + : "ir" (0), "i" (offsetof (struct pthread, \ + header.vgetcpu_cache[0])), \ + "i" (offsetof (struct pthread, \ + header.vgetcpu_cache[1]))); \ + } while (0) + +#include "../pthread_setaffinity.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_init.c b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_init.c new file mode 100644 index 000000000..483de8cac --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_init.c @@ -0,0 +1 @@ +#include <sysdeps/x86_64/pthread_spin_init.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_unlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_unlock.S new file mode 100644 index 000000000..e8e2ba262 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_unlock.S @@ -0,0 +1 @@ +#include <sysdeps/x86_64/pthread_spin_unlock.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S new file mode 100644 index 000000000..7af6524fe --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S @@ -0,0 +1,89 @@ +/* Copyright (C) 2002, 2003, 2005, 2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <pthread-errnos.h> +#include <structsem.h> + + + .text + + .globl sem_post + .type sem_post,@function + .align 16 +sem_post: +#if VALUE == 0 + movl (%rdi), %eax +#else + movl VALUE(%rdi), %eax +#endif +0: cmpl $SEM_VALUE_MAX, %eax + je 3f + leal 1(%rax), %esi + LOCK +#if VALUE == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, VALUE(%rdi) +#endif + jnz 0b + + cmpq $0, NWAITERS(%rdi) + je 2f + + movl $SYS_futex, %eax + movl $FUTEX_WAKE, %esi + orl PRIVATE(%rdi), %esi + movl $1, %edx + syscall + + testq %rax, %rax + js 1f + +2: xorl %eax, %eax + retq + +1: +#if USE___THREAD + movl $EINVAL, %eax +#else + callq __errno_location@plt + movl $EINVAL, %edx +#endif + jmp 4f + +3: +#if USE___THREAD + movl $EOVERFLOW, %eax +#else + callq __errno_location@plt + movl $EOVERFLOW, %edx +#endif + +4: +#if USE___THREAD + movq errno@gottpoff(%rip), %rdx + movl %eax, %fs:(%rdx) +#else + movl %edx, (%rax) +#endif + orl $-1, %eax + retq + .size sem_post,.-sem_post diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S new file mode 100644 index 000000000..704a2223a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S @@ -0,0 +1,379 @@ +/* Copyright (C) 2002, 2003, 2005, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <bits/kernel-features.h> +#include <lowlevellock.h> +#include <pthread-errnos.h> +#include <structsem.h> + + +/* For the calculation see asm/vsyscall.h. */ +#define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000 + + .text + + .globl sem_timedwait + .type sem_timedwait,@function + .align 16 +sem_timedwait: +.LSTARTCODE: + cfi_startproc +#if VALUE == 0 + movl (%rdi), %eax +#else + movl VALUE(%rdi), %eax +#endif +2: testl %eax, %eax + je 1f + + leaq -1(%rax), %rdx + LOCK +#if VALUE == 0 + cmpxchgl %edx, (%rdi) +#else + cmpxchgl %edx, VALUE(%rdi) +#endif + jne 2b + + xorl %eax, %eax + retq + + /* Check whether the timeout value is valid. */ +1: cmpq $1000000000, 8(%rsi) + jae 6f + +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +# ifdef __PIC__ + cmpl $0, __have_futex_clock_realtime(%rip) +# else + cmpl $0, __have_futex_clock_realtime +# endif + je .Lreltmo +#endif + + /* This push is only needed to store the sem_t pointer for the + exception handler. */ + pushq %rdi + cfi_adjust_cfa_offset(8) + + movq %rsi, %r10 + + LOCK + addq $1, NWAITERS(%rdi) + +.LcleanupSTART: +13: call __pthread_enable_asynccancel + movl %eax, %r8d + +#if VALUE != 0 + leaq VALUE(%rdi), %rdi +#endif + movl $0xffffffff, %r9d + movl $FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, %esi + orl PRIVATE(%rdi), %esi + movl $SYS_futex, %eax + xorl %edx, %edx + syscall + movq %rax, %r9 +#if VALUE != 0 + leaq -VALUE(%rdi), %rdi +#endif + + xchgq %r8, %rdi + call __pthread_disable_asynccancel +.LcleanupEND: + movq %r8, %rdi + + testq %r9, %r9 + je 11f + cmpq $-EWOULDBLOCK, %r9 + jne 3f + +11: +#if VALUE == 0 + movl (%rdi), %eax +#else + movl VALUE(%rdi), %eax +#endif +14: testl %eax, %eax + je 13b + + leaq -1(%rax), %rcx + LOCK +#if VALUE == 0 + cmpxchgl %ecx, (%rdi) +#else + cmpxchgl %ecx, VALUE(%rdi) +#endif + jne 14b + + xorl %eax, %eax + +15: LOCK + subq $1, NWAITERS(%rdi) + + leaq 8(%rsp), %rsp + cfi_adjust_cfa_offset(-8) + retq + + cfi_adjust_cfa_offset(8) +3: negq %r9 +#if USE___THREAD + movq errno@gottpoff(%rip), %rdx + movl %r9d, %fs:(%rdx) +#else + callq __errno_location@plt + movl %r9d, (%rax) +#endif + + orl $-1, %eax + jmp 15b + + cfi_adjust_cfa_offset(-8) +6: +#if USE___THREAD + movq errno@gottpoff(%rip), %rdx + movl $EINVAL, %fs:(%rdx) +#else + callq __errno_location@plt + movl $EINVAL, (%rax) +#endif + + orl $-1, %eax + + retq + +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +.Lreltmo: + pushq %r12 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r12, 0) + pushq %r13 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r13, 0) + pushq %r14 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r14, 0) + +#ifdef __ASSUME_FUTEX_CLOCK_REALTIME +# define STACKFRAME 8 +#else +# define STACKFRAME 24 +#endif + subq $STACKFRAME, %rsp + cfi_adjust_cfa_offset(STACKFRAME) + + movq %rdi, %r12 + movq %rsi, %r13 + + LOCK + addq $1, NWAITERS(%r12) + +7: xorl %esi, %esi + movq %rsp, %rdi + movq $VSYSCALL_ADDR_vgettimeofday, %rax + callq *%rax + + /* Compute relative timeout. */ + movq 8(%rsp), %rax + movl $1000, %edi + mul %rdi /* Milli seconds to nano seconds. */ + movq (%r13), %rdi + movq 8(%r13), %rsi + subq (%rsp), %rdi + subq %rax, %rsi + jns 5f + addq $1000000000, %rsi + decq %rdi +5: testq %rdi, %rdi + movl $ETIMEDOUT, %r14d + js 36f /* Time is already up. */ + + movq %rdi, (%rsp) /* Store relative timeout. */ + movq %rsi, 8(%rsp) + +.LcleanupSTART2: + call __pthread_enable_asynccancel + movl %eax, 16(%rsp) + + movq %rsp, %r10 +# if VALUE == 0 + movq %r12, %rdi +# else + leaq VALUE(%r12), %rdi +# endif +# if FUTEX_WAIT == 0 + movl PRIVATE(%rdi), %esi +# else + movl $FUTEX_WAIT, %esi + orl PRIVATE(%rdi), %esi +# endif + movl $SYS_futex, %eax + xorl %edx, %edx + syscall + movq %rax, %r14 + + movl 16(%rsp), %edi + call __pthread_disable_asynccancel +.LcleanupEND2: + + testq %r14, %r14 + je 9f + cmpq $-EWOULDBLOCK, %r14 + jne 33f + +9: +# if VALUE == 0 + movl (%r12), %eax +# else + movl VALUE(%r12), %eax +# endif +8: testl %eax, %eax + je 7b + + leaq -1(%rax), %rcx + LOCK +# if VALUE == 0 + cmpxchgl %ecx, (%r12) +# else + cmpxchgl %ecx, VALUE(%r12) +# endif + jne 8b + + xorl %eax, %eax + +45: LOCK + subq $1, NWAITERS(%r12) + + addq $STACKFRAME, %rsp + cfi_adjust_cfa_offset(-STACKFRAME) + popq %r14 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r14) + popq %r13 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r13) + popq %r12 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r12) + retq + + cfi_adjust_cfa_offset(STACKFRAME + 3 * 8) + cfi_rel_offset(%r12, STACKFRAME + 2 * 8) + cfi_rel_offset(%r13, STACKFRAME + 1 * 8) + cfi_rel_offset(%r14, STACKFRAME) +33: negq %r14 +36: +#if USE___THREAD + movq errno@gottpoff(%rip), %rdx + movl %r14d, %fs:(%rdx) +#else + callq __errno_location@plt + movl %r14d, (%rax) +#endif + + orl $-1, %eax + jmp 45b +#endif + cfi_endproc + .size sem_timedwait,.-sem_timedwait + + + .type sem_timedwait_cleanup,@function +sem_timedwait_cleanup: + cfi_startproc + cfi_adjust_cfa_offset(8) + + movq (%rsp), %rdi + LOCK + subq $1, NWAITERS(%rdi) + movq %rax, %rdi +.LcallUR: + call _Unwind_Resume@PLT + hlt +.LENDCODE: + cfi_endproc + .size sem_timedwait_cleanup,.-sem_timedwait_cleanup + + +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME + .type sem_timedwait_cleanup2,@function +sem_timedwait_cleanup2: + cfi_startproc + cfi_adjust_cfa_offset(STACKFRAME + 3 * 8) + cfi_rel_offset(%r12, STACKFRAME + 2 * 8) + cfi_rel_offset(%r13, STACKFRAME + 1 * 8) + cfi_rel_offset(%r14, STACKFRAME) + + LOCK + subq $1, NWAITERS(%r12) + movq %rax, %rdi + movq STACKFRAME(%rsp), %r14 + movq STACKFRAME+8(%rsp), %r13 + movq STACKFRAME+16(%rsp), %r12 +.LcallUR2: + call _Unwind_Resume@PLT + hlt +.LENDCODE2: + cfi_endproc + .size sem_timedwait_cleanup2,.-sem_timedwait_cleanup2 +#endif + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte DW_EH_PE_omit # @LPStart format + .byte DW_EH_PE_omit # @TType format + .byte DW_EH_PE_uleb128 # call-site format + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 sem_timedwait_cleanup-.LSTARTCODE + .uleb128 0 +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME + .uleb128 .LcleanupSTART2-.LSTARTCODE + .uleb128 .LcleanupEND2-.LcleanupSTART2 + .uleb128 sem_timedwait_cleanup2-.LSTARTCODE + .uleb128 0 +#endif + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME + .uleb128 .LcallUR2-.LSTARTCODE + .uleb128 .LENDCODE2-.LcallUR2 + .uleb128 0 + .uleb128 0 +#endif +.Lcstend: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 8 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 8 +DW.ref.__gcc_personality_v0: + .quad __gcc_personality_v0 +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S new file mode 100644 index 000000000..7b7f63ddb --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S @@ -0,0 +1,52 @@ +/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <pthread-errnos.h> + + .text + + .globl sem_trywait + .type sem_trywait,@function + .align 16 +sem_trywait: + movl (%rdi), %eax +2: testl %eax, %eax + jz 1f + + leal -1(%rax), %edx + LOCK + cmpxchgl %edx, (%rdi) + jne 2b + + xorl %eax, %eax + retq + +1: +#if USE___THREAD + movq errno@gottpoff(%rip), %rdx + movl $EAGAIN, %fs:(%rdx) +#else + callq __errno_location@plt + movl $EAGAIN, (%rax) +#endif + orl $-1, %eax + retq + .size sem_trywait,.-sem_trywait diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S new file mode 100644 index 000000000..f6b39bd74 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S @@ -0,0 +1,174 @@ +/* Copyright (C) 2002, 2003, 2005, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <lowlevellock.h> +#include <pthread-errnos.h> +#include <structsem.h> + + + .text + + .globl sem_wait + .type sem_wait,@function + .align 16 +sem_wait: +.LSTARTCODE: + cfi_startproc + +#if VALUE == 0 + movl (%rdi), %eax +#else + movl VALUE(%rdi), %eax +#endif +2: testl %eax, %eax + je 1f + + leal -1(%rax), %edx + LOCK +#if VALUE == 0 + cmpxchgl %edx, (%rdi) +#else + cmpxchgl %edx, VALUE(%rdi) +#endif + jne 2b + + xorl %eax, %eax + retq + + /* This push is only needed to store the sem_t pointer for the + exception handler. */ +1: pushq %rdi + cfi_adjust_cfa_offset(8) + + LOCK + addq $1, NWAITERS(%rdi) + +.LcleanupSTART: +6: call __pthread_enable_asynccancel + movl %eax, %r8d + + xorq %r10, %r10 + movl $SYS_futex, %eax +#if FUTEX_WAIT == 0 + movl PRIVATE(%rdi), %esi +#else + movl $FUTEX_WAIT, %esi + orl PRIVATE(%rdi), %esi +#endif + xorl %edx, %edx + syscall + movq %rax, %rcx + + xchgq %r8, %rdi + call __pthread_disable_asynccancel +.LcleanupEND: + movq %r8, %rdi + + testq %rcx, %rcx + je 3f + cmpq $-EWOULDBLOCK, %rcx + jne 4f + +3: +#if VALUE == 0 + movl (%rdi), %eax +#else + movl VALUE(%rdi), %eax +#endif +5: testl %eax, %eax + je 6b + + leal -1(%rax), %edx + LOCK +#if VALUE == 0 + cmpxchgl %edx, (%rdi) +#else + cmpxchgl %edx, VALUE(%rdi) +#endif + jne 5b + + xorl %eax, %eax + +9: LOCK + subq $1, NWAITERS(%rdi) + + leaq 8(%rsp), %rsp + cfi_adjust_cfa_offset(-8) + + retq + + cfi_adjust_cfa_offset(8) +4: negq %rcx +#if USE___THREAD + movq errno@gottpoff(%rip), %rdx + movl %ecx, %fs:(%rdx) +#else +# error "not supported. %rcx and %rdi must be preserved" + callq __errno_location@plt + movl %ecx, (%rax) +#endif + orl $-1, %eax + + jmp 9b + .size sem_wait,.-sem_wait + + + .type sem_wait_cleanup,@function +sem_wait_cleanup: + movq (%rsp), %rdi + LOCK + subq $1, NWAITERS(%rdi) + movq %rax, %rdi +.LcallUR: + call _Unwind_Resume@PLT + hlt +.LENDCODE: + cfi_endproc + .size sem_wait_cleanup,.-sem_wait_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte DW_EH_PE_omit # @LPStart format + .byte DW_EH_PE_omit # @TType format + .byte DW_EH_PE_uleb128 # call-site format + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 sem_wait_cleanup-.LSTARTCODE + .uleb128 0 + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +.Lcstend: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 8 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 8 +DW.ref.__gcc_personality_v0: + .quad __gcc_personality_v0 +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h new file mode 100644 index 000000000..1c93952d4 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h @@ -0,0 +1,111 @@ +/* Copyright (C) 2002-2006, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <pthreadP.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +/* The code to disable cancellation depends on the fact that the called + functions are special. They don't modify registers other than %rax + and %r11 if they return. Therefore we don't have to preserve other + registers around these calls. */ +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + jne L(pseudo_cancel); \ + .type __##syscall_name##_nocancel,@function; \ + .globl __##syscall_name##_nocancel; \ + __##syscall_name##_nocancel: \ + DO_CALL (syscall_name, args); \ + cmpq $-4095, %rax; \ + jae SYSCALL_ERROR_LABEL; \ + ret; \ + .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ + L(pseudo_cancel): \ + /* We always have to align the stack before calling a function. */ \ + subq $8, %rsp; cfi_adjust_cfa_offset (8); \ + CENABLE \ + /* The return value from CENABLE is argument for CDISABLE. */ \ + movq %rax, (%rsp); \ + DO_CALL (syscall_name, args); \ + movq (%rsp), %rdi; \ + /* Save %rax since it's the error code from the syscall. */ \ + movq %rax, %rdx; \ + CDISABLE \ + movq %rdx, %rax; \ + addq $8,%rsp; cfi_adjust_cfa_offset (-8); \ + cmpq $-4095, %rax; \ + jae SYSCALL_ERROR_LABEL; \ + L(pseudo_end): + + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel; +# define CDISABLE call __pthread_disable_asynccancel; +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define CENABLE call __libc_enable_asynccancel; +# define CDISABLE call __libc_disable_asynccancel; +# define __local_multiple_threads __libc_multiple_threads +# elif defined IS_IN_librt +# define CENABLE call __librt_enable_asynccancel; +# define CDISABLE call __librt_disable_asynccancel; +# else +# error Unsupported library +# endif + +# if defined IS_IN_libpthread || !defined NOT_IN_libc +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P \ + __builtin_expect (__local_multiple_threads == 0, 1) +# else +# define SINGLE_THREAD_P cmpl $0, __local_multiple_threads(%rip) +# endif + +# else + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P cmpl $0, %fs:MULTIPLE_THREADS_OFFSET +# endif + +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/vfork.S new file mode 100644 index 000000000..9a9912ca8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/vfork.S @@ -0,0 +1,43 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* We want an #include_next, but we are the main source file. + So, #include ourselves and in that incarnation we can use #include_next. */ +#ifndef INCLUDED_SELF +# define INCLUDED_SELF +# include <vfork.S> +#else + +# include <tcb-offsets.h> + +# define SAVE_PID \ + movl %fs:PID, %esi; \ + movl $0x80000000, %ecx; \ + movl %esi, %edx; \ + negl %edx; \ + cmove %ecx, %edx; \ + movl %edx, %fs:PID + +# define RESTORE_PID \ + testq %rax, %rax; \ + je 1f; \ + movl %esi, %fs:PID; \ +1: + +# include_next <vfork.S> +#endif diff --git a/libpthread/nptl/sysdeps/x86_64/Makefile.arch b/libpthread/nptl/sysdeps/x86_64/Makefile.arch new file mode 100644 index 000000000..8ba9e9ed4 --- /dev/null +++ b/libpthread/nptl/sysdeps/x86_64/Makefile.arch @@ -0,0 +1,53 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_CSRC = pthread_spin_lock.c +libpthread_SSRC = pthread_spin_trylock.S + +CFLAGS-pthread_spin_lock.c += -D_GNU_SOURCE + +CFLAGS-x86_64 = $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +PTHREAD_ARCH_DIR := $(top_srcdir)libpthread/nptl/sysdeps/x86_64 +PTHREAD_ARCH_OUT := $(top_builddir)libpthread/nptl/sysdeps/x86_64 +PTHREAD_ARCH_OBJ := $(patsubst %.S,$(PTHREAD_ARCH_OUT)/%.o,$(libpthread_SSRC)) +PTHREAD_ARCH_OBJ += $(patsubst %.c,$(PTHREAD_ARCH_OUT)/%.o,$(libpthread_CSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(PTHREAD_ARCH_OBJ:.o=.os) +else +libpthread-a-y += $(PTHREAD_ARCH_OBJ) +endif +libpthread-so-y += $(PTHREAD_ARCH_OBJ:.o=.oS) + +libpthread-nomulti-y += $(PTHREAD_ARCH_OBJ) + +objclean-y += nptl_arch_clean +headers_clean-y += nptl_arch_headers_clean + +# +# Create 'tcb-offsets.h' header file. +# +CFLAGS-tcb-offsets.c = -S + +$(PTHREAD_ARCH_OUT)/tcb-offsets.c: $(PTHREAD_ARCH_DIR)/tcb-offsets.sym + $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ + +$(PTHREAD_ARCH_OUT)/tcb-offsets.s: $(PTHREAD_ARCH_OUT)/tcb-offsets.c + $(compile.c) + +$(PTHREAD_ARCH_OUT)/tcb-offsets.h: $(PTHREAD_ARCH_OUT)/tcb-offsets.s + $(do_sed) -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*$\/#define \1 \2/p" $< > $@ + +pregen-headers-$(UCLIBC_HAS_THREADS_NATIVE) += $(PTHREAD_ARCH_OUT)/tcb-offsets.h + +nptl_arch_headers_clean: + $(do_rm) $(addprefix $(PTHREAD_ARCH_OUT)/tcb-offsets., c s h) + +nptl_arch_clean: + $(do_rm) $(addprefix $(PTHREAD_ARCH_OUT)/*., o os oS) diff --git a/libpthread/nptl/sysdeps/x86_64/dl-tls.h b/libpthread/nptl/sysdeps/x86_64/dl-tls.h new file mode 100644 index 000000000..3e4768dc1 --- /dev/null +++ b/libpthread/nptl/sysdeps/x86_64/dl-tls.h @@ -0,0 +1,29 @@ +/* Thread-local storage handling in the ELF dynamic linker. x86-64 version. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + + +extern void *__tls_get_addr (tls_index *ti); diff --git a/libpthread/nptl/sysdeps/x86_64/jmpbuf-unwind.h b/libpthread/nptl/sysdeps/x86_64/jmpbuf-unwind.h new file mode 100644 index 000000000..345ed557c --- /dev/null +++ b/libpthread/nptl/sysdeps/x86_64/jmpbuf-unwind.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 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 <setjmp.h> +#include <stdint.h> +#include <unwind.h> + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ + _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ + ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_RSP] - (_adj)) + +/* We use the normal lobngjmp for unwinding. */ +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/libpthread/nptl/sysdeps/x86_64/pthread_spin_init.c b/libpthread/nptl/sysdeps/x86_64/pthread_spin_init.c new file mode 100644 index 000000000..55696204c --- /dev/null +++ b/libpthread/nptl/sysdeps/x86_64/pthread_spin_init.c @@ -0,0 +1 @@ +#include "../i386/pthread_spin_init.c" diff --git a/libpthread/nptl/sysdeps/x86_64/pthread_spin_lock.c b/libpthread/nptl/sysdeps/x86_64/pthread_spin_lock.c new file mode 100644 index 000000000..7cf0e0ecc --- /dev/null +++ b/libpthread/nptl/sysdeps/x86_64/pthread_spin_lock.c @@ -0,0 +1 @@ +#include "../i386/pthread_spin_lock.c" diff --git a/libpthread/nptl/sysdeps/x86_64/pthread_spin_trylock.S b/libpthread/nptl/sysdeps/x86_64/pthread_spin_trylock.S new file mode 100644 index 000000000..9b5133583 --- /dev/null +++ b/libpthread/nptl/sysdeps/x86_64/pthread_spin_trylock.S @@ -0,0 +1,40 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthread-errnos.h> + + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + + .globl pthread_spin_trylock + .type pthread_spin_trylock,@function + .align 16 +pthread_spin_trylock: + movl $1, %eax + xorl %ecx, %ecx + LOCK + cmpxchgl %ecx, (%rdi) + movl $EBUSY, %eax + cmovel %ecx, %eax + retq + .size pthread_spin_trylock,.-pthread_spin_trylock diff --git a/libpthread/nptl/sysdeps/x86_64/pthread_spin_unlock.S b/libpthread/nptl/sysdeps/x86_64/pthread_spin_unlock.S new file mode 100644 index 000000000..d3e13bde9 --- /dev/null +++ b/libpthread/nptl/sysdeps/x86_64/pthread_spin_unlock.S @@ -0,0 +1,31 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + .globl pthread_spin_unlock + .type pthread_spin_unlock,@function + .align 16 +pthread_spin_unlock: + movl $1, (%rdi) + xorl %eax, %eax + retq + .size pthread_spin_unlock,.-pthread_spin_unlock + + /* The implementation of pthread_spin_init is identical. */ + .globl pthread_spin_init +pthread_spin_init = pthread_spin_unlock diff --git a/libpthread/nptl/sysdeps/x86_64/pthreaddef.h b/libpthread/nptl/sysdeps/x86_64/pthreaddef.h new file mode 100644 index 000000000..b33c18638 --- /dev/null +++ b/libpthread/nptl/sysdeps/x86_64/pthreaddef.h @@ -0,0 +1,43 @@ +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. SSE requires 16 + bytes. */ +#define STACK_ALIGN 16 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 2048 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 16 + + +/* Location of current stack frame. The frame pointer is not usable. */ +#define CURRENT_STACK_FRAME \ + ({ char *frame; __asm__ ("movq %%rsp, %0" : "=r" (frame)); frame; }) + + +/* XXX Until we have a better place keep the definitions here. */ + +/* While there is no such syscall. */ +#define __exit_thread_inline(val) \ + __asm__ volatile ("syscall" :: "a" (__NR_exit), "D" (val)) diff --git a/libpthread/nptl/sysdeps/x86_64/tcb-offsets.sym b/libpthread/nptl/sysdeps/x86_64/tcb-offsets.sym new file mode 100644 index 000000000..cf863752e --- /dev/null +++ b/libpthread/nptl/sysdeps/x86_64/tcb-offsets.sym @@ -0,0 +1,28 @@ +#include <sysdep.h> +#include <tls.h> + +RESULT offsetof (struct pthread, result) +TID offsetof (struct pthread, tid) +PID offsetof (struct pthread, pid) +CANCELHANDLING offsetof (struct pthread, cancelhandling) +CLEANUP_JMP_BUF offsetof (struct pthread, cleanup_jmp_buf) +CLEANUP offsetof (struct pthread, cleanup) +CLEANUP_PREV offsetof (struct _pthread_cleanup_buffer, __prev) +MUTEX_FUTEX offsetof (pthread_mutex_t, __data.__lock) +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) +POINTER_GUARD offsetof (tcbhead_t, pointer_guard) +VGETCPU_CACHE_OFFSET offsetof (tcbhead_t, vgetcpu_cache) +#ifndef __ASSUME_PRIVATE_FUTEX +PRIVATE_FUTEX offsetof (tcbhead_t, private_futex) +#endif +RTLD_SAVESPACE_SSE offsetof (tcbhead_t, rtld_savespace_sse) + +-- Not strictly offsets, but these values are also used in the TCB. +TCB_CANCELSTATE_BITMASK CANCELSTATE_BITMASK +TCB_CANCELTYPE_BITMASK CANCELTYPE_BITMASK +TCB_CANCELING_BITMASK CANCELING_BITMASK +TCB_CANCELED_BITMASK CANCELED_BITMASK +TCB_EXITING_BITMASK EXITING_BITMASK +TCB_CANCEL_RESTMASK CANCEL_RESTMASK +TCB_TERMINATED_BITMASK TERMINATED_BITMASK +TCB_PTHREAD_CANCELED PTHREAD_CANCELED diff --git a/libpthread/nptl/sysdeps/x86_64/tls.h b/libpthread/nptl/sysdeps/x86_64/tls.h new file mode 100644 index 000000000..396ad4213 --- /dev/null +++ b/libpthread/nptl/sysdeps/x86_64/tls.h @@ -0,0 +1,438 @@ +/* Definition for thread-local data handling. nptl/x86_64 version. + Copyright (C) 2002-2007, 2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H 1 + +#ifndef __ASSEMBLER__ +# include <asm/prctl.h> /* For ARCH_SET_FS. */ +# include <stdbool.h> +# include <stddef.h> +# include <stdint.h> +# include <stdlib.h> +# include <sysdep.h> +# include <bits/kernel-features.h> +# include <bits/wordsize.h> +# include <xmmintrin.h> + + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessarily the + thread descriptor used by libpthread. */ + 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; + unsigned long int vgetcpu_cache[2]; +# ifndef __ASSUME_PRIVATE_FUTEX + int private_futex; +# else + int __unused1; +# endif +# if __WORDSIZE == 64 + int rtld_must_xmm_save; +# endif + /* Reservation of some values for the TM ABI. */ + void *__private_tm[5]; +# if __WORDSIZE == 64 + long int __unused2; + /* Have space for the post-AVX register size. */ + __m128 rtld_savespace_sse[8][4]; + + void *__padding[8]; +# endif +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif + + +/* We require TLS support in the tools. */ +#define HAVE_TLS_SUPPORT 1 +#define HAVE___THREAD 1 +#define HAVE_TLS_MODEL_ATTRIBUTE 1 + +/* Signal that TLS support is available. */ +#define USE_TLS 1 + +/* Alignment requirement for the stack. */ +#define STACK_ALIGN 16 + + +#ifndef __ASSEMBLER__ +/* Get system call information. */ +# include <sysdep.h> + + +/* Get the thread descriptor definition. */ +# include <descr.h> + +#ifndef LOCK_PREFIX +# ifdef UP +# define LOCK_PREFIX /* nothing */ +# else +# define LOCK_PREFIX "lock;" +# endif +#endif + +/* This is the size of the initial TCB. Can't be just sizeof (tcbhead_t), + because NPTL getpid, __libc_alloca_cutoff etc. need (almost) the whole + struct pthread even when not linked with -lpthread. */ +# define TLS_INIT_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the TCB. */ +//# define TLS_TCB_ALIGN __alignof__ (struct pthread) +// Normally the above would be correct But we have to store post-AVX +// vector registers in the TCB and we want the storage to be aligned. +// unfortunately there isn't yet a type for these values and hence no +// 32-byte alignment requirement. Make this explicit, for now. +# define TLS_TCB_ALIGN 32 + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtvp) \ + ({ struct pthread *__pd; \ + THREAD_SETMEM (__pd, header.dtv, (dtvp)); }) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + + +/* Macros to load from and store into segment registers. */ +# define TLS_GET_FS() \ + ({ int __seg; __asm__ ("movl %%fs, %0" : "=q" (__seg)); __seg; }) +# define TLS_SET_FS(val) \ + __asm__ ("movl %0, %%fs" :: "q" (val)) + + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. + + We have to make the syscall for both uses of the macro since the + address might be (and probably is) different. */ +# define TLS_INIT_TP(thrdescr, secondcall) \ + ({ void *_thrdescr = (thrdescr); \ + tcbhead_t *_head = _thrdescr; \ + int _result; \ + \ + _head->tcb = _thrdescr; \ + /* For now the thread descriptor is at the same address. */ \ + _head->self = _thrdescr; \ + \ + /* It is a simple syscall to set the %fs value for the thread. */ \ + __asm__ volatile ("syscall" \ + : "=a" (_result) \ + : "0" ((unsigned long int) __NR_arch_prctl), \ + "D" ((unsigned long int) ARCH_SET_FS), \ + "S" (_thrdescr) \ + : "memory", "cc", "r11", "cx"); \ + \ + _result ? "cannot set %fs base address for thread-local storage" : 0; \ + }) + + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ struct pthread *__pd; \ + THREAD_GETMEM (__pd, header.dtv); }) + + +/* Return the thread descriptor for the current thread. + + The contained asm must *not* be marked volatile since otherwise + assignments like + pthread_descr self = thread_self(); + do not get optimized away. */ +# define THREAD_SELF \ + ({ struct pthread *__self; \ + __asm__ ("movq %%fs:%c1,%q0" : "=r" (__self) \ + : "i" (offsetof (struct pthread, header.self))); \ + __self;}) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF_INCLUDE <sys/reg.h> /* For the FS constant. */ +# define DB_THREAD_SELF CONST_THREAD_AREA (64, FS) + +/* Read member of the thread descriptor directly. */ +# define THREAD_GETMEM(descr, member) \ + ({ __typeof (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ volatile ("movb %%fs:%P2,%b0" \ + : "=q" (__value) \ + : "0" (0), "i" (offsetof (struct pthread, member))); \ + else if (sizeof (__value) == 4) \ + __asm__ volatile ("movl %%fs:%P1,%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct pthread, member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ volatile ("movq %%fs:%P1,%q0" \ + : "=r" (__value) \ + : "i" (offsetof (struct pthread, member))); \ + } \ + __value; }) + + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +# define THREAD_GETMEM_NC(descr, member, idx) \ + ({ __typeof (descr->member[0]) __value; \ + if (sizeof (__value) == 1) \ + __asm__ volatile ("movb %%fs:%P2(%q3),%b0" \ + : "=q" (__value) \ + : "0" (0), "i" (offsetof (struct pthread, member[0])), \ + "r" (idx)); \ + else if (sizeof (__value) == 4) \ + __asm__ volatile ("movl %%fs:%P1(,%q2,4),%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct pthread, member[0])), "r" (idx));\ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ volatile ("movq %%fs:%P1(,%q2,8),%q0" \ + : "=r" (__value) \ + : "i" (offsetof (struct pthread, member[0])), \ + "r" (idx)); \ + } \ + __value; }) + + +/* Loading addresses of objects on x86-64 needs to be treated special + when generating PIC code. */ +#ifdef __pic__ +# define IMM_MODE "nr" +#else +# define IMM_MODE "ir" +#endif + + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +# define THREAD_SETMEM(descr, member, value) \ + ({ if (sizeof (descr->member) == 1) \ + __asm__ volatile ("movb %b0,%%fs:%P1" : \ + : "iq" (value), \ + "i" (offsetof (struct pthread, member))); \ + else if (sizeof (descr->member) == 4) \ + __asm__ volatile ("movl %0,%%fs:%P1" : \ + : IMM_MODE (value), \ + "i" (offsetof (struct pthread, member))); \ + else \ + { \ + if (sizeof (descr->member) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ volatile ("movq %q0,%%fs:%P1" : \ + : IMM_MODE ((unsigned long int) value), \ + "i" (offsetof (struct pthread, member))); \ + }}) + + +/* Set member of the thread descriptor directly. */ +# define THREAD_SETMEM_NC(descr, member, idx, value) \ + ({ if (sizeof (descr->member[0]) == 1) \ + __asm__ volatile ("movb %b0,%%fs:%P1(%q2)" : \ + : "iq" (value), \ + "i" (offsetof (struct pthread, member[0])), \ + "r" (idx)); \ + else if (sizeof (descr->member[0]) == 4) \ + __asm__ volatile ("movl %0,%%fs:%P1(,%q2,4)" : \ + : IMM_MODE (value), \ + "i" (offsetof (struct pthread, member[0])), \ + "r" (idx)); \ + else \ + { \ + if (sizeof (descr->member[0]) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ volatile ("movq %q0,%%fs:%P1(,%q2,8)" : \ + : IMM_MODE ((unsigned long int) value), \ + "i" (offsetof (struct pthread, member[0])), \ + "r" (idx)); \ + }}) + + +/* Atomic compare and exchange on TLS, returning old value. */ +# define THREAD_ATOMIC_CMPXCHG_VAL(descr, member, newval, oldval) \ + ({ __typeof (descr->member) __ret; \ + __typeof (oldval) __old = (oldval); \ + if (sizeof (descr->member) == 4) \ + __asm__ volatile (LOCK_PREFIX "cmpxchgl %2, %%fs:%P3" \ + : "=a" (__ret) \ + : "0" (__old), "r" (newval), \ + "i" (offsetof (struct pthread, member))); \ + else \ + /* Not necessary for other sizes in the moment. */ \ + abort (); \ + __ret; }) + + +/* Atomic logical and. */ +# define THREAD_ATOMIC_AND(descr, member, val) \ + (void) ({ if (sizeof ((descr)->member) == 4) \ + __asm__ volatile (LOCK_PREFIX "andl %1, %%fs:%P0" \ + :: "i" (offsetof (struct pthread, member)), \ + "ir" (val)); \ + else \ + /* Not necessary for other sizes in the moment. */ \ + abort (); }) + + +/* Atomic set bit. */ +# define THREAD_ATOMIC_BIT_SET(descr, member, bit) \ + (void) ({ if (sizeof ((descr)->member) == 4) \ + __asm__ volatile (LOCK_PREFIX "orl %1, %%fs:%P0" \ + :: "i" (offsetof (struct pthread, member)), \ + "ir" (1 << (bit))); \ + else \ + /* Not necessary for other sizes in the moment. */ \ + abort (); }) + + +# define CALL_THREAD_FCT(descr) \ + ({ void *__res; \ + __asm__ volatile ("movq %%fs:%P2, %%rdi\n\t" \ + "callq *%%fs:%P1" \ + : "=a" (__res) \ + : "i" (offsetof (struct pthread, start_routine)), \ + "i" (offsetof (struct pthread, arg)) \ + : "di", "si", "cx", "dx", "r8", "r9", "r10", "r11", \ + "memory", "cc"); \ + __res; }) + + +/* Set the stack guard field in TCB head. */ +# define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.stack_guard, value) +# define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->header.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, header.stack_guard)) + + +/* Set the pointer guard field in the TCB head. */ +# define THREAD_SET_POINTER_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.pointer_guard, value) +# define THREAD_COPY_POINTER_GUARD(descr) \ + ((descr)->header.pointer_guard \ + = 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, LLL_PRIVATE); \ + } \ + 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) () + + +# ifdef SHARED +/* Defined in dl-trampoline.S. */ +extern void _dl_x86_64_save_sse (void); +extern void _dl_x86_64_restore_sse (void); + +# define RTLD_CHECK_FOREIGN_CALL \ + (THREAD_GETMEM (THREAD_SELF, header.rtld_must_xmm_save) != 0) + +/* NB: Don't use the xchg operation because that would imply a lock + prefix which is expensive and unnecessary. The cache line is also + not contested at all. */ +# define RTLD_ENABLE_FOREIGN_CALL \ + int old_rtld_must_xmm_save = THREAD_GETMEM (THREAD_SELF, \ + header.rtld_must_xmm_save); \ + THREAD_SETMEM (THREAD_SELF, header.rtld_must_xmm_save, 1) + +# define RTLD_PREPARE_FOREIGN_CALL \ + do if (THREAD_GETMEM (THREAD_SELF, header.rtld_must_xmm_save)) \ + { \ + _dl_x86_64_save_sse (); \ + THREAD_SETMEM (THREAD_SELF, header.rtld_must_xmm_save, 0); \ + } \ + while (0) + +# define RTLD_FINALIZE_FOREIGN_CALL \ + do { \ + if (THREAD_GETMEM (THREAD_SELF, header.rtld_must_xmm_save) == 0) \ + _dl_x86_64_restore_sse (); \ + THREAD_SETMEM (THREAD_SELF, header.rtld_must_xmm_save, \ + old_rtld_must_xmm_save); \ + } while (0) +# endif + + +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/libpthread/nptl/unwind.c b/libpthread/nptl/unwind.c new file mode 100644 index 000000000..d1f824121 --- /dev/null +++ b/libpthread/nptl/unwind.c @@ -0,0 +1,177 @@ +/* Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com> + and Richard Henderson <rth@redhat.com>, 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 <setjmp.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "pthreadP.h" +#include <jmpbuf-unwind.h> + +#ifdef HAVE_FORCED_UNWIND + +#ifdef _STACK_GROWS_DOWN +# define FRAME_LEFT(frame, other, adj) \ + ((uintptr_t) frame - adj >= (uintptr_t) other - adj) +#elif _STACK_GROWS_UP +# define FRAME_LEFT(frame, other, adj) \ + ((uintptr_t) frame - adj <= (uintptr_t) other - adj) +#else +# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +#endif + +static _Unwind_Reason_Code +unwind_stop (int version, _Unwind_Action actions, + _Unwind_Exception_Class exc_class, + struct _Unwind_Exception *exc_obj, + struct _Unwind_Context *context, void *stop_parameter) +{ + struct pthread_unwind_buf *buf = stop_parameter; + struct pthread *self = THREAD_SELF; + struct _pthread_cleanup_buffer *curp = THREAD_GETMEM (self, cleanup); + int do_longjump = 0; + + /* Adjust all pointers used in comparisons, so that top of thread's + stack is at the top of address space. Without that, things break + if stack is allocated above the main stack. */ + uintptr_t adj = (uintptr_t) self->stackblock + self->stackblock_size; + + /* Do longjmp if we're at "end of stack", aka "end of unwind data". + We assume there are only C frame without unwind data in between + here and the jmp_buf target. Otherwise simply note that the CFA + of a function is NOT within it's stack frame; it's the SP of the + previous frame. */ + if ((actions & _UA_END_OF_STACK) + || ! _JMPBUF_CFA_UNWINDS_ADJ (buf->cancel_jmp_buf[0].jmp_buf, context, + adj)) + do_longjump = 1; + + if (__builtin_expect (curp != NULL, 0)) + { + /* Handle the compatibility stuff. Execute all handlers + registered with the old method which would be unwound by this + step. */ + struct _pthread_cleanup_buffer *oldp = buf->priv.data.cleanup; + void *cfa = (void *) _Unwind_GetCFA (context); + + if (curp != oldp && (do_longjump || FRAME_LEFT (cfa, curp, adj))) + { + do + { + /* Pointer to the next element. */ + struct _pthread_cleanup_buffer *nextp = curp->__prev; + + /* Call the handler. */ + curp->__routine (curp->__arg); + + /* To the next. */ + curp = nextp; + } + while (curp != oldp + && (do_longjump || FRAME_LEFT (cfa, curp, adj))); + + /* Mark the current element as handled. */ + THREAD_SETMEM (self, cleanup, curp); + } + } + + if (do_longjump) + __libc_unwind_longjmp ((struct __jmp_buf_tag *) buf->cancel_jmp_buf, 1); + + return _URC_NO_REASON; +} + + +static void +unwind_cleanup (_Unwind_Reason_Code reason, struct _Unwind_Exception *exc) +{ + /* When we get here a C++ catch block didn't rethrow the object. We + cannot handle this case and therefore abort. */ +# define STR_N_LEN(str) str, strlen (str) + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (write, err, 3, STDERR_FILENO, + STR_N_LEN ("FATAL: exception not rethrown\n")); + abort (); +} + +#endif /* have forced unwind */ + + +void +attribute_hidden +__cleanup_fct_attribute __attribute ((noreturn)) +__pthread_unwind (__pthread_unwind_buf_t *buf) +{ + struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf; + struct pthread *self = THREAD_SELF; + +#ifdef HAVE_FORCED_UNWIND + /* This is not a catchable exception, so don't provide any details about + the exception type. We do need to initialize the field though. */ + THREAD_SETMEM (self, exc.exception_class, 0); + THREAD_SETMEM (self, exc.exception_cleanup, unwind_cleanup); + + _Unwind_ForcedUnwind (&self->exc, unwind_stop, ibuf); +#else + /* Handle the compatibility stuff first. Execute all handlers + registered with the old method. We don't execute them in order, + instead, they will run first. */ + struct _pthread_cleanup_buffer *oldp = ibuf->priv.data.cleanup; + struct _pthread_cleanup_buffer *curp = THREAD_GETMEM (self, cleanup); + + if (curp != oldp) + { + do + { + /* Pointer to the next element. */ + struct _pthread_cleanup_buffer *nextp = curp->__prev; + + /* Call the handler. */ + curp->__routine (curp->__arg); + + /* To the next. */ + curp = nextp; + } + while (curp != oldp); + + /* Mark the current element as handled. */ + THREAD_SETMEM (self, cleanup, curp); + } + + /* We simply jump to the registered setjmp buffer. */ + __libc_unwind_longjmp ((struct __jmp_buf_tag *) ibuf->cancel_jmp_buf, 1); +#endif + /* NOTREACHED */ + + /* We better do not get here. */ + abort (); +} +hidden_def (__pthread_unwind) + + +void +__cleanup_fct_attribute __attribute ((noreturn)) +__pthread_unwind_next (__pthread_unwind_buf_t *buf) +{ + struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf; + + __pthread_unwind ((__pthread_unwind_buf_t *) ibuf->priv.data.prev); +} +hidden_def (__pthread_unwind_next) diff --git a/libpthread/nptl/vars.c b/libpthread/nptl/vars.c new file mode 100644 index 000000000..1e1a3cf5b --- /dev/null +++ b/libpthread/nptl/vars.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthreadP.h> +#include <stdlib.h> +#include <tls.h> +#include <unistd.h> + +/* Default stack size. */ +size_t __default_stacksize attribute_hidden +#ifdef SHARED +; +#else + = PTHREAD_STACK_MIN; +#endif + +/* Flag whether the machine is SMP or not. */ +int __is_smp attribute_hidden; + +#ifndef TLS_MULTIPLE_THREADS_IN_TCB +/* Variable set to a nonzero value if more than one thread runs or ran. */ +int __pthread_multiple_threads attribute_hidden; +#endif + +/* Table of the key information. */ +struct pthread_key_struct __pthread_keys[PTHREAD_KEYS_MAX] + __attribute__ ((nocommon)); +hidden_data_def (__pthread_keys) diff --git a/libpthread/nptl/version.c b/libpthread/nptl/version.c new file mode 100644 index 000000000..b69556e94 --- /dev/null +++ b/libpthread/nptl/version.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <unistd.h> +#include <sysdep.h> + + +static const char banner[] = +#include "banner.h" +"Copyright (C) 2006 Free Software Foundation, Inc.\n\ +This is free software; see the source for copying conditions.\n\ +There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n\ +PARTICULAR PURPOSE.\n" +#ifdef HAVE_FORCED_UNWIND +"Forced unwind support included.\n" +#endif +; + + +extern void __nptl_main (void) __attribute__ ((noreturn)); +void +__nptl_main (void) +{ + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (write, err, 3, STDOUT_FILENO, (const char *) banner, + sizeof banner - 1); + + _exit (0); +} diff --git a/libpthread/nptl/version.h b/libpthread/nptl/version.h new file mode 100644 index 000000000..f294f5c97 --- /dev/null +++ b/libpthread/nptl/version.h @@ -0,0 +1 @@ +#define VERSION __stringify(__UCLIBC_MAJOR__) "." __stringify(__UCLIBC_MINOR__) "." __stringify(__UCLIBC_SUBLEVEL__) diff --git a/libpthread/nptl_db/ChangeLog b/libpthread/nptl_db/ChangeLog new file mode 100644 index 000000000..52c849138 --- /dev/null +++ b/libpthread/nptl_db/ChangeLog @@ -0,0 +1,207 @@ +2004-09-09 Roland McGrath <roland@redhat.com> + + * td_ta_map_lwp2thr.c (td_ta_map_lwp2thr): Don't abort if inferior's + descriptor is bogus. + +2004-05-27 Roland McGrath <roland@redhat.com> + + * td_thr_validate.c: When we find no threads and the inferior appears + uninitialized, validate the main thread as a special case. + +2004-05-01 Jakub Jelinek <jakub@redhat.com> + + * thread_dbP.h (LOG): Use write instead of __libc_write. + +2004-04-03 Ulrich Drepper <drepper@redhat.com> + + * td_ta_set_event.c (td_ta_set_event): Initialize copy to avoid + warnings. + + * td_ta_thr_iter.c (td_ta_thr_iter): Initialize list to avoid warning. + * td_ta_clear_event.c (td_ta_clear_event): Initialize eventmask to + avoid warning. + * td_ta_set_event.c (td_ta_set_event): Likewise. + +2004-03-24 Roland McGrath <roland@redhat.com> + + * fetch-value.c (_td_locate_field): Cast DB_DESC_OFFSET to int32_t. + * thread_dbP.h (DB_DESC_OFFSET): Remove cast from definition. + +2004-03-13 Jakub Jelinek <jakub@redhat.com> + + * db_info.c: Don't use TLS_TP_OFFSET in the #if, but + TLS_TCB_SIZE == 0 ?: in the DESC macro. + +2004-03-12 Roland McGrath <roland@redhat.com> + + * db_info.c [TLS_DTV_AT_TP && TLS_TP_OFFSET > 0] + (_thread_db_pthread_dtvp): Define differently for this case (PowerPC). + +2003-12-11 Ulrich Weigand <uweigand@de.ibm.com> + + * db_info.c (REGISTER): Add bit size of thread register as second + parameter to REGISTER macro. + +2003-12-02 Roland McGrath <roland@redhat.com> + + * thread_dbP.h (DB_FUNCTION): New macro. + * structs.def: Use it for __nptl_create_event and __nptl_death_event. + * db_info.c (DB_FUNCTION): New macro. + * td_symbol_list.c (DB_FUNCTION): New macro, prepend "." to symbol + name under [HAVE_ASM_GLOBAL_DOT_NAME]. + (td_lookup) [HAVE_ASM_GLOBAL_DOT_NAME]: If lookup fails with PS_NOSYM + and name starts with a dot, try it without the dot. + +2003-09-08 Roland McGrath <roland@redhat.com> + + * td_thr_get_info.c (td_thr_get_info): Cast th_unique to thread_t. + +2003-08-22 Roland McGrath <roland@redhat.com> + + * fetch-value.c (_td_check_sizeof, _td_locate_field): Return + TD_NOCAPAB for PS_NOSYM, instead of vanilla TD_ERR. + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Return TD_NOAPLIC when + DB_GET_FIELD returns TD_NOCAPAB. + + * thread_db.h (td_thr_tls_get_addr): Use psaddr_t in signature. + * structs.def [USE_TLS]: Add DB_STRUCT_FIELD (link_map, l_tls_modid). + * db_info.c (link_map): Typedef it. + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Rewritten. + +2003-08-14 Roland McGrath <roland@redhat.com> + + * thread_dbP.h: Mostly rewritten with many new macros and decls. + * td_ta_new.c (td_ta_new): Don't cache a lot of symbol values. + * structs.def: New file. + * db_info.c: New file. + * td_symbol_list.c (symbol_list_arr): Define with structs.def macros. + * td_ta_clear_event.c: Rewritten. + * td_ta_event_addr.c: Rewritten. + * td_ta_event_getmsg.c: Rewritten. + * td_ta_get_nthreads.c: Rewritten. + * td_ta_map_lwp2thr.c: New file. + * td_ta_set_event.c: Rewritten. + * td_ta_thr_iter.c: Rewritten. + * td_ta_tsd_iter.c: Rewritten. + * td_thr_clear_event.c: Rewritten. + * td_thr_event_enable.c: Rewritten. + * td_thr_event_getmsg.c: Rewritten. + * td_thr_get_info.c: Rewritten. + * td_thr_getfpregs.c: Rewritten. + * td_thr_getgregs.c: Rewritten. + * td_thr_set_event.c: Rewritten. + * td_thr_setfpregs.c: Rewritten. + * td_thr_setgregs.c: Rewritten. + * td_thr_tlsbase.c: Rewritten. + * td_thr_tsd.c: Rewritten. + * td_thr_validate.c: Rewritten. + * Makefile (distribute): Add them. + * fetch-value.c: New file. + * Makefile (libthread_db-routines): Add it. + + * thread_db.h (td_err_e): Comment fix. + +2003-08-05 Roland McGrath <roland@redhat.com> + + * thread_dbP.h (td_lookup): Add attribute_hidden to decl. + +2003-08-04 Roland McGrath <roland@redhat.com> + + * td_ta_clear_event.c (td_ta_clear_event): Fix sizes in ps_* calls. + +2003-06-23 Roland McGrath <roland@redhat.com> + + * proc_service.h: Cosmetic and comment fixes. + +2003-06-19 Roland McGrath <roland@redhat.com> + + * td_thr_event_enable.c (td_thr_event_enable): Use proper type `bool' + for value written into inferior's `report_events'. + +2003-03-18 Roland McGrath <roland@redhat.com> + + * td_thr_event_getmsg.c (td_thr_event_getmsg): Splice the thread out + of the ->nextevent linkage. + + * td_ta_event_getmsg.c (td_ta_event_getmsg): Runtime error instead of + assert for reading TD_EVENT_NONE. Clear the event buffer after + reading it. Add a sanity check for foo->nextevent = foo. + +2003-03-15 Roland McGrath <roland@redhat.com> + + * thread_db.h (td_err_e): Add TD_NOTLS and TD_TLSDEFER. + (td_thr_tlsbase): Declare it. + * td_thr_tlsbase.c: New file. + * Makefile (libthread_db-routines): Add it. + * Versions (libthread_db: GLIBC_2.3.3): New set, add td_thr_tlsbase. + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Use td_thr_tlsbase. + +2003-03-14 Roland McGrath <roland@redhat.com> + + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Use `header.' prefix. + +2003-03-10 Roland McGrath <roland@redhat.com> + + * td_ta_thr_iter.c (iterate_thread_list): Don't use `header.data.' + prefix for `struct pthread' members. + * td_thr_validate.c (check_thread_list): Likewise. + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Likewise. + +2003-03-03 Roland McGrath <roland@redhat.com> + + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Handle TLS_DTV_AT_TP. + +2003-02-15 Ulrich Drepper <drepper@redhat.com> + + * td_symbol_list.c: New symbol name for SYM_PTHREAD_NTHREADS. + +2003-01-07 Jakub Jelinek <jakub@redhat.com> + + * td_ta_event_getmsg.c: Include assert.h. + +-2003-01-05 Ulrich Drepper <drepper@redhat.com> + + * Makefile (libthread_db.so-no-z-defs): Define. + +2003-01-03 Roland McGrath <roland@redhat.com> + + * td_thr_setgregs.c (td_thr_setgregs): *_BIT -> *_BITMASK + * td_thr_setfpregs.c (td_thr_setfpregs): Likewise. + * td_thr_get_info.c (td_thr_get_info): Likewise. + * td_thr_getgregs.c (td_thr_getgregs): Likewise. + * td_thr_getfpregs.c (td_thr_getfpregs): Likewise. + * td_ta_thr_iter.c (iterate_thread_list): Likewise. + +2002-12-12 Roland McGrath <roland@redhat.com> + + * td_ta_thr_iter.c (iterate_thread_list): Handle special case of + uninitialized __stack_user (zeros), hard-wire just the main thread. + + * td_thr_get_info.c (td_thr_get_info): Fix ti_lid initialization. + +2002-12-06 Roland McGrath <roland@redhat.com> + + * td_ta_event_getmsg.c (td_ta_event_getmsg): Write the NEXT pointer + into the inferior's __pthread_last_event variable, not a word from + an inferior address used in the parent. Pass the address of a + null word to ps_pdwrite, not a null pointer. + +2002-12-04 Roland McGrath <roland@redhat.com> + + * td_thr_get_info.c (td_thr_get_info): ti_tid is pthread_t, not a PID. + + * thread_db.h (td_thrinfo_t): Comment fix. + + * td_ta_map_lwp2thr.c: Moved to ../nptl/sysdeps/i386/. + +2002-12-04 Ulrich Drepper <drepper@redhat.com> + + * td_ta_thr_iter.c (iterate_thread_list): At end of iteration read + pointer to the next element from inferior. + +2002-12-02 Roland McGrath <roland@redhat.com> + + * td_symbol_list.c (symbol_list_arr): pthread_keys -> __pthread_keys + + * td_ta_map_lwp2thr.c (td_ta_map_lwp2thr): Fetch inferior registers to + see its %gs value, not our own. diff --git a/libpthread/nptl_db/Makefile b/libpthread/nptl_db/Makefile new file mode 100644 index 000000000..f9100219a --- /dev/null +++ b/libpthread/nptl_db/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/libpthread/nptl_db/Makefile.in b/libpthread/nptl_db/Makefile.in new file mode 100644 index 000000000..3eaded59f --- /dev/null +++ b/libpthread/nptl_db/Makefile.in @@ -0,0 +1,71 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libpthread/nptl/nptl_db + +# Get the thread include dependencies and shared object name +CFLAGS-nptl_db := -DLIBPTHREAD_SO="\"libpthread.so.$(MAJOR_VERSION)\"" +CFLAGS-nptl_db += -I$(top_srcdir)libpthread/nptl -D_GNU_SOURCE +CFLAGS-nptl_db += -DIS_IN_libthread_db=1 -std=gnu99 -I$(top_srcdir)ldso/include + +LDFLAGS-libthread_db.so := $(LDFLAGS_NOSTRIP) -s --warn-unresolved-symbols + +LIBS-libthread_db.so := $(LIBS) + +libthread_db_FULL_NAME := libthread_db-$(VERSION).so + +libthread_db_DIR := $(top_srcdir)libpthread/nptl_db +libthread_db_OUT := $(top_builddir)libpthread/nptl_db + +libthread_db_SRC := $(wildcard $(libthread_db_DIR)/td_*.c) \ + $(libthread_db_DIR)/fetch-value.c + +libthread_db_OBJ := $(patsubst $(libthread_db_DIR)/%.c,$(libthread_db_OUT)/%.o,$(libthread_db_SRC)) + +libthread_db-so-y := $(libthread_db_OBJ:.o=.oS) +ifeq ($(DOPIC),y) +libthread_db-a-y := $(libthread_db-so-y) +else +libthread_db-a-y := $(libthread_db_OBJ) +endif + +libthread_db-multi-y := $(libthread_db_SRC) + +lib-a-$(PTHREADS_DEBUG_SUPPORT) += $(top_builddir)lib/libthread_db.a +lib-so-$(PTHREADS_DEBUG_SUPPORT) += $(top_builddir)lib/libthread_db.so +objclean-y += libthread_db_clean +headers-$(PTHREADS_DEBUG_SUPPORT) += $(nptl_db_headers) +headers_clean-y += nptl_db_headers_clean + +ifeq ($(DOPIC),y) +$(top_builddir)lib/libthread_db.so: $(top_builddir)lib/libthread_db.a $(libc) +else +$(top_builddir)lib/libthread_db.so: $(libthread_db_OUT)/libthread_db_so.a $(libc) +endif + $(call link.so,$(libthread_db_FULL_NAME),1) + +$(libthread_db_OUT)/libthread_db_so.a: $(libthread_db-so-y) + $(Q)$(RM) $@ + $(do_strip) + $(do_ar) + +$(top_builddir)lib/libthread_db.a: $(libthread_db-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_strip) + $(do_ar) + +$(top_builddir)include/thread_db.h: + $(do_ln) $(call rel_srcdir)$(PTDIR)_db/$(@F) $@ + +nptl_db_headers:= $(top_builddir)include/thread_db.h + +nptl_db_headers_clean: + $(do_rm) $(nptl_db_headers) + +libthread_db_clean: + $(do_rm) $(addprefix $(libthread_db_OUT)/*., o oS a) diff --git a/libpthread/nptl_db/db_info.c b/libpthread/nptl_db/db_info.c new file mode 100644 index 000000000..5aec152d5 --- /dev/null +++ b/libpthread/nptl_db/db_info.c @@ -0,0 +1,103 @@ +/* This file is included by pthread_create.c to define in libpthread + all the magic symbols required by libthread_db. + + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include <tls.h> + +typedef struct pthread pthread; +typedef struct pthread_key_struct pthread_key_struct; +typedef struct pthread_key_data pthread_key_data; +typedef struct +{ + struct pthread_key_data data[PTHREAD_KEY_2NDLEVEL_SIZE]; +} +pthread_key_data_level2; + +typedef struct +{ + union dtv dtv[UINT32_MAX / 2 / sizeof (union dtv)]; /* No constant bound. */ +} dtv; + +typedef struct link_map link_map; + + +#define schedparam_sched_priority schedparam.sched_priority + +#define eventbuf_eventmask eventbuf.eventmask +#define eventbuf_eventmask_event_bits eventbuf.eventmask.event_bits + +#define DESC(name, offset, obj) \ + DB_DEFINE_DESC (name, 8 * sizeof (obj), 1, offset); +#define ARRAY_DESC(name, offset, obj) \ + DB_DEFINE_DESC (name, \ + 8 * sizeof (obj)[0], sizeof (obj) / sizeof (obj)[0], \ + offset); + +#if defined(TLS_TCB_AT_TP) +# define dtvp header.dtv +#elif defined(TLS_DTV_AT_TP) +/* Special case hack. If TLS_TCB_SIZE == 0 (on PowerPC), there is no TCB + containing the DTV at the TP, but actually the TCB lies behind the TP, + i.e. at the very end of the area covered by TLS_PRE_TCB_SIZE. */ +DESC (_thread_db_pthread_dtvp, + TLS_PRE_TCB_SIZE + offsetof (tcbhead_t, dtv) + - (TLS_TCB_SIZE == 0 ? sizeof (tcbhead_t) : 0), union dtv) +#endif + + +#define DB_STRUCT(type) \ + const uint32_t _thread_db_sizeof_##type = sizeof (type); +#define DB_STRUCT_FIELD(type, field) \ + DESC (_thread_db_##type##_##field, \ + offsetof (type, field), ((type *) 0)->field) +#define DB_STRUCT_ARRAY_FIELD(type, field) \ + ARRAY_DESC (_thread_db_##type##_##field, \ + offsetof (type, field), ((type *) 0)->field) +#define DB_VARIABLE(name) DESC (_thread_db_##name, 0, name) +#define DB_ARRAY_VARIABLE(name) ARRAY_DESC (_thread_db_##name, 0, name) +#define DB_SYMBOL(name) /* Nothing. */ +#define DB_FUNCTION(name) /* Nothing. */ +#include "structs.def" +#undef DB_STRUCT +#undef DB_STRUCT_FIELD +#undef DB_SYMBOL +#undef DB_FUNCTION +#undef DB_VARIABLE +#undef DESC + + + +#ifdef DB_THREAD_SELF +# ifdef DB_THREAD_SELF_INCLUDE +# include DB_THREAD_SELF_INCLUDE +# endif + +/* This macro is defined in the machine's tls.h using the three below. */ +# define CONST_THREAD_AREA(bits, value) \ + const uint32_t _thread_db_const_thread_area = (value); +# define REGISTER_THREAD_AREA(bits, regofs, scale) \ + DB_DEFINE_DESC (_thread_db_register##bits##_thread_area, \ + bits, (scale), (regofs)); +# define REGISTER(bits, size, regofs, bias) \ + DB_DEFINE_DESC (_thread_db_register##bits, size, (uint32_t)(bias), (regofs)); + +DB_THREAD_SELF +#endif diff --git a/libpthread/nptl_db/fetch-value.c b/libpthread/nptl_db/fetch-value.c new file mode 100644 index 000000000..0d9bb0eb8 --- /dev/null +++ b/libpthread/nptl_db/fetch-value.c @@ -0,0 +1,284 @@ +/* Helper routines for libthread_db. + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include <byteswap.h> +#include <assert.h> + +td_err_e +_td_check_sizeof (td_thragent_t *ta, uint32_t *sizep, int sizep_name) +{ + if (*sizep == 0) + { + psaddr_t descptr; + ps_err_e err = td_lookup (ta->ph, sizep_name, &descptr); + if (err == PS_NOSYM) + return TD_NOCAPAB; + if (err == PS_OK) + err = ps_pdread (ta->ph, descptr, sizep, sizeof *sizep); + if (err != PS_OK) + return TD_ERR; + if (*sizep & 0xff000000U) + *sizep = bswap_32 (*sizep); + } + return TD_OK; +} + +td_err_e +_td_locate_field (td_thragent_t *ta, + db_desc_t desc, int descriptor_name, + psaddr_t idx, psaddr_t *address) +{ + uint32_t elemsize; + + if (DB_DESC_SIZE (desc) == 0) + { + /* Read the information about this field from the inferior. */ + psaddr_t descptr; + ps_err_e err = td_lookup (ta->ph, descriptor_name, &descptr); + if (err == PS_NOSYM) + return TD_NOCAPAB; + if (err == PS_OK) + err = ps_pdread (ta->ph, descptr, desc, DB_SIZEOF_DESC); + if (err != PS_OK) + return TD_ERR; + if (DB_DESC_SIZE (desc) == 0) + return TD_DBERR; + if (DB_DESC_SIZE (desc) & 0xff000000U) + { + /* Byte-swap these words, though we leave the size word + in native order as the handy way to distinguish. */ + DB_DESC_OFFSET (desc) = bswap_32 (DB_DESC_OFFSET (desc)); + DB_DESC_NELEM (desc) = bswap_32 (DB_DESC_NELEM (desc)); + } + } + + if (idx != 0 && idx - (psaddr_t) 0 > DB_DESC_NELEM (desc)) + /* This is an internal indicator to callers with nonzero IDX + that the IDX value is too big. */ + return TD_NOAPLIC; + + elemsize = DB_DESC_SIZE (desc); + if (elemsize & 0xff000000U) + elemsize = bswap_32 (elemsize); + + *address += (int32_t) DB_DESC_OFFSET (desc); + *address += (elemsize / 8 * (idx - (psaddr_t) 0)); + return TD_OK; +} + +td_err_e +_td_fetch_value (td_thragent_t *ta, + db_desc_t desc, int descriptor_name, + psaddr_t idx, psaddr_t address, + psaddr_t *result) +{ + ps_err_e err; + td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address); + if (terr != TD_OK) + return terr; + + if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8)) + { + uint8_t value; + err = ps_pdread (ta->ph, address, &value, sizeof value); + *result = (psaddr_t) 0 + value; + } + else if (DB_DESC_SIZE (desc) == 32) + { + uint32_t value; + err = ps_pdread (ta->ph, address, &value, sizeof value); + *result = (psaddr_t) 0 + value; + } + else if (DB_DESC_SIZE (desc) == 64) + { + uint64_t value; + if (sizeof (psaddr_t) < 8) + return TD_NOCAPAB; + err = ps_pdread (ta->ph, address, &value, sizeof value); + *result = (psaddr_t) 0 + value; + } + else if (DB_DESC_SIZE (desc) == bswap_32 (32)) + { + uint32_t value; + err = ps_pdread (ta->ph, address, &value, sizeof value); + value = bswap_32 (value); + *result = (psaddr_t) 0 + value; + } + else if (DB_DESC_SIZE (desc) == bswap_32 (64)) + { + uint64_t value; + if (sizeof (psaddr_t) < 8) + return TD_NOCAPAB; + err = ps_pdread (ta->ph, address, &value, sizeof value); + value = bswap_64 (value); + *result = (psaddr_t) 0 + value; + } + else + return TD_DBERR; + + return err == PS_OK ? TD_OK : TD_ERR; +} + + +td_err_e +_td_store_value (td_thragent_t *ta, + uint32_t desc[2], int descriptor_name, psaddr_t idx, + psaddr_t address, psaddr_t widened_value) +{ + ps_err_e err; + td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address); + if (terr != TD_OK) + return terr; + + if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8)) + { + uint8_t value = widened_value - (psaddr_t) 0; + err = ps_pdwrite (ta->ph, address, &value, sizeof value); + } + else if (DB_DESC_SIZE (desc) == 32) + { + uint32_t value = widened_value - (psaddr_t) 0; + err = ps_pdwrite (ta->ph, address, &value, sizeof value); + } + else if (DB_DESC_SIZE (desc) == 64) + { + uint64_t value = widened_value - (psaddr_t) 0; + if (sizeof (psaddr_t) < 8) + return TD_NOCAPAB; + err = ps_pdwrite (ta->ph, address, &value, sizeof value); + } + else if (DB_DESC_SIZE (desc) == bswap_32 (32)) + { + uint32_t value = widened_value - (psaddr_t) 0; + value = bswap_32 (value); + err = ps_pdwrite (ta->ph, address, &value, sizeof value); + } + else if (DB_DESC_SIZE (desc) == bswap_32 (64)) + { + uint64_t value = widened_value - (psaddr_t) 0; + if (sizeof (psaddr_t) < 8) + return TD_NOCAPAB; + value = bswap_64 (value); + err = ps_pdwrite (ta->ph, address, &value, sizeof value); + } + else + return TD_DBERR; + + return err == PS_OK ? TD_OK : TD_ERR; +} + +td_err_e +_td_fetch_value_local (td_thragent_t *ta, + db_desc_t desc, int descriptor_name, psaddr_t idx, + void *address, + psaddr_t *result) +{ + td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address); + if (terr != TD_OK) + return terr; + + if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8)) + { + uint8_t value; + memcpy (&value, address, sizeof value); + *result = (psaddr_t) 0 + value; + } + else if (DB_DESC_SIZE (desc) == 32) + { + uint32_t value; + memcpy (&value, address, sizeof value); + *result = (psaddr_t) 0 + value; + } + else if (DB_DESC_SIZE (desc) == 64) + { + uint64_t value; + if (sizeof (psaddr_t) < 8) + return TD_NOCAPAB; + memcpy (&value, address, sizeof value); + *result = (psaddr_t) 0 + value; + } + else if (DB_DESC_SIZE (desc) == bswap_32 (32)) + { + uint32_t value; + memcpy (&value, address, sizeof value); + value = bswap_32 (value); + *result = (psaddr_t) 0 + value; + } + else if (DB_DESC_SIZE (desc) == bswap_32 (64)) + { + uint64_t value; + if (sizeof (psaddr_t) < 8) + return TD_NOCAPAB; + memcpy (&value, address, sizeof value); + value = bswap_64 (value); + *result = (psaddr_t) 0 + value; + } + else + return TD_DBERR; + + return TD_OK; +} + + +td_err_e +_td_store_value_local (td_thragent_t *ta, + uint32_t desc[2], int descriptor_name, psaddr_t idx, + void *address, psaddr_t widened_value) +{ + td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address); + if (terr != TD_OK) + return terr; + + if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8)) + { + uint8_t value = widened_value - (psaddr_t) 0; + memcpy (address, &value, sizeof value); + } + else if (DB_DESC_SIZE (desc) == 32) + { + uint32_t value = widened_value - (psaddr_t) 0; + memcpy (address, &value, sizeof value); + } + else if (DB_DESC_SIZE (desc) == 64) + { + uint64_t value = widened_value - (psaddr_t) 0; + if (sizeof (psaddr_t) < 8) + return TD_NOCAPAB; + memcpy (address, &value, sizeof value); + } + else if (DB_DESC_SIZE (desc) == bswap_32 (32)) + { + uint32_t value = widened_value - (psaddr_t) 0; + value = bswap_32 (value); + memcpy (address, &value, sizeof value); + } + else if (DB_DESC_SIZE (desc) == bswap_32 (64)) + { + uint64_t value = widened_value - (psaddr_t) 0; + if (sizeof (psaddr_t) < 8) + return TD_NOCAPAB; + value = bswap_64 (value); + memcpy (address, &value, sizeof value); + } + else + return TD_DBERR; + + return TD_OK; +} diff --git a/libpthread/nptl_db/proc_service.h b/libpthread/nptl_db/proc_service.h new file mode 100644 index 000000000..d49e87ab3 --- /dev/null +++ b/libpthread/nptl_db/proc_service.h @@ -0,0 +1,87 @@ +/* Callback interface for libthread_db, functions users must define. + Copyright (C) 1999,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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The definitions in this file must correspond to those in the debugger. */ +#include <sys/procfs.h> + +/* Functions in this interface return one of these status codes. */ +typedef enum +{ + PS_OK, /* Generic "call succeeded". */ + PS_ERR, /* Generic error. */ + PS_BADPID, /* Bad process handle. */ + PS_BADLID, /* Bad LWP identifier. */ + PS_BADADDR, /* Bad address. */ + PS_NOSYM, /* Could not find given symbol. */ + PS_NOFREGS /* FPU register set not available for given LWP. */ +} ps_err_e; + + +/* This type is opaque in this interface. + It's defined by the user of libthread_db. */ +struct ps_prochandle; + + +/* Read or write process memory at the given address. */ +extern ps_err_e ps_pdread (struct ps_prochandle *, + psaddr_t, void *, size_t); +extern ps_err_e ps_pdwrite (struct ps_prochandle *, + psaddr_t, const void *, size_t); +extern ps_err_e ps_ptread (struct ps_prochandle *, + psaddr_t, void *, size_t); +extern ps_err_e ps_ptwrite (struct ps_prochandle *, + psaddr_t, const void *, size_t); + + +/* Get and set the given LWP's general or FPU register set. */ +extern ps_err_e ps_lgetregs (struct ps_prochandle *, + lwpid_t, prgregset_t); +extern ps_err_e ps_lsetregs (struct ps_prochandle *, + lwpid_t, const prgregset_t); +extern ps_err_e ps_lgetfpregs (struct ps_prochandle *, + lwpid_t, prfpregset_t *); +extern ps_err_e ps_lsetfpregs (struct ps_prochandle *, + lwpid_t, const prfpregset_t *); + +/* Return the PID of the process. */ +extern pid_t ps_getpid (struct ps_prochandle *); + +/* Fetch the special per-thread address associated with the given LWP. + This call is only used on a few platforms (most use a normal register). + The meaning of the `int' parameter is machine-dependent. */ +extern ps_err_e ps_get_thread_area (const struct ps_prochandle *, + lwpid_t, int, psaddr_t *); + + +/* Look up the named symbol in the named DSO in the symbol tables + associated with the process being debugged, filling in *SYM_ADDR + with the corresponding run-time address. */ +extern ps_err_e ps_pglobal_lookup (struct ps_prochandle *, + const char *object_name, + const char *sym_name, + psaddr_t *sym_addr); + + +/* Stop or continue the entire process. */ +extern ps_err_e ps_pstop (const struct ps_prochandle *); +extern ps_err_e ps_pcontinue (const struct ps_prochandle *); + +/* Stop or continue the given LWP alone. */ +extern ps_err_e ps_lstop (const struct ps_prochandle *, lwpid_t); +extern ps_err_e ps_lcontinue (const struct ps_prochandle *, lwpid_t); diff --git a/libpthread/nptl_db/structs.def b/libpthread/nptl_db/structs.def new file mode 100644 index 000000000..1572ad696 --- /dev/null +++ b/libpthread/nptl_db/structs.def @@ -0,0 +1,88 @@ +/* List of types and symbols in libpthread examined by libthread_db. + Copyright (C) 2003, 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef DB_STRUCT_ARRAY_FIELD +# define DB_STRUCT_ARRAY_FIELD(type, field) DB_STRUCT_FIELD (type, field) +# define DB_ARRAY_VARIABLE(name) DB_VARIABLE (name) +# define STRUCTS_DEF_DEFAULTS 1 +#endif + +DB_STRUCT (pthread) +DB_STRUCT_FIELD (pthread, list) +DB_STRUCT_FIELD (pthread, report_events) +DB_STRUCT_FIELD (pthread, tid) +DB_STRUCT_FIELD (pthread, start_routine) +DB_STRUCT_FIELD (pthread, cancelhandling) +DB_STRUCT_FIELD (pthread, schedpolicy) +DB_STRUCT_FIELD (pthread, schedparam_sched_priority) +DB_STRUCT_FIELD (pthread, specific) +DB_STRUCT_FIELD (pthread, eventbuf) +DB_STRUCT_FIELD (pthread, eventbuf_eventmask) +DB_STRUCT_ARRAY_FIELD (pthread, eventbuf_eventmask_event_bits) +DB_STRUCT_FIELD (pthread, nextevent) + +DB_STRUCT (list_t) +DB_STRUCT_FIELD (list_t, next) +DB_STRUCT_FIELD (list_t, prev) + +DB_STRUCT (td_thr_events_t) +DB_STRUCT_ARRAY_FIELD (td_thr_events_t, event_bits) + +DB_STRUCT (td_eventbuf_t) +DB_STRUCT_FIELD (td_eventbuf_t, eventnum) +DB_STRUCT_FIELD (td_eventbuf_t, eventdata) + +DB_SYMBOL (stack_used) +DB_SYMBOL (__stack_user) +DB_SYMBOL (nptl_version) +DB_FUNCTION (__nptl_create_event) +DB_FUNCTION (__nptl_death_event) +DB_SYMBOL (__nptl_threads_events) +DB_VARIABLE (__nptl_nthreads) +DB_VARIABLE (__nptl_last_event) + +DB_ARRAY_VARIABLE (__pthread_keys) +DB_STRUCT (pthread_key_struct) +DB_STRUCT_FIELD (pthread_key_struct, seq) +DB_STRUCT_FIELD (pthread_key_struct, destr) + +DB_STRUCT (pthread_key_data) +DB_STRUCT_FIELD (pthread_key_data, seq) +DB_STRUCT_FIELD (pthread_key_data, data) +DB_STRUCT (pthread_key_data_level2) +DB_STRUCT_ARRAY_FIELD (pthread_key_data_level2, data) + +#if USE_TLS +DB_STRUCT_FIELD (link_map, l_tls_modid) +#endif + +#if !defined IS_IN_libpthread || USE_TLS +DB_STRUCT_ARRAY_FIELD (dtv, dtv) +# define pointer_val pointer.val /* Field of anonymous struct in dtv_t. */ +DB_STRUCT_FIELD (dtv_t, pointer_val) +#endif +#if !defined IS_IN_libpthread || (defined TLS_TCB_AT_TP && TLS_TCB_AT_TP) +DB_STRUCT_FIELD (pthread, dtvp) +#endif + +#ifdef STRUCTS_DEF_DEFAULTS +# undef DB_STRUCT_ARRAY_FIELD +# undef DB_ARRAY_VARIABLE +# undef STRUCTS_DEF_DEFAULTS +#endif diff --git a/libpthread/nptl_db/td_init.c b/libpthread/nptl_db/td_init.c new file mode 100644 index 000000000..946ff7244 --- /dev/null +++ b/libpthread/nptl_db/td_init.c @@ -0,0 +1,32 @@ +/* Initialization function of thread debugger support library. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + +int __td_debug; + + +td_err_e +td_init (void) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_init"); + return TD_OK; +} diff --git a/libpthread/nptl_db/td_log.c b/libpthread/nptl_db/td_log.c new file mode 100644 index 000000000..52212a0e9 --- /dev/null +++ b/libpthread/nptl_db/td_log.c @@ -0,0 +1,32 @@ +/* Noop, left for historical reasons. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_log (void) +{ + /* This interface is deprecated in the Sun interface. We provide it + for compatibility but don't do anything ourself. We might in + future do some logging if this seems reasonable. */ + LOG ("td_log"); + return TD_OK; +} diff --git a/libpthread/nptl_db/td_symbol_list.c b/libpthread/nptl_db/td_symbol_list.c new file mode 100644 index 000000000..04aed6787 --- /dev/null +++ b/libpthread/nptl_db/td_symbol_list.c @@ -0,0 +1,87 @@ +/* Return list of symbols the library can request. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. + + 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 <assert.h> +#ifndef __UCLIBC__ +#include <gnu/lib-names.h> +#endif +#include "thread_dbP.h" + + +#ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define DOT "." /* PPC64 requires . prefix on code symbols. */ +#else +# define DOT /* No prefix. */ +#endif + +static const char *symbol_list_arr[] = +{ +# define DB_STRUCT(type) \ + [SYM_SIZEOF_##type] = "_thread_db_sizeof_" #type, +# define DB_STRUCT_FIELD(type, field) \ + [SYM_##type##_FIELD_##field] = "_thread_db_" #type "_" #field, +# define DB_SYMBOL(name) \ + [SYM_##name] = #name, +# define DB_FUNCTION(name) \ + [SYM_##name] = DOT #name, +# define DB_VARIABLE(name) \ + [SYM_##name] = #name, \ + [SYM_DESC_##name] = "_thread_db_" #name, +# include "structs.def" +# undef DB_STRUCT +# undef DB_FUNCTION +# undef DB_SYMBOL +# undef DB_VARIABLE + + [SYM_TH_UNIQUE_CONST_THREAD_AREA] = "_thread_db_const_thread_area", + [SYM_TH_UNIQUE_REGISTER64] = "_thread_db_register64", + [SYM_TH_UNIQUE_REGISTER32] = "_thread_db_register32", + [SYM_TH_UNIQUE_REGISTER32_THREAD_AREA] = "_thread_db_register32_thread_area", + [SYM_TH_UNIQUE_REGISTER64_THREAD_AREA] = "_thread_db_register64_thread_area", + + [SYM_NUM_MESSAGES] = NULL +}; + + +const char ** +td_symbol_list (void) +{ + return symbol_list_arr; +} + + +ps_err_e +td_lookup (struct ps_prochandle *ps, int idx, psaddr_t *sym_addr) +{ + ps_err_e result; + assert (idx >= 0 && idx < SYM_NUM_MESSAGES); + result = ps_pglobal_lookup (ps, LIBPTHREAD_SO, symbol_list_arr[idx], + sym_addr); + +#ifdef HAVE_ASM_GLOBAL_DOT_NAME + /* For PowerPC, 64-bit uses dot symbols but 32-bit does not. + We could be a 64-bit libthread_db debugging a 32-bit libpthread. */ + if (result == PS_NOSYM && symbol_list_arr[idx][0] == '.') + result = ps_pglobal_lookup (ps, LIBPTHREAD_SO, &symbol_list_arr[idx][1], + sym_addr); +#endif + + return result; +} diff --git a/libpthread/nptl_db/td_ta_clear_event.c b/libpthread/nptl_db/td_ta_clear_event.c new file mode 100644 index 000000000..7a2850c4e --- /dev/null +++ b/libpthread/nptl_db/td_ta_clear_event.c @@ -0,0 +1,79 @@ +/* Globally disable events. + Copyright (C) 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_ta_clear_event (ta_arg, event) + const td_thragent_t *ta_arg; + td_thr_events_t *event; +{ + td_thragent_t *const ta = (td_thragent_t *) ta_arg; + td_err_e err; + psaddr_t eventmask = 0; + void *copy = NULL; + + LOG ("td_ta_clear_event"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Fetch the old event mask from the inferior and modify it in place. */ + err = DB_GET_SYMBOL (eventmask, ta, __nptl_threads_events); + if (err == TD_OK) + err = DB_GET_STRUCT (copy, ta, eventmask, td_thr_events_t); + if (err == TD_OK) + { + uint32_t idx; + for (idx = 0; idx < TD_EVENTSIZE; ++idx) + { + psaddr_t word; + uint32_t mask; + err = DB_GET_FIELD_LOCAL (word, ta, copy, + td_thr_events_t, event_bits, idx); + if (err != TD_OK) + break; + mask = (uintptr_t) word; + mask &= ~event->event_bits[idx]; + word = (psaddr_t) (uintptr_t) mask; + err = DB_PUT_FIELD_LOCAL (ta, copy, + td_thr_events_t, event_bits, idx, word); + if (err != TD_OK) + break; + } + if (err == TD_NOAPLIC) + { + err = TD_OK; + while (idx < TD_EVENTSIZE) + if (event->event_bits[idx++] != 0) + { + err = TD_NOEVENT; + break; + } + } + if (err == TD_OK) + /* Now write it back to the inferior. */ + err = DB_PUT_STRUCT (ta, eventmask, td_thr_events_t, copy); + } + + return err; +} diff --git a/libpthread/nptl_db/td_ta_delete.c b/libpthread/nptl_db/td_ta_delete.c new file mode 100644 index 000000000..57b90e57f --- /dev/null +++ b/libpthread/nptl_db/td_ta_delete.c @@ -0,0 +1,42 @@ +/* Detach to target process. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 <stdlib.h> + +#include "thread_dbP.h" + + +td_err_e +td_ta_delete (td_thragent_t *ta) +{ + LOG ("td_ta_delete"); + + /* Safety check. Note that the test will also fail for TA == NULL. */ + if (!ta_ok (ta)) + return TD_BADTA; + + /* Remove the handle from the list. */ + list_del (&ta->list); + + /* The handle was allocated in `td_ta_new'. */ + free (ta); + + return TD_OK; +} diff --git a/libpthread/nptl_db/td_ta_enable_stats.c b/libpthread/nptl_db/td_ta_enable_stats.c new file mode 100644 index 000000000..ec7014ad2 --- /dev/null +++ b/libpthread/nptl_db/td_ta_enable_stats.c @@ -0,0 +1,35 @@ +/* Enable collection of statistics for process. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_ta_enable_stats (const td_thragent_t *ta, int enable) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_ta_enable_stats"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_OK; +} diff --git a/libpthread/nptl_db/td_ta_event_addr.c b/libpthread/nptl_db/td_ta_event_addr.c new file mode 100644 index 000000000..45c6b113d --- /dev/null +++ b/libpthread/nptl_db/td_ta_event_addr.c @@ -0,0 +1,61 @@ +/* Get event address. + Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_ta_event_addr (const td_thragent_t *ta_arg, + td_event_e event, td_notify_t *addr) +{ + td_thragent_t *const ta = (td_thragent_t *) ta_arg; + td_err_e err; + psaddr_t taddr = NULL; + + LOG ("td_ta_event_addr"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + switch (event) + { + case TD_CREATE: + err = DB_GET_SYMBOL (taddr, ta, __nptl_create_event); + break; + + case TD_DEATH: + err = DB_GET_SYMBOL (taddr, ta, __nptl_death_event); + break; + + default: + /* Event cannot be handled. */ + return TD_NOEVENT; + } + + if (err == TD_OK) + { + /* Success, we got the address. */ + addr->type = NOTIFY_BPT; + addr->u.bptaddr = taddr; + } + + return err; +} diff --git a/libpthread/nptl_db/td_ta_event_getmsg.c b/libpthread/nptl_db/td_ta_event_getmsg.c new file mode 100644 index 000000000..d3b46bd56 --- /dev/null +++ b/libpthread/nptl_db/td_ta_event_getmsg.c @@ -0,0 +1,105 @@ +/* Retrieve event. + Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 <stddef.h> +#include <string.h> + +#include "thread_dbP.h" + + +td_err_e +td_ta_event_getmsg (const td_thragent_t *ta_arg, td_event_msg_t *msg) +{ + td_thragent_t *const ta = (td_thragent_t *) ta_arg; + td_err_e err; + psaddr_t eventbuf, eventnum, eventdata; + psaddr_t thp, next; + void *copy = NULL; + + /* XXX I cannot think of another way but using a static variable. */ + /* XXX Use at least __thread once it is possible. */ + static td_thrhandle_t th; + + LOG ("td_thr_event_getmsg"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Get the pointer to the thread descriptor with the last event. */ + err = DB_GET_VALUE (thp, ta, __nptl_last_event, 0); + if (err != TD_OK) + return err; + + if (thp == 0) + /* Nothing waiting. */ + return TD_NOMSG; + + /* Copy the event message buffer in from the inferior. */ + err = DB_GET_FIELD_ADDRESS (eventbuf, ta, thp, pthread, eventbuf, 0); + if (err == TD_OK) + err = DB_GET_STRUCT (copy, ta, eventbuf, td_eventbuf_t); + if (err != TD_OK) + return err; + + /* Read the event details from the target thread. */ + err = DB_GET_FIELD_LOCAL (eventnum, ta, copy, td_eventbuf_t, eventnum, 0); + if (err != TD_OK) + return err; + /* If the structure is on the list there better be an event recorded. */ + if ((int) (uintptr_t) eventnum == TD_EVENT_NONE) + return TD_DBERR; + + /* Fill the user's data structure. */ + err = DB_GET_FIELD_LOCAL (eventdata, ta, copy, td_eventbuf_t, eventdata, 0); + if (err != TD_OK) + return err; + + /* Generate the thread descriptor. */ + th.th_ta_p = (td_thragent_t *) ta; + th.th_unique = thp; + + /* Fill the user's data structure. */ + msg->msg.data = (uintptr_t) eventdata; + msg->event = (uintptr_t) eventnum; + msg->th_p = &th; + + /* And clear the event message in the target. */ + memset (copy, 0, ta->ta_sizeof_td_eventbuf_t); + err = DB_PUT_STRUCT (ta, eventbuf, td_eventbuf_t, copy); + if (err != TD_OK) + return err; + + /* Get the pointer to the next descriptor with an event. */ + err = DB_GET_FIELD (next, ta, thp, pthread, nextevent, 0); + if (err != TD_OK) + return err; + + /* Store the pointer in the list head variable. */ + err = DB_PUT_VALUE (ta, __nptl_last_event, 0, next); + if (err != TD_OK) + return err; + + if (next != 0) + /* Clear the next pointer in the current descriptor. */ + err = DB_PUT_FIELD (ta, thp, pthread, nextevent, 0, 0); + + return err; +} diff --git a/libpthread/nptl_db/td_ta_get_nthreads.c b/libpthread/nptl_db/td_ta_get_nthreads.c new file mode 100644 index 000000000..ffe78bd57 --- /dev/null +++ b/libpthread/nptl_db/td_ta_get_nthreads.c @@ -0,0 +1,42 @@ +/* Get the number of threads in the process. + Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + +td_err_e +td_ta_get_nthreads (const td_thragent_t *ta_arg, int *np) +{ + td_thragent_t *const ta = (td_thragent_t *) ta_arg; + td_err_e err; + psaddr_t n; + + LOG ("td_ta_get_nthreads"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Access the variable in the inferior that tells us. */ + err = DB_GET_VALUE (n, ta, __nptl_nthreads, 0); + if (err == TD_OK) + *np = (uintptr_t) n; + + return err; +} diff --git a/libpthread/nptl_db/td_ta_get_ph.c b/libpthread/nptl_db/td_ta_get_ph.c new file mode 100644 index 000000000..04e01fb73 --- /dev/null +++ b/libpthread/nptl_db/td_ta_get_ph.c @@ -0,0 +1,36 @@ +/* Get external process handle. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_ta_get_ph (const td_thragent_t *ta, struct ps_prochandle **ph) +{ + LOG ("td_ta_get_ph"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + *ph = ta->ph; + + return TD_OK; +} diff --git a/libpthread/nptl_db/td_ta_get_stats.c b/libpthread/nptl_db/td_ta_get_stats.c new file mode 100644 index 000000000..d5d879c3e --- /dev/null +++ b/libpthread/nptl_db/td_ta_get_stats.c @@ -0,0 +1,35 @@ +/* Retrieve statistics for process. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_ta_get_stats (const td_thragent_t *ta, td_ta_stats_t *statsp) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_ta_get_stats"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_OK; +} diff --git a/libpthread/nptl_db/td_ta_map_id2thr.c b/libpthread/nptl_db/td_ta_map_id2thr.c new file mode 100644 index 000000000..189a67171 --- /dev/null +++ b/libpthread/nptl_db/td_ta_map_id2thr.c @@ -0,0 +1,38 @@ +/* Map thread ID to thread handle. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_ta_map_id2thr (const td_thragent_t *ta, pthread_t pt, td_thrhandle_t *th) +{ + LOG ("td_ta_map_id2thr"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Create the `td_thrhandle_t' object. */ + th->th_ta_p = (td_thragent_t *) ta; + th->th_unique = (psaddr_t) pt; + + return TD_OK; +} diff --git a/libpthread/nptl_db/td_ta_map_lwp2thr.c b/libpthread/nptl_db/td_ta_map_lwp2thr.c new file mode 100644 index 000000000..acfa0fd8a --- /dev/null +++ b/libpthread/nptl_db/td_ta_map_lwp2thr.c @@ -0,0 +1,178 @@ +/* Which thread is running on an LWP? + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include <stdlib.h> +#include <byteswap.h> +#include <sys/procfs.h> + + +td_err_e +td_ta_map_lwp2thr (const td_thragent_t *ta_arg, + lwpid_t lwpid, td_thrhandle_t *th) +{ + td_thragent_t *const ta = (td_thragent_t *) ta_arg; + ps_err_e err; + td_err_e terr; + prgregset_t regs; + psaddr_t addr; + + LOG ("td_ta_map_lwp2thr"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + if (ta->ta_howto == ta_howto_unknown) + { + /* We need to read in from the inferior the instructions what to do. */ + psaddr_t howto; + + err = td_lookup (ta->ph, SYM_TH_UNIQUE_CONST_THREAD_AREA, &howto); + if (err == PS_OK) + { + err = ps_pdread (ta->ph, howto, + &ta->ta_howto_data.const_thread_area, + sizeof ta->ta_howto_data.const_thread_area); + if (err != PS_OK) + return TD_ERR; + ta->ta_howto = ta_howto_const_thread_area; + if (ta->ta_howto_data.const_thread_area & 0xff000000U) + ta->ta_howto_data.const_thread_area + = bswap_32 (ta->ta_howto_data.const_thread_area); + } + else + { + switch (sizeof (regs[0])) + { + case 8: + err = td_lookup (ta->ph, SYM_TH_UNIQUE_REGISTER64, &howto); + if (err == PS_OK) + ta->ta_howto = ta_howto_reg; + else if (err == PS_NOSYM) + { + err = td_lookup (ta->ph, + SYM_TH_UNIQUE_REGISTER64_THREAD_AREA, + &howto); + if (err == PS_OK) + ta->ta_howto = ta_howto_reg_thread_area; + } + break; + + case 4: + err = td_lookup (ta->ph, SYM_TH_UNIQUE_REGISTER32, &howto); + if (err == PS_OK) + ta->ta_howto = ta_howto_reg; + else if (err == PS_NOSYM) + { + err = td_lookup (ta->ph, + SYM_TH_UNIQUE_REGISTER32_THREAD_AREA, + &howto); + if (err == PS_OK) + ta->ta_howto = ta_howto_reg_thread_area; + } + break; + + default: + abort (); + return TD_DBERR; + } + + if (err != PS_OK) + return TD_DBERR; + + /* For either of these methods we read in the same descriptor. */ + err = ps_pdread (ta->ph, howto, + ta->ta_howto_data.reg, DB_SIZEOF_DESC); + if (err != PS_OK) + return TD_ERR; + if (DB_DESC_SIZE (ta->ta_howto_data.reg) == 0) + return TD_DBERR; + if (DB_DESC_SIZE (ta->ta_howto_data.reg) & 0xff000000U) + { + /* Byte-swap these words, though we leave the size word + in native order as the handy way to distinguish. */ + DB_DESC_OFFSET (ta->ta_howto_data.reg) + = bswap_32 (DB_DESC_OFFSET (ta->ta_howto_data.reg)); + DB_DESC_NELEM (ta->ta_howto_data.reg) + = bswap_32 (DB_DESC_NELEM (ta->ta_howto_data.reg)); + } + } + } + + switch (ta->ta_howto) + { + case ta_howto_unknown: + return TD_DBERR; + + default: + return TD_DBERR; + + case ta_howto_reg: + /* On most machines, we are just looking at a register. */ + if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK) + return TD_ERR; + terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg, -1, + 0, regs, &addr); + if (terr != TD_OK) + return terr; + /* In this descriptor the nelem word is overloaded as the bias. */ + addr += (int32_t) DB_DESC_NELEM (ta->ta_howto_data.reg); + th->th_unique = addr; + break; + + case ta_howto_const_thread_area: + /* Some hosts don't have this call and this case won't be used. */ +# pragma weak ps_get_thread_area + if (&ps_get_thread_area == NULL) + return TD_NOCAPAB; + + /* A la x86-64, there is a constant magic index for get_thread_area. */ + if (ps_get_thread_area (ta->ph, lwpid, + ta->ta_howto_data.const_thread_area, + &th->th_unique) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + break; + + case ta_howto_reg_thread_area: + if (&ps_get_thread_area == NULL) + return TD_NOCAPAB; + + /* A la i386, there is a register with an index for get_thread_area. */ + if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK) + return TD_ERR; + terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg_thread_area, -1, + 0, regs, &addr); + if (terr != TD_OK) + return terr; + /* In this descriptor the nelem word is overloaded as scale factor. */ + if (ps_get_thread_area + (ta->ph, lwpid, + ((addr - (psaddr_t) 0) + >> DB_DESC_NELEM (ta->ta_howto_data.reg_thread_area)), + &th->th_unique) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + break; + } + + /* Found it. Now complete the `td_thrhandle_t' object. */ + th->th_ta_p = (td_thragent_t *) ta; + + return TD_OK; +} diff --git a/libpthread/nptl_db/td_ta_new.c b/libpthread/nptl_db/td_ta_new.c new file mode 100644 index 000000000..f84049af3 --- /dev/null +++ b/libpthread/nptl_db/td_ta_new.c @@ -0,0 +1,65 @@ +/* Attach to target process. + Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <version.h> + +#include "thread_dbP.h" + + +/* Datatype for the list of known thread agents. Normally there will + be exactly one so we don't spend much though on making it fast. */ +LIST_HEAD (__td_agent_list); + + +td_err_e +td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta) +{ + psaddr_t versaddr; + char versbuf[sizeof (VERSION)]; + + LOG ("td_ta_new"); + + /* Check whether the versions match. */ + if (td_lookup (ps, SYM_nptl_version, &versaddr) != PS_OK) + return TD_NOLIBTHREAD; + if (ps_pdread (ps, versaddr, versbuf, sizeof (versbuf)) != PS_OK) + return TD_ERR; + + if (memcmp (versbuf, VERSION, sizeof VERSION) != 0) + /* Not the right version. */ + return TD_VERSION; + + /* Fill in the appropriate information. */ + *ta = (td_thragent_t *) calloc (1, sizeof (td_thragent_t)); + if (*ta == NULL) + return TD_MALLOC; + + /* Store the proc handle which we will pass to the callback functions + back into the debugger. */ + (*ta)->ph = ps; + + /* Now add the new agent descriptor to the list. */ + list_add (&(*ta)->list, &__td_agent_list); + + return TD_OK; +} diff --git a/libpthread/nptl_db/td_ta_reset_stats.c b/libpthread/nptl_db/td_ta_reset_stats.c new file mode 100644 index 000000000..ea59d2cda --- /dev/null +++ b/libpthread/nptl_db/td_ta_reset_stats.c @@ -0,0 +1,35 @@ +/* Reset statistics. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_ta_reset_stats (const td_thragent_t *ta) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_ta_reset_stats"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_OK; +} diff --git a/libpthread/nptl_db/td_ta_set_event.c b/libpthread/nptl_db/td_ta_set_event.c new file mode 100644 index 000000000..29fc14bfb --- /dev/null +++ b/libpthread/nptl_db/td_ta_set_event.c @@ -0,0 +1,79 @@ +/* Globally enable events. + Copyright (C) 1999,2001,2002,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_ta_set_event (ta_arg, event) + const td_thragent_t *ta_arg; + td_thr_events_t *event; +{ + td_thragent_t *const ta = (td_thragent_t *) ta_arg; + td_err_e err; + psaddr_t eventmask = 0; + void *copy = NULL; + + LOG ("td_ta_set_event"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Fetch the old event mask from the inferior and modify it in place. */ + err = DB_GET_SYMBOL (eventmask, ta, __nptl_threads_events); + if (err == TD_OK) + err = DB_GET_STRUCT (copy, ta, eventmask, td_thr_events_t); + if (err == TD_OK) + { + uint32_t idx; + for (idx = 0; idx < TD_EVENTSIZE; ++idx) + { + psaddr_t word; + uint32_t mask; + err = DB_GET_FIELD_LOCAL (word, ta, copy, + td_thr_events_t, event_bits, idx); + if (err != TD_OK) + break; + mask = (uintptr_t) word; + mask |= event->event_bits[idx]; + word = (psaddr_t) (uintptr_t) mask; + err = DB_PUT_FIELD_LOCAL (ta, copy, + td_thr_events_t, event_bits, idx, word); + if (err != TD_OK) + break; + } + if (err == TD_NOAPLIC) + { + err = TD_OK; + while (idx < TD_EVENTSIZE) + if (event->event_bits[idx++] != 0) + { + err = TD_NOEVENT; + break; + } + } + if (err == TD_OK) + /* Now write it back to the inferior. */ + err = DB_PUT_STRUCT (ta, eventmask, td_thr_events_t, copy); + } + + return err; +} diff --git a/libpthread/nptl_db/td_ta_setconcurrency.c b/libpthread/nptl_db/td_ta_setconcurrency.c new file mode 100644 index 000000000..8552ffbe0 --- /dev/null +++ b/libpthread/nptl_db/td_ta_setconcurrency.c @@ -0,0 +1,35 @@ +/* Set suggested concurrency level for process. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_ta_setconcurrency (const td_thragent_t *ta, int level) +{ + /* This is something LinuxThreads does not need to support. */ + LOG ("td_ta_setconcurrency"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_NOCAPAB; +} diff --git a/libpthread/nptl_db/td_ta_thr_iter.c b/libpthread/nptl_db/td_ta_thr_iter.c new file mode 100644 index 000000000..66e437665 --- /dev/null +++ b/libpthread/nptl_db/td_ta_thr_iter.c @@ -0,0 +1,148 @@ +/* Iterate over a process's threads. + Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +static td_err_e +iterate_thread_list (td_thragent_t *ta, td_thr_iter_f *callback, + void *cbdata_p, td_thr_state_e state, int ti_pri, + psaddr_t head, int fake_empty) +{ + td_err_e err; + psaddr_t next, ofs; + void *copy; + + /* Test the state. + XXX This is incomplete. Normally this test should be in the loop. */ + if (state != TD_THR_ANY_STATE) + return TD_OK; + + err = DB_GET_FIELD (next, ta, head, list_t, next, 0); + if (err != TD_OK) + return err; + + if (next == 0 && fake_empty) + { + /* __pthread_initialize_minimal has not run. + There is just the main thread to return. */ + td_thrhandle_t th; + err = td_ta_map_lwp2thr (ta, ps_getpid (ta->ph), &th); + if (err == TD_OK) + err = callback (&th, cbdata_p) != 0 ? TD_DBERR : TD_OK; + return err; + } + + /* Cache the offset from struct pthread to its list_t member. */ + err = DB_GET_FIELD_ADDRESS (ofs, ta, 0, pthread, list, 0); + if (err != TD_OK) + return err; + + if (ta->ta_sizeof_pthread == 0) + { + err = _td_check_sizeof (ta, &ta->ta_sizeof_pthread, SYM_SIZEOF_pthread); + if (err != TD_OK) + return err; + } + copy = __alloca (ta->ta_sizeof_pthread); + + while (next != head) + { + psaddr_t addr, schedpolicy, schedprio; + + addr = next - (ofs - (psaddr_t) 0); + if (next == 0 || addr == 0) /* Sanity check. */ + return TD_DBERR; + + /* Copy the whole descriptor in once so we can access the several + fields locally. Excess copying in one go is much better than + multiple ps_pdread calls. */ + if (ps_pdread (ta->ph, addr, copy, ta->ta_sizeof_pthread) != PS_OK) + return TD_ERR; + + err = DB_GET_FIELD_LOCAL (schedpolicy, ta, copy, pthread, + schedpolicy, 0); + if (err != TD_OK) + break; + err = DB_GET_FIELD_LOCAL (schedprio, ta, copy, pthread, + schedparam_sched_priority, 0); + if (err != TD_OK) + break; + + /* Now test whether this thread matches the specified conditions. */ + + /* Only if the priority level is as high or higher. */ + int descr_pri = ((uintptr_t) schedpolicy == SCHED_OTHER + ? 0 : (uintptr_t) schedprio); + if (descr_pri >= ti_pri) + { + /* Yep, it matches. Call the callback function. */ + td_thrhandle_t th; + th.th_ta_p = (td_thragent_t *) ta; + th.th_unique = addr; + if (callback (&th, cbdata_p) != 0) + return TD_DBERR; + } + + /* Get the pointer to the next element. */ + err = DB_GET_FIELD_LOCAL (next, ta, copy + (ofs - (psaddr_t) 0), list_t, + next, 0); + if (err != TD_OK) + break; + } + + return err; +} + + +td_err_e +td_ta_thr_iter (const td_thragent_t *ta_arg, td_thr_iter_f *callback, + void *cbdata_p, td_thr_state_e state, int ti_pri, + sigset_t *ti_sigmask_p, unsigned int ti_user_flags) +{ + td_thragent_t *const ta = (td_thragent_t *) ta_arg; + td_err_e err; + psaddr_t list = 0; + + LOG ("td_ta_thr_iter"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* The thread library keeps two lists for the running threads. One + list contains the thread which are using user-provided stacks + (this includes the main thread) and the other includes the + threads for which the thread library allocated the stacks. We + have to iterate over both lists separately. We start with the + list of threads with user-defined stacks. */ + + err = DB_GET_SYMBOL (list, ta, __stack_user); + if (err == TD_OK) + err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri, list, 1); + + /* And the threads with stacks allocated by the implementation. */ + if (err == TD_OK) + err = DB_GET_SYMBOL (list, ta, stack_used); + if (err == TD_OK) + err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri, list, 0); + + return err; +} diff --git a/libpthread/nptl_db/td_ta_tsd_iter.c b/libpthread/nptl_db/td_ta_tsd_iter.c new file mode 100644 index 000000000..9cfb1e8de --- /dev/null +++ b/libpthread/nptl_db/td_ta_tsd_iter.c @@ -0,0 +1,81 @@ +/* Iterate over a process's thread-specific data. + Copyright (C) 1999,2000,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" +#include <alloca.h> + +td_err_e +td_ta_tsd_iter (const td_thragent_t *ta_arg, td_key_iter_f *callback, + void *cbdata_p) +{ + td_thragent_t *const ta = (td_thragent_t *) ta_arg; + td_err_e err; + void *keys; + size_t keys_nb, keys_elemsize; + psaddr_t addr; + uint32_t idx; + + LOG ("td_ta_tsd_iter"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* This makes sure we have the size information on hand. */ + addr = 0; + err = _td_locate_field (ta, + ta->ta_var___pthread_keys, SYM_DESC___pthread_keys, + (psaddr_t) 0 + 1, &addr); + if (err != TD_OK) + return err; + + /* Now copy in the entire array of key descriptors. */ + keys_elemsize = (addr - (psaddr_t) 0) / 8; + keys_nb = keys_elemsize * DB_DESC_NELEM (ta->ta_var___pthread_keys); + keys = __alloca (keys_nb); + err = DB_GET_SYMBOL (addr, ta, __pthread_keys); + if (err != TD_OK) + return err; + if (ps_pdread (ta->ph, addr, keys, keys_nb) != PS_OK) + return TD_ERR; + + /* Now get all descriptors, one after the other. */ + for (idx = 0; idx < DB_DESC_NELEM (ta->ta_var___pthread_keys); ++idx) + { + psaddr_t seq, destr; + err = DB_GET_FIELD_LOCAL (seq, ta, keys, pthread_key_struct, seq, 0); + if (err != TD_OK) + return err; + if (((uintptr_t) seq) & 1) + { + err = DB_GET_FIELD_LOCAL (destr, ta, keys, pthread_key_struct, + destr, 0); + if (err != TD_OK) + return err; + /* Return with an error if the callback returns a nonzero value. */ + if (callback ((thread_key_t) idx, destr, cbdata_p) != 0) + return TD_DBERR; + } + /* Advance to the next element in the copied array. */ + keys += keys_elemsize; + } + + return TD_OK; +} diff --git a/libpthread/nptl_db/td_thr_clear_event.c b/libpthread/nptl_db/td_thr_clear_event.c new file mode 100644 index 000000000..c43c625a4 --- /dev/null +++ b/libpthread/nptl_db/td_thr_clear_event.c @@ -0,0 +1,77 @@ +/* Disable specific event for thread. + Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 <stddef.h> + +#include "thread_dbP.h" + + +td_err_e +td_thr_clear_event (th, event) + const td_thrhandle_t *th; + td_thr_events_t *event; +{ + td_err_e err; + psaddr_t eventmask; + void *copy = NULL; + + LOG ("td_thr_clear_event"); + + /* Fetch the old event mask from the inferior and modify it in place. */ + err = DB_GET_FIELD_ADDRESS (eventmask, th->th_ta_p, + th->th_unique, pthread, eventbuf_eventmask, 0); + if (err == TD_OK) + err = DB_GET_STRUCT (copy, th->th_ta_p, eventmask, td_thr_events_t); + if (err == TD_OK) + { + uint32_t idx; + for (idx = 0; idx < TD_EVENTSIZE; ++idx) + { + psaddr_t word; + uint32_t mask; + err = DB_GET_FIELD_LOCAL (word, th->th_ta_p, copy, + td_thr_events_t, event_bits, idx); + if (err != TD_OK) + break; + mask = (uintptr_t) word; + mask &= ~event->event_bits[idx]; + word = (psaddr_t) (uintptr_t) mask; + err = DB_PUT_FIELD_LOCAL (th->th_ta_p, copy, + td_thr_events_t, event_bits, idx, word); + if (err != TD_OK) + break; + } + if (err == TD_NOAPLIC) + { + err = TD_OK; + while (idx < TD_EVENTSIZE) + if (event->event_bits[idx++] != 0) + { + err = TD_NOEVENT; + break; + } + } + if (err == TD_OK) + /* Now write it back to the inferior. */ + err = DB_PUT_STRUCT (th->th_ta_p, eventmask, td_thr_events_t, copy); + } + + return err; +} diff --git a/libpthread/nptl_db/td_thr_dbresume.c b/libpthread/nptl_db/td_thr_dbresume.c new file mode 100644 index 000000000..3fd794377 --- /dev/null +++ b/libpthread/nptl_db/td_thr_dbresume.c @@ -0,0 +1,30 @@ +/* Resume execution of given thread. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_thr_dbresume (const td_thrhandle_t *th) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_dbresume"); + return TD_NOCAPAB; +} diff --git a/libpthread/nptl_db/td_thr_dbsuspend.c b/libpthread/nptl_db/td_thr_dbsuspend.c new file mode 100644 index 000000000..6ef82ad34 --- /dev/null +++ b/libpthread/nptl_db/td_thr_dbsuspend.c @@ -0,0 +1,30 @@ +/* Suspend execution of given thread. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_thr_dbsuspend (const td_thrhandle_t *th) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_dbsuspend"); + return TD_NOCAPAB; +} diff --git a/libpthread/nptl_db/td_thr_event_enable.c b/libpthread/nptl_db/td_thr_event_enable.c new file mode 100644 index 000000000..a02be5da4 --- /dev/null +++ b/libpthread/nptl_db/td_thr_event_enable.c @@ -0,0 +1,34 @@ +/* Enable event process-wide. + Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_thr_event_enable (th, onoff) + const td_thrhandle_t *th; + int onoff; +{ + LOG ("td_thr_event_enable"); + + /* Write the new value into the thread data structure. */ + return DB_PUT_FIELD (th->th_ta_p, th->th_unique, pthread, report_events, 0, + (psaddr_t) 0 + (onoff != 0)); +} diff --git a/libpthread/nptl_db/td_thr_event_getmsg.c b/libpthread/nptl_db/td_thr_event_getmsg.c new file mode 100644 index 000000000..b24fc25d7 --- /dev/null +++ b/libpthread/nptl_db/td_thr_event_getmsg.c @@ -0,0 +1,119 @@ +/* Retrieve event. + Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" +#include <assert.h> + + +td_err_e +td_thr_event_getmsg (const td_thrhandle_t *th, td_event_msg_t *msg) +{ + td_err_e err; + psaddr_t eventbuf, eventnum, eventdata; + psaddr_t thp, prevp; + void *copy = NULL; + + LOG ("td_thr_event_getmsg"); + + /* Copy the event message buffer in from the inferior. */ + err = DB_GET_FIELD_ADDRESS (eventbuf, th->th_ta_p, th->th_unique, pthread, + eventbuf, 0); + if (err == TD_OK) + err = DB_GET_STRUCT (copy, th->th_ta_p, eventbuf, td_eventbuf_t); + if (err != TD_OK) + return err; + + /* Check whether an event occurred. */ + err = DB_GET_FIELD_LOCAL (eventnum, th->th_ta_p, copy, + td_eventbuf_t, eventnum, 0); + if (err != TD_OK) + return err; + if ((int) (uintptr_t) eventnum == TD_EVENT_NONE) + /* Nothing. */ + return TD_NOMSG; + + /* Fill the user's data structure. */ + err = DB_GET_FIELD_LOCAL (eventdata, th->th_ta_p, copy, + td_eventbuf_t, eventdata, 0); + if (err != TD_OK) + return err; + + msg->msg.data = (uintptr_t) eventdata; + msg->event = (uintptr_t) eventnum; + msg->th_p = th; + + /* And clear the event message in the target. */ + memset (copy, 0, th->th_ta_p->ta_sizeof_td_eventbuf_t); + err = DB_PUT_STRUCT (th->th_ta_p, eventbuf, td_eventbuf_t, copy); + if (err != TD_OK) + return err; + + /* Get the pointer to the thread descriptor with the last event. + If it doesn't match TH, then walk down the list until we find it. + We must splice it out of the list so that there is no dangling + pointer to it later when it dies. */ + err = DB_GET_SYMBOL (prevp, th->th_ta_p, __nptl_last_event); + if (err != TD_OK) + return err; + err = DB_GET_VALUE (thp, th->th_ta_p, __nptl_last_event, 0); + if (err != TD_OK) + return err; + + while (thp != 0) + { + psaddr_t next; + err = DB_GET_FIELD (next, th->th_ta_p, th->th_unique, pthread, + nextevent, 0); + if (err != TD_OK) + return err; + + if (next == thp) + return TD_DBERR; + + if (thp == th->th_unique) + { + /* PREVP points at this thread, splice it out. */ + psaddr_t next_nextp; + err = DB_GET_FIELD_ADDRESS (next_nextp, th->th_ta_p, next, pthread, + nextevent, 0); + assert (err == TD_OK); /* We used this field before. */ + if (prevp == next_nextp) + return TD_DBERR; + + err = _td_store_value (th->th_ta_p, + th->th_ta_p->ta_var___nptl_last_event, -1, + 0, prevp, next); + if (err != TD_OK) + return err; + + /* Now clear this thread's own next pointer so it's not dangling + when the thread resumes and then chains on for its next event. */ + return DB_PUT_FIELD (th->th_ta_p, thp, pthread, nextevent, 0, 0); + } + + err = DB_GET_FIELD_ADDRESS (prevp, th->th_ta_p, thp, pthread, + nextevent, 0); + assert (err == TD_OK); /* We used this field before. */ + thp = next; + } + + /* Ack! This should not happen. */ + return TD_DBERR; +} diff --git a/libpthread/nptl_db/td_thr_get_info.c b/libpthread/nptl_db/td_thr_get_info.c new file mode 100644 index 000000000..bb1388804 --- /dev/null +++ b/libpthread/nptl_db/td_thr_get_info.c @@ -0,0 +1,110 @@ +/* Get thread information. + Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 <stddef.h> +#include <string.h> +#include "thread_dbP.h" + + +td_err_e +td_thr_get_info (const td_thrhandle_t *th, td_thrinfo_t *infop) +{ + td_err_e err; + void *copy; + psaddr_t tls, schedpolicy, schedprio, cancelhandling, tid, report_events; + + LOG ("td_thr_get_info"); + + /* Copy the whole descriptor in once so we can access the several + fields locally. Excess copying in one go is much better than + multiple ps_pdread calls. */ + err = DB_GET_STRUCT (copy, th->th_ta_p, th->th_unique, pthread); + if (err != TD_OK) + return err; + + err = DB_GET_FIELD_ADDRESS (tls, th->th_ta_p, th->th_unique, + pthread, specific, 0); + if (err != TD_OK) + return err; + + err = DB_GET_FIELD_LOCAL (schedpolicy, th->th_ta_p, copy, pthread, + schedpolicy, 0); + if (err != TD_OK) + return err; + err = DB_GET_FIELD_LOCAL (schedprio, th->th_ta_p, copy, pthread, + schedparam_sched_priority, 0); + if (err != TD_OK) + return err; + err = DB_GET_FIELD_LOCAL (tid, th->th_ta_p, copy, pthread, tid, 0); + if (err != TD_OK) + return err; + err = DB_GET_FIELD_LOCAL (cancelhandling, th->th_ta_p, copy, pthread, + cancelhandling, 0); + if (err != TD_OK) + return err; + err = DB_GET_FIELD_LOCAL (report_events, th->th_ta_p, copy, pthread, + report_events, 0); + if (err != TD_OK) + return err; + + /* Fill in information. Clear first to provide reproducable + results for the fields we do not fill in. */ + memset (infop, '\0', sizeof (td_thrinfo_t)); + + infop->ti_tid = (thread_t) th->th_unique; + infop->ti_tls = (char *) tls; + infop->ti_pri = ((uintptr_t) schedpolicy == SCHED_OTHER + ? 0 : (uintptr_t) schedprio); + infop->ti_type = TD_THR_USER; + + if ((((int) (uintptr_t) cancelhandling) & EXITING_BITMASK) == 0) + /* XXX For now there is no way to get more information. */ + infop->ti_state = TD_THR_ACTIVE; + else if ((((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) == 0) + infop->ti_state = TD_THR_ZOMBIE; + else + infop->ti_state = TD_THR_UNKNOWN; + + /* Initialization which are the same in both cases. */ + infop->ti_ta_p = th->th_ta_p; + infop->ti_lid = tid == 0 ? ps_getpid (th->th_ta_p->ph) : (uintptr_t) tid; + infop->ti_traceme = report_events != 0; + + err = DB_GET_FIELD_LOCAL (infop->ti_startfunc, th->th_ta_p, copy, pthread, + start_routine, 0); + if (err == TD_OK) + { + uint32_t idx; + for (idx = 0; idx < TD_EVENTSIZE; ++idx) + { + psaddr_t word; + err = DB_GET_FIELD_LOCAL (word, th->th_ta_p, copy, pthread, + eventbuf_eventmask_event_bits, idx); + if (err != TD_OK) + break; + infop->ti_events.event_bits[idx] = (uintptr_t) word; + } + if (err == TD_NOAPLIC) + memset (&infop->ti_events.event_bits[idx], 0, + (TD_EVENTSIZE - idx) * sizeof infop->ti_events.event_bits[0]); + } + + return err; +} diff --git a/libpthread/nptl_db/td_thr_getfpregs.c b/libpthread/nptl_db/td_thr_getfpregs.c new file mode 100644 index 000000000..7760512eb --- /dev/null +++ b/libpthread/nptl_db/td_thr_getfpregs.c @@ -0,0 +1,53 @@ +/* Get a thread's floating-point register set. + Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_thr_getfpregs (const td_thrhandle_t *th, prfpregset_t *regset) +{ + psaddr_t cancelhandling, tid; + td_err_e err; + + LOG ("td_thr_getfpregs"); + + /* We have to get the state and the PID for this thread. */ + err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread, + cancelhandling, 0); + if (err != TD_OK) + return err; + + /* If the thread already terminated we return all zeroes. */ + if (((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) + memset (regset, '\0', sizeof (*regset)); + /* Otherwise get the register content through the callback. */ + else + { + err = DB_GET_FIELD (tid, th->th_ta_p, th->th_unique, pthread, tid, 0); + if (err != TD_OK) + return err; + + if (ps_lgetfpregs (th->th_ta_p->ph, (uintptr_t) tid, regset) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/libpthread/nptl_db/td_thr_getgregs.c b/libpthread/nptl_db/td_thr_getgregs.c new file mode 100644 index 000000000..4c2373ef6 --- /dev/null +++ b/libpthread/nptl_db/td_thr_getgregs.c @@ -0,0 +1,53 @@ +/* Get a thread's general register set. + Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_thr_getgregs (const td_thrhandle_t *th, prgregset_t regset) +{ + psaddr_t cancelhandling, tid; + td_err_e err; + + LOG ("td_thr_getgregs"); + + /* We have to get the state and the PID for this thread. */ + err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread, + cancelhandling, 0); + if (err != TD_OK) + return err; + + /* If the thread already terminated we return all zeroes. */ + if (((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) + memset (regset, '\0', sizeof (*regset)); + /* Otherwise get the register content through the callback. */ + else + { + err = DB_GET_FIELD (tid, th->th_ta_p, th->th_unique, pthread, tid, 0); + if (err != TD_OK) + return err; + + if (ps_lgetregs (th->th_ta_p->ph, (uintptr_t) tid, regset) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/libpthread/nptl_db/td_thr_getxregs.c b/libpthread/nptl_db/td_thr_getxregs.c new file mode 100644 index 000000000..3c77ab6be --- /dev/null +++ b/libpthread/nptl_db/td_thr_getxregs.c @@ -0,0 +1,30 @@ +/* Get a thread's extra state register set. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_thr_getxregs (const td_thrhandle_t *th, void *xregs) +{ + /* XXX This might be platform specific. */ + LOG ("td_thr_getxregs"); + return TD_NOXREGS; +} diff --git a/libpthread/nptl_db/td_thr_getxregsize.c b/libpthread/nptl_db/td_thr_getxregsize.c new file mode 100644 index 000000000..1704e4b0a --- /dev/null +++ b/libpthread/nptl_db/td_thr_getxregsize.c @@ -0,0 +1,30 @@ +/* Get the size of the extra state register set for this architecture. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_thr_getxregsize (const td_thrhandle_t *th, int *sizep) +{ + /* XXX This might be platform specific. */ + LOG ("td_thr_getxregsize"); + return TD_NOXREGS; +} diff --git a/libpthread/nptl_db/td_thr_set_event.c b/libpthread/nptl_db/td_thr_set_event.c new file mode 100644 index 000000000..6617147a8 --- /dev/null +++ b/libpthread/nptl_db/td_thr_set_event.c @@ -0,0 +1,77 @@ +/* Enable specific event for thread. + Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 <stddef.h> + +#include "thread_dbP.h" + + +td_err_e +td_thr_set_event (th, event) + const td_thrhandle_t *th; + td_thr_events_t *event; +{ + td_err_e err; + psaddr_t eventmask; + void *copy = NULL; + + LOG ("td_thr_set_event"); + + /* Fetch the old event mask from the inferior and modify it in place. */ + err = DB_GET_FIELD_ADDRESS (eventmask, th->th_ta_p, + th->th_unique, pthread, eventbuf_eventmask, 0); + if (err == TD_OK) + err = DB_GET_STRUCT (copy, th->th_ta_p, eventmask, td_thr_events_t); + if (err == TD_OK) + { + uint32_t idx; + for (idx = 0; idx < TD_EVENTSIZE; ++idx) + { + psaddr_t word; + uint32_t mask; + err = DB_GET_FIELD_LOCAL (word, th->th_ta_p, copy, + td_thr_events_t, event_bits, idx); + if (err != TD_OK) + break; + mask = (uintptr_t) word; + mask |= event->event_bits[idx]; + word = (psaddr_t) (uintptr_t) mask; + err = DB_PUT_FIELD_LOCAL (th->th_ta_p, copy, + td_thr_events_t, event_bits, idx, word); + if (err != TD_OK) + break; + } + if (err == TD_NOAPLIC) + { + err = TD_OK; + while (idx < TD_EVENTSIZE) + if (event->event_bits[idx++] != 0) + { + err = TD_NOEVENT; + break; + } + } + if (err == TD_OK) + /* Now write it back to the inferior. */ + err = DB_PUT_STRUCT (th->th_ta_p, eventmask, td_thr_events_t, copy); + } + + return err; +} diff --git a/libpthread/nptl_db/td_thr_setfpregs.c b/libpthread/nptl_db/td_thr_setfpregs.c new file mode 100644 index 000000000..01bdb5323 --- /dev/null +++ b/libpthread/nptl_db/td_thr_setfpregs.c @@ -0,0 +1,50 @@ +/* Set a thread's floating-point register set. + Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_thr_setfpregs (const td_thrhandle_t *th, const prfpregset_t *fpregs) +{ + psaddr_t cancelhandling, tid; + td_err_e err; + + LOG ("td_thr_setfpregs"); + + /* We have to get the state and the PID for this thread. */ + err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread, + cancelhandling, 0); + if (err != TD_OK) + return err; + + /* Only set the registers if the thread hasn't yet terminated. */ + if ((((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) == 0) + { + err = DB_GET_FIELD (tid, th->th_ta_p, th->th_unique, pthread, tid, 0); + if (err != TD_OK) + return err; + + if (ps_lsetfpregs (th->th_ta_p->ph, (uintptr_t) tid, fpregs) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/libpthread/nptl_db/td_thr_setgregs.c b/libpthread/nptl_db/td_thr_setgregs.c new file mode 100644 index 000000000..2a9ce7e01 --- /dev/null +++ b/libpthread/nptl_db/td_thr_setgregs.c @@ -0,0 +1,50 @@ +/* Set a thread's general register set. + Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_thr_setgregs (const td_thrhandle_t *th, prgregset_t gregs) +{ + psaddr_t cancelhandling, tid; + td_err_e err; + + LOG ("td_thr_setgregs"); + + /* We have to get the state and the PID for this thread. */ + err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread, + cancelhandling, 0); + if (err != TD_OK) + return err; + + /* Only set the registers if the thread hasn't yet terminated. */ + if ((((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) == 0) + { + err = DB_GET_FIELD (tid, th->th_ta_p, th->th_unique, pthread, tid, 0); + if (err != TD_OK) + return err; + + if (ps_lsetregs (th->th_ta_p->ph, tid - (psaddr_t) 0, gregs) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/libpthread/nptl_db/td_thr_setprio.c b/libpthread/nptl_db/td_thr_setprio.c new file mode 100644 index 000000000..6032b0ed4 --- /dev/null +++ b/libpthread/nptl_db/td_thr_setprio.c @@ -0,0 +1,30 @@ +/* Set a thread's priority. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_thr_setprio (const td_thrhandle_t *th, int prio) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_setprio"); + return TD_OK; +} diff --git a/libpthread/nptl_db/td_thr_setsigpending.c b/libpthread/nptl_db/td_thr_setsigpending.c new file mode 100644 index 000000000..e2c9d7ad2 --- /dev/null +++ b/libpthread/nptl_db/td_thr_setsigpending.c @@ -0,0 +1,31 @@ +/* Raise a signal for a thread. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_thr_setsigpending (const td_thrhandle_t *th, unsigned char n, + const sigset_t *ss) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_setsigpending"); + return TD_OK; +} diff --git a/libpthread/nptl_db/td_thr_setxregs.c b/libpthread/nptl_db/td_thr_setxregs.c new file mode 100644 index 000000000..f48877c78 --- /dev/null +++ b/libpthread/nptl_db/td_thr_setxregs.c @@ -0,0 +1,30 @@ +/* Set a thread's extra state register set. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_thr_setxregs (const td_thrhandle_t *ta, const void *addr) +{ + /* XXX This might have to be platform specific. */ + LOG ("td_thr_setxregs"); + return TD_NOXREGS; +} diff --git a/libpthread/nptl_db/td_thr_sigsetmask.c b/libpthread/nptl_db/td_thr_sigsetmask.c new file mode 100644 index 000000000..3a68aecd3 --- /dev/null +++ b/libpthread/nptl_db/td_thr_sigsetmask.c @@ -0,0 +1,30 @@ +/* Set a thread's signal mask. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_thr_sigsetmask (const td_thrhandle_t *th, const sigset_t *ss) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_sigsetmask"); + return TD_OK; +} diff --git a/libpthread/nptl_db/td_thr_tls_get_addr.c b/libpthread/nptl_db/td_thr_tls_get_addr.c new file mode 100644 index 000000000..e7d232272 --- /dev/null +++ b/libpthread/nptl_db/td_thr_tls_get_addr.c @@ -0,0 +1,43 @@ +/* Get address of thread local variable. + Copyright (C) 2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <link.h> +#include "thread_dbP.h" + +td_err_e +td_thr_tls_get_addr (const td_thrhandle_t *th, + psaddr_t map_address, size_t offset, psaddr_t *address) +{ + td_err_e err; + psaddr_t modid; + + /* Get the TLS module ID from the `struct link_map' in the inferior. */ + err = DB_GET_FIELD (modid, th->th_ta_p, map_address, link_map, + l_tls_modid, 0); + if (err == TD_NOCAPAB) + return TD_NOAPLIC; + if (err == TD_OK) + { + err = td_thr_tlsbase (th, (uintptr_t) modid, address); + if (err == TD_OK) + *address += offset; + } + return err; +} diff --git a/libpthread/nptl_db/td_thr_tlsbase.c b/libpthread/nptl_db/td_thr_tlsbase.c new file mode 100644 index 000000000..aaeda6f3c --- /dev/null +++ b/libpthread/nptl_db/td_thr_tlsbase.c @@ -0,0 +1,55 @@ +/* Locate TLS data for a thread. + Copyright (C) 2003, 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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + +td_err_e +td_thr_tlsbase (const td_thrhandle_t *th, + unsigned long int modid, + psaddr_t *base) +{ + td_err_e err; + psaddr_t dtv, dtvslot, dtvptr; + + if (modid < 1) + return TD_NOTLS; + + /* Get the DTV pointer from the thread descriptor. */ + err = DB_GET_FIELD (dtv, th->th_ta_p, th->th_unique, pthread, dtvp, 0); + if (err != TD_OK) + return err; + + /* Find the corresponding entry in the DTV. */ + err = DB_GET_FIELD_ADDRESS (dtvslot, th->th_ta_p, dtv, dtv, dtv, modid); + if (err != TD_OK) + return err; + + /* Extract the TLS block address from that DTV slot. */ + err = DB_GET_FIELD (dtvptr, th->th_ta_p, dtvslot, dtv_t, pointer_val, 0); + if (err != TD_OK) + return err; + + /* It could be that the memory for this module is not allocated for + the given thread. */ + if ((uintptr_t) dtvptr & 1) + return TD_TLSDEFER; + + *base = dtvptr; + return TD_OK; +} diff --git a/libpthread/nptl_db/td_thr_tsd.c b/libpthread/nptl_db/td_thr_tsd.c new file mode 100644 index 000000000..08f617b7d --- /dev/null +++ b/libpthread/nptl_db/td_thr_tsd.c @@ -0,0 +1,96 @@ +/* Get a thread-specific data pointer for a thread. + Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" + + +td_err_e +td_thr_tsd (const td_thrhandle_t *th, const thread_key_t tk, void **data) +{ + td_err_e err; + psaddr_t tk_seq, level1, level2, seq, value; + void *copy; + uint32_t pthread_key_2ndlevel_size, idx1st, idx2nd; + + LOG ("td_thr_tsd"); + + /* Get the key entry. */ + err = DB_GET_VALUE (tk_seq, th->th_ta_p, __pthread_keys, tk); + if (err == TD_NOAPLIC) + return TD_BADKEY; + if (err != TD_OK) + return err; + + /* Fail if this key is not at all used. */ + if (((uintptr_t) tk_seq & 1) == 0) + return TD_BADKEY; + + /* This makes sure we have the size information on hand. */ + err = DB_GET_FIELD_ADDRESS (level2, th->th_ta_p, 0, pthread_key_data_level2, + data, 1); + if (err != TD_OK) + return err; + + /* Compute the indeces. */ + pthread_key_2ndlevel_size + = DB_DESC_NELEM (th->th_ta_p->ta_field_pthread_key_data_level2_data); + idx1st = tk / pthread_key_2ndlevel_size; + idx2nd = tk % pthread_key_2ndlevel_size; + + /* Now fetch the first level pointer. */ + err = DB_GET_FIELD (level1, th->th_ta_p, th->th_unique, pthread, + specific, idx1st); + if (err == TD_NOAPLIC) + return TD_DBERR; + if (err != TD_OK) + return err; + + /* Check the pointer to the second level array. */ + if (level1 == 0) + return TD_NOTSD; + + /* Locate the element within the second level array. */ + err = DB_GET_FIELD_ADDRESS (level2, th->th_ta_p, + level1, pthread_key_data_level2, data, idx2nd); + if (err == TD_NOAPLIC) + return TD_DBERR; + if (err != TD_OK) + return err; + + /* Now copy in that whole structure. */ + err = DB_GET_STRUCT (copy, th->th_ta_p, level2, pthread_key_data); + if (err != TD_OK) + return err; + + /* Check whether the data is valid. */ + err = DB_GET_FIELD_LOCAL (seq, th->th_ta_p, copy, pthread_key_data, seq, 0); + if (err != TD_OK) + return err; + if (seq != tk_seq) + return TD_NOTSD; + + /* Finally, fetch the value. */ + err = DB_GET_FIELD_LOCAL (value, th->th_ta_p, copy, pthread_key_data, + data, 0); + if (err == TD_OK) + *data = value; + + return err; +} diff --git a/libpthread/nptl_db/td_thr_validate.c b/libpthread/nptl_db/td_thr_validate.c new file mode 100644 index 000000000..19ee940d6 --- /dev/null +++ b/libpthread/nptl_db/td_thr_validate.c @@ -0,0 +1,91 @@ +/* Validate a thread handle. + Copyright (C) 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1999. + + 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 "thread_dbP.h" +#include <stdbool.h> + +static td_err_e +check_thread_list (const td_thrhandle_t *th, psaddr_t head, bool *uninit) +{ + td_err_e err; + psaddr_t next, ofs; + + err = DB_GET_FIELD (next, th->th_ta_p, head, list_t, next, 0); + if (err == TD_OK) + { + if (next == 0) + { + *uninit = true; + return TD_NOTHR; + } + err = DB_GET_FIELD_ADDRESS (ofs, th->th_ta_p, 0, pthread, list, 0); + } + + while (err == TD_OK) + { + if (next == head) + return TD_NOTHR; + + if (next - (ofs - (psaddr_t) 0) == th->th_unique) + return TD_OK; + + err = DB_GET_FIELD (next, th->th_ta_p, next, list_t, next, 0); + } + + return err; +} + + +td_err_e +td_thr_validate (const td_thrhandle_t *th) +{ + td_err_e err; + psaddr_t list = NULL; + + LOG ("td_thr_validate"); + + /* First check the list with threads using user allocated stacks. */ + bool uninit = false; + err = DB_GET_SYMBOL (list, th->th_ta_p, __stack_user); + if (err == TD_OK) + err = check_thread_list (th, list, &uninit); + + /* If our thread is not on this list search the list with stack + using implementation allocated stacks. */ + if (err == TD_NOTHR) + { + err = DB_GET_SYMBOL (list, th->th_ta_p, stack_used); + if (err == TD_OK) + err = check_thread_list (th, list, &uninit); + + if (err == TD_NOTHR && uninit) + { + /* __pthread_initialize_minimal has not run yet. + But the main thread still has a valid ID. */ + td_thrhandle_t main_th; + err = td_ta_map_lwp2thr (th->th_ta_p, + ps_getpid (th->th_ta_p->ph), &main_th); + if (err == TD_OK && th->th_unique != main_th.th_unique) + err = TD_NOTHR; + } + } + + return err; +} diff --git a/libpthread/nptl_db/thread_db.h b/libpthread/nptl_db/thread_db.h new file mode 100644 index 000000000..433b54fd5 --- /dev/null +++ b/libpthread/nptl_db/thread_db.h @@ -0,0 +1,459 @@ +/* thread_db.h -- interface to libthread_db.so library for debugging -lpthread + Copyright (C) 1999,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; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _THREAD_DB_H +#define _THREAD_DB_H 1 + +/* This is the debugger interface for the NPTL library. It is + modelled closely after the interface with same names in Solaris + with the goal to share the same code in the debugger. */ +#include <pthread.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/procfs.h> + + +/* Error codes of the library. */ +typedef enum +{ + TD_OK, /* No error. */ + TD_ERR, /* No further specified error. */ + TD_NOTHR, /* No matching thread found. */ + TD_NOSV, /* No matching synchronization handle found. */ + TD_NOLWP, /* No matching light-weighted process found. */ + TD_BADPH, /* Invalid process handle. */ + TD_BADTH, /* Invalid thread handle. */ + TD_BADSH, /* Invalid synchronization handle. */ + TD_BADTA, /* Invalid thread agent. */ + TD_BADKEY, /* Invalid key. */ + TD_NOMSG, /* No event available. */ + TD_NOFPREGS, /* No floating-point register content available. */ + TD_NOLIBTHREAD, /* Application not linked with thread library. */ + TD_NOEVENT, /* Requested event is not supported. */ + TD_NOCAPAB, /* Capability not available. */ + TD_DBERR, /* Internal debug library error. */ + TD_NOAPLIC, /* Operation is not applicable. */ + TD_NOTSD, /* No thread-specific data available. */ + TD_MALLOC, /* Out of memory. */ + TD_PARTIALREG, /* Not entire register set was read or written. */ + TD_NOXREGS, /* X register set not available for given thread. */ + TD_TLSDEFER, /* Thread has not yet allocated TLS for given module. */ + TD_NOTALLOC = TD_TLSDEFER, + TD_VERSION, /* Version if libpthread and libthread_db do not match. */ + TD_NOTLS /* There is no TLS segment in the given module. */ +} td_err_e; + + +/* Possible thread states. TD_THR_ANY_STATE is a pseudo-state used to + select threads regardless of state in td_ta_thr_iter(). */ +typedef enum +{ + TD_THR_ANY_STATE, + TD_THR_UNKNOWN, + TD_THR_STOPPED, + TD_THR_RUN, + TD_THR_ACTIVE, + TD_THR_ZOMBIE, + TD_THR_SLEEP, + TD_THR_STOPPED_ASLEEP +} td_thr_state_e; + +/* Thread type: user or system. TD_THR_ANY_TYPE is a pseudo-type used + to select threads regardless of type in td_ta_thr_iter(). */ +typedef enum +{ + TD_THR_ANY_TYPE, + TD_THR_USER, + TD_THR_SYSTEM +} td_thr_type_e; + + +/* Types of the debugging library. */ + +/* Handle for a process. This type is opaque. */ +typedef struct td_thragent td_thragent_t; + +/* The actual thread handle type. This is also opaque. */ +typedef struct td_thrhandle +{ + td_thragent_t *th_ta_p; + psaddr_t th_unique; +} td_thrhandle_t; + + +/* Forward declaration of a type defined by and for the dynamic linker. */ +struct link_map; + + +/* Flags for `td_ta_thr_iter'. */ +#define TD_THR_ANY_USER_FLAGS 0xffffffff +#define TD_THR_LOWEST_PRIORITY -20 +#define TD_SIGNO_MASK NULL + + +#define TD_EVENTSIZE 2 +#define BT_UISHIFT 5 /* log base 2 of BT_NBIPUI, to extract word index */ +#define BT_NBIPUI (1 << BT_UISHIFT) /* n bits per uint */ +#define BT_UIMASK (BT_NBIPUI - 1) /* to extract bit index */ + +/* Bitmask of enabled events. */ +typedef struct td_thr_events +{ + uint32_t event_bits[TD_EVENTSIZE]; +} td_thr_events_t; + +/* Event set manipulation macros. */ +#define __td_eventmask(n) \ + (UINT32_C (1) << (((n) - 1) & BT_UIMASK)) +#define __td_eventword(n) \ + ((UINT32_C ((n) - 1)) >> BT_UISHIFT) + +#define td_event_emptyset(setp) \ + do { \ + int __i; \ + for (__i = TD_EVENTSIZE; __i > 0; --__i) \ + (setp)->event_bits[__i - 1] = 0; \ + } while (0) + +#define td_event_fillset(setp) \ + do { \ + int __i; \ + for (__i = TD_EVENTSIZE; __i > 0; --__i) \ + (setp)->event_bits[__i - 1] = UINT32_C (0xffffffff); \ + } while (0) + +#define td_event_addset(setp, n) \ + (((setp)->event_bits[__td_eventword (n)]) |= __td_eventmask (n)) +#define td_event_delset(setp, n) \ + (((setp)->event_bits[__td_eventword (n)]) &= ~__td_eventmask (n)) +#define td_eventismember(setp, n) \ + (__td_eventmask (n) & ((setp)->event_bits[__td_eventword (n)])) +#if TD_EVENTSIZE == 2 +# define td_eventisempty(setp) \ + (!((setp)->event_bits[0]) && !((setp)->event_bits[1])) +#else +# error "td_eventisempty must be changed to match TD_EVENTSIZE" +#endif + +/* Events reportable by the thread implementation. */ +typedef enum +{ + TD_ALL_EVENTS, /* Pseudo-event number. */ + TD_EVENT_NONE = TD_ALL_EVENTS, /* Depends on context. */ + TD_READY, /* Is executable now. */ + TD_SLEEP, /* Blocked in a synchronization obj. */ + TD_SWITCHTO, /* Now assigned to a process. */ + TD_SWITCHFROM, /* Not anymore assigned to a process. */ + TD_LOCK_TRY, /* Trying to get an unavailable lock. */ + TD_CATCHSIG, /* Signal posted to the thread. */ + TD_IDLE, /* Process getting idle. */ + TD_CREATE, /* New thread created. */ + TD_DEATH, /* Thread terminated. */ + TD_PREEMPT, /* Preempted. */ + TD_PRI_INHERIT, /* Inherited elevated priority. */ + TD_REAP, /* Reaped. */ + TD_CONCURRENCY, /* Number of processes changing. */ + TD_TIMEOUT, /* Conditional variable wait timed out. */ + TD_MIN_EVENT_NUM = TD_READY, + TD_MAX_EVENT_NUM = TD_TIMEOUT, + TD_EVENTS_ENABLE = 31 /* Event reporting enabled. */ +} td_event_e; + +/* Values representing the different ways events are reported. */ +typedef enum +{ + NOTIFY_BPT, /* User must insert breakpoint at u.bptaddr. */ + NOTIFY_AUTOBPT, /* Breakpoint at u.bptaddr is automatically + inserted. */ + NOTIFY_SYSCALL /* System call u.syscallno will be invoked. */ +} td_notify_e; + +/* Description how event type is reported. */ +typedef struct td_notify +{ + td_notify_e type; /* Way the event is reported. */ + union + { + psaddr_t bptaddr; /* Address of breakpoint. */ + int syscallno; /* Number of system call used. */ + } u; +} td_notify_t; + +/* Structure used to report event. */ +typedef struct td_event_msg +{ + td_event_e event; /* Event type being reported. */ + const td_thrhandle_t *th_p; /* Thread reporting the event. */ + union + { +# if 0 + td_synchandle_t *sh; /* Handle of synchronization object. */ +#endif + uintptr_t data; /* Event specific data. */ + } msg; +} td_event_msg_t; + +/* Structure containing event data available in each thread structure. */ +typedef struct +{ + td_thr_events_t eventmask; /* Mask of enabled events. */ + td_event_e eventnum; /* Number of last event. */ + void *eventdata; /* Data associated with event. */ +} td_eventbuf_t; + + +/* Gathered statistics about the process. */ +typedef struct td_ta_stats +{ + int nthreads; /* Total number of threads in use. */ + int r_concurrency; /* Concurrency level requested by user. */ + int nrunnable_num; /* Average runnable threads, numerator. */ + int nrunnable_den; /* Average runnable threads, denominator. */ + int a_concurrency_num; /* Achieved concurrency level, numerator. */ + int a_concurrency_den; /* Achieved concurrency level, denominator. */ + int nlwps_num; /* Average number of processes in use, + numerator. */ + int nlwps_den; /* Average number of processes in use, + denominator. */ + int nidle_num; /* Average number of idling processes, + numerator. */ + int nidle_den; /* Average number of idling processes, + denominator. */ +} td_ta_stats_t; + + +/* Since Sun's library is based on Solaris threads we have to define a few + types to map them to POSIX threads. */ +typedef pthread_t thread_t; +typedef pthread_key_t thread_key_t; + + +/* Callback for iteration over threads. */ +typedef int td_thr_iter_f (const td_thrhandle_t *, void *); + +/* Callback for iteration over thread local data. */ +typedef int td_key_iter_f (thread_key_t, void (*) (void *), void *); + + + +/* Forward declaration. This has to be defined by the user. */ +struct ps_prochandle; + + +/* Information about the thread. */ +typedef struct td_thrinfo +{ + td_thragent_t *ti_ta_p; /* Process handle. */ + unsigned int ti_user_flags; /* Unused. */ + thread_t ti_tid; /* Thread ID returned by + pthread_create(). */ + char *ti_tls; /* Pointer to thread-local data. */ + psaddr_t ti_startfunc; /* Start function passed to + pthread_create(). */ + psaddr_t ti_stkbase; /* Base of thread's stack. */ + long int ti_stksize; /* Size of thread's stack. */ + psaddr_t ti_ro_area; /* Unused. */ + int ti_ro_size; /* Unused. */ + td_thr_state_e ti_state; /* Thread state. */ + unsigned char ti_db_suspended; /* Nonzero if suspended by debugger. */ + td_thr_type_e ti_type; /* Type of the thread (system vs + user thread). */ + intptr_t ti_pc; /* Unused. */ + intptr_t ti_sp; /* Unused. */ + short int ti_flags; /* Unused. */ + int ti_pri; /* Thread priority. */ + lwpid_t ti_lid; /* Kernel PID for this thread. */ + sigset_t ti_sigmask; /* Signal mask. */ + unsigned char ti_traceme; /* Nonzero if event reporting + enabled. */ + unsigned char ti_preemptflag; /* Unused. */ + unsigned char ti_pirecflag; /* Unused. */ + sigset_t ti_pending; /* Set of pending signals. */ + td_thr_events_t ti_events; /* Set of enabled events. */ +} td_thrinfo_t; + + + +/* Prototypes for exported library functions. */ + +/* Initialize the thread debug support library. */ +extern td_err_e td_init (void); + +/* Historical relict. Should not be used anymore. */ +extern td_err_e td_log (void); + +/* Return list of symbols the library can request. */ +extern const char **td_symbol_list (void); + +/* Generate new thread debug library handle for process PS. */ +extern td_err_e td_ta_new (struct ps_prochandle *__ps, td_thragent_t **__ta); + +/* Free resources allocated for TA. */ +extern td_err_e td_ta_delete (td_thragent_t *__ta); + +/* Get number of currently running threads in process associated with TA. */ +extern td_err_e td_ta_get_nthreads (const td_thragent_t *__ta, int *__np); + +/* Return process handle passed in `td_ta_new' for process associated with + TA. */ +extern td_err_e td_ta_get_ph (const td_thragent_t *__ta, + struct ps_prochandle **__ph); + +/* Map thread library handle PT to thread debug library handle for process + associated with TA and store result in *TH. */ +extern td_err_e td_ta_map_id2thr (const td_thragent_t *__ta, pthread_t __pt, + td_thrhandle_t *__th); + +/* Map process ID LWPID to thread debug library handle for process + associated with TA and store result in *TH. */ +extern td_err_e td_ta_map_lwp2thr (const td_thragent_t *__ta, lwpid_t __lwpid, + td_thrhandle_t *__th); + + +/* Call for each thread in a process associated with TA the callback function + CALLBACK. */ +extern td_err_e td_ta_thr_iter (const td_thragent_t *__ta, + td_thr_iter_f *__callback, void *__cbdata_p, + td_thr_state_e __state, int __ti_pri, + sigset_t *__ti_sigmask_p, + unsigned int __ti_user_flags); + +/* Call for each defined thread local data entry the callback function KI. */ +extern td_err_e td_ta_tsd_iter (const td_thragent_t *__ta, td_key_iter_f *__ki, + void *__p); + + +/* Get event address for EVENT. */ +extern td_err_e td_ta_event_addr (const td_thragent_t *__ta, + td_event_e __event, td_notify_t *__ptr); + +/* Enable EVENT in global mask. */ +extern td_err_e td_ta_set_event (const td_thragent_t *__ta, + td_thr_events_t *__event); + +/* Disable EVENT in global mask. */ +extern td_err_e td_ta_clear_event (const td_thragent_t *__ta, + td_thr_events_t *__event); + +/* Return information about last event. */ +extern td_err_e td_ta_event_getmsg (const td_thragent_t *__ta, + td_event_msg_t *__msg); + + +/* Set suggested concurrency level for process associated with TA. */ +extern td_err_e td_ta_setconcurrency (const td_thragent_t *__ta, int __level); + + +/* Enable collecting statistics for process associated with TA. */ +extern td_err_e td_ta_enable_stats (const td_thragent_t *__ta, int __enable); + +/* Reset statistics. */ +extern td_err_e td_ta_reset_stats (const td_thragent_t *__ta); + +/* Retrieve statistics from process associated with TA. */ +extern td_err_e td_ta_get_stats (const td_thragent_t *__ta, + td_ta_stats_t *__statsp); + + +/* Validate that TH is a thread handle. */ +extern td_err_e td_thr_validate (const td_thrhandle_t *__th); + +/* Return information about thread TH. */ +extern td_err_e td_thr_get_info (const td_thrhandle_t *__th, + td_thrinfo_t *__infop); + +/* Retrieve floating-point register contents of process running thread TH. */ +extern td_err_e td_thr_getfpregs (const td_thrhandle_t *__th, + prfpregset_t *__regset); + +/* Retrieve general register contents of process running thread TH. */ +extern td_err_e td_thr_getgregs (const td_thrhandle_t *__th, + prgregset_t __gregs); + +/* Retrieve extended register contents of process running thread TH. */ +extern td_err_e td_thr_getxregs (const td_thrhandle_t *__th, void *__xregs); + +/* Get size of extended register set of process running thread TH. */ +extern td_err_e td_thr_getxregsize (const td_thrhandle_t *__th, int *__sizep); + +/* Set floating-point register contents of process running thread TH. */ +extern td_err_e td_thr_setfpregs (const td_thrhandle_t *__th, + const prfpregset_t *__fpregs); + +/* Set general register contents of process running thread TH. */ +extern td_err_e td_thr_setgregs (const td_thrhandle_t *__th, + prgregset_t __gregs); + +/* Set extended register contents of process running thread TH. */ +extern td_err_e td_thr_setxregs (const td_thrhandle_t *__th, + const void *__addr); + + +/* Get address of the given module's TLS storage area for the given thread. */ +extern td_err_e td_thr_tlsbase (const td_thrhandle_t *__th, + unsigned long int __modid, + psaddr_t *__base); + +/* Get address of thread local variable. */ +extern td_err_e td_thr_tls_get_addr (const td_thrhandle_t *__th, + psaddr_t __map_address, size_t __offset, + psaddr_t *__address); + + +/* Enable reporting for EVENT for thread TH. */ +extern td_err_e td_thr_event_enable (const td_thrhandle_t *__th, int __event); + +/* Enable EVENT for thread TH. */ +extern td_err_e td_thr_set_event (const td_thrhandle_t *__th, + td_thr_events_t *__event); + +/* Disable EVENT for thread TH. */ +extern td_err_e td_thr_clear_event (const td_thrhandle_t *__th, + td_thr_events_t *__event); + +/* Get event message for thread TH. */ +extern td_err_e td_thr_event_getmsg (const td_thrhandle_t *__th, + td_event_msg_t *__msg); + + +/* Set priority of thread TH. */ +extern td_err_e td_thr_setprio (const td_thrhandle_t *__th, int __prio); + + +/* Set pending signals for thread TH. */ +extern td_err_e td_thr_setsigpending (const td_thrhandle_t *__th, + unsigned char __n, const sigset_t *__ss); + +/* Set signal mask for thread TH. */ +extern td_err_e td_thr_sigsetmask (const td_thrhandle_t *__th, + const sigset_t *__ss); + + +/* Return thread local data associated with key TK in thread TH. */ +extern td_err_e td_thr_tsd (const td_thrhandle_t *__th, + const thread_key_t __tk, void **__data); + + +/* Suspend execution of thread TH. */ +extern td_err_e td_thr_dbsuspend (const td_thrhandle_t *__th); + +/* Resume execution of thread TH. */ +extern td_err_e td_thr_dbresume (const td_thrhandle_t *__th); + +#endif /* thread_db.h */ diff --git a/libpthread/nptl_db/thread_dbP.h b/libpthread/nptl_db/thread_dbP.h new file mode 100644 index 000000000..c3d263b0c --- /dev/null +++ b/libpthread/nptl_db/thread_dbP.h @@ -0,0 +1,258 @@ +/* Private header for thread debug library + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _THREAD_DBP_H +#define _THREAD_DBP_H 1 + +#include <stdbool.h> +#include <stdint.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <assert.h> +#include "proc_service.h" +#include "thread_db.h" +#include "../nptl/pthreadP.h" /* This is for *_BITMASK only. */ + +#ifdef __UCLIBC__ +#define __alloca alloca +#endif + +/* Indeces for the symbol names. */ +enum + { +# define DB_STRUCT(type) SYM_SIZEOF_##type, +# define DB_STRUCT_FIELD(type, field) SYM_##type##_FIELD_##field, +# define DB_SYMBOL(name) SYM_##name, +# define DB_FUNCTION(name) SYM_##name, +# define DB_VARIABLE(name) SYM_##name, SYM_DESC_##name, +# include "structs.def" +# undef DB_STRUCT +# undef DB_STRUCT_FIELD +# undef DB_SYMBOL +# undef DB_FUNCTION +# undef DB_VARIABLE + + SYM_TH_UNIQUE_CONST_THREAD_AREA, + SYM_TH_UNIQUE_REGISTER64, + SYM_TH_UNIQUE_REGISTER32, + SYM_TH_UNIQUE_REGISTER64_THREAD_AREA, + SYM_TH_UNIQUE_REGISTER32_THREAD_AREA, + + SYM_NUM_MESSAGES + }; + + +/* Comment out the following for less verbose output. */ +#ifndef NDEBUG +# define LOG(c) if (__td_debug) write (2, c "\n", strlen (c "\n")) +extern int __td_debug attribute_hidden; +#else +# define LOG(c) +#endif + + +#define DB_DESC_SIZE(desc) ((desc)[0]) +#define DB_DESC_NELEM(desc) ((desc)[1]) +#define DB_DESC_OFFSET(desc) ((desc)[2]) +#define DB_SIZEOF_DESC (3 * sizeof (uint32_t)) +#define DB_DEFINE_DESC(name, size, nelem, offset) \ + const uint32_t name[3] = { (size), (nelem), (offset) } +typedef uint32_t db_desc_t[3]; + + +/* Handle for a process. This type is opaque. */ +struct td_thragent +{ + /* Chain on the list of all agent structures. */ + list_t list; + + /* Delivered by the debugger and we have to pass it back in the + proc callbacks. */ + struct ps_prochandle *ph; + + /* Cached values read from the inferior. */ +# define DB_STRUCT(type) \ + uint32_t ta_sizeof_##type; +# define DB_STRUCT_FIELD(type, field) \ + db_desc_t ta_field_##type##_##field; +# define DB_SYMBOL(name) \ + psaddr_t ta_addr_##name; +# define DB_FUNCTION(name) \ + psaddr_t ta_addr_##name; +# define DB_VARIABLE(name) \ + psaddr_t ta_addr_##name; \ + db_desc_t ta_var_##name; +# include "structs.def" +# undef DB_STRUCT +# undef DB_STRUCT_FIELD +# undef DB_FUNCTION +# undef DB_SYMBOL +# undef DB_VARIABLE + + /* The method of locating a thread's th_unique value. */ + enum + { + ta_howto_unknown, + ta_howto_reg, + ta_howto_reg_thread_area, + ta_howto_const_thread_area + } ta_howto; + union + { + uint32_t const_thread_area; /* Constant argument to ps_get_thread_area. */ + /* These are as if the descriptor of the field in prregset_t, + but DB_DESC_NELEM is overloaded as follows: */ + db_desc_t reg; /* Signed bias applied to register value. */ + db_desc_t reg_thread_area; /* Bits to scale down register value. */ + } ta_howto_data; +}; + + +/* List of all known descriptors. */ +extern list_t __td_agent_list attribute_hidden; + + +/* Function used to test for correct thread agent pointer. */ +static inline bool +ta_ok (const td_thragent_t *ta) +{ + list_t *runp; + + list_for_each (runp, &__td_agent_list) + if (list_entry (runp, td_thragent_t, list) == ta) + return true; + + return false; +} + + +/* Internal wrapper around ps_pglobal_lookup. */ +extern ps_err_e td_lookup (struct ps_prochandle *ps, + int idx, psaddr_t *sym_addr) attribute_hidden; + + + + +/* Store in psaddr_t VAR the address of inferior's symbol NAME. */ +#define DB_GET_SYMBOL(var, ta, name) \ + (((ta)->ta_addr_##name == 0 \ + && td_lookup ((ta)->ph, SYM_##name, &(ta)->ta_addr_##name) != PS_OK) \ + ? TD_ERR : ((var) = (ta)->ta_addr_##name, TD_OK)) + +/* Store in psaddr_t VAR the value of ((TYPE) PTR)->FIELD[IDX] in the inferior. + A target field smaller than psaddr_t is zero-extended. */ +#define DB_GET_FIELD(var, ta, ptr, type, field, idx) \ + _td_fetch_value ((ta), (ta)->ta_field_##type##_##field, \ + SYM_##type##_FIELD_##field, \ + (psaddr_t) 0 + (idx), (ptr), &(var)) + +#define DB_GET_FIELD_ADDRESS(var, ta, ptr, type, field, idx) \ + ((var) = (ptr), _td_locate_field ((ta), (ta)->ta_field_##type##_##field, \ + SYM_##type##_FIELD_##field, \ + (psaddr_t) 0 + (idx), &(var))) + +extern td_err_e _td_locate_field (td_thragent_t *ta, + db_desc_t desc, int descriptor_name, + psaddr_t idx, + psaddr_t *address) attribute_hidden; + + +/* Like DB_GET_FIELD, but PTR is a local pointer to a structure that + has already been copied in from the inferior. */ +#define DB_GET_FIELD_LOCAL(var, ta, ptr, type, field, idx) \ + _td_fetch_value_local ((ta), (ta)->ta_field_##type##_##field, \ + SYM_##type##_FIELD_##field, \ + (psaddr_t) 0 + (idx), (ptr), &(var)) + +/* Store in psaddr_t VAR the value of variable NAME[IDX] in the inferior. + A target value smaller than psaddr_t is zero-extended. */ +#define DB_GET_VALUE(var, ta, name, idx) \ + (((ta)->ta_addr_##name == 0 \ + && td_lookup ((ta)->ph, SYM_##name, &(ta)->ta_addr_##name) != PS_OK) \ + ? TD_ERR \ + : _td_fetch_value ((ta), (ta)->ta_var_##name, SYM_DESC_##name, \ + (psaddr_t) 0 + (idx), (ta)->ta_addr_##name, &(var))) + +/* Helper functions for those. */ +extern td_err_e _td_fetch_value (td_thragent_t *ta, + db_desc_t field, int descriptor_name, + psaddr_t idx, psaddr_t address, + psaddr_t *result) attribute_hidden; +extern td_err_e _td_fetch_value_local (td_thragent_t *ta, + db_desc_t field, + int descriptor_name, + psaddr_t idx, void *address, + psaddr_t *result) attribute_hidden; + +/* Store psaddr_t VALUE in ((TYPE) PTR)->FIELD[IDX] in the inferior. + A target field smaller than psaddr_t is zero-extended. */ +#define DB_PUT_FIELD(ta, ptr, type, field, idx, value) \ + _td_store_value ((ta), (ta)->ta_field_##type##_##field, \ + SYM_##type##_FIELD_##field, \ + (psaddr_t) 0 + (idx), (ptr), (value)) + +#define DB_PUT_FIELD_LOCAL(ta, ptr, type, field, idx, value) \ + _td_store_value_local ((ta), (ta)->ta_field_##type##_##field, \ + SYM_##type##_FIELD_##field, \ + (psaddr_t) 0 + (idx), (ptr), (value)) + +/* Store psaddr_t VALUE in variable NAME[IDX] in the inferior. + A target field smaller than psaddr_t is zero-extended. */ +#define DB_PUT_VALUE(ta, name, idx, value) \ + (((ta)->ta_addr_##name == 0 \ + && td_lookup ((ta)->ph, SYM_##name, &(ta)->ta_addr_##name) != PS_OK) \ + ? TD_ERR \ + : _td_store_value ((ta), (ta)->ta_var_##name, SYM_DESC_##name, \ + (psaddr_t) 0 + (idx), (ta)->ta_addr_##name, (value))) + +/* Helper functions for those. */ +extern td_err_e _td_store_value (td_thragent_t *ta, + db_desc_t field, int descriptor_name, + psaddr_t idx, psaddr_t address, + psaddr_t value) attribute_hidden; +extern td_err_e _td_store_value_local (td_thragent_t *ta, + db_desc_t field, int descriptor_name, + psaddr_t idx, void *address, + psaddr_t value) attribute_hidden; + +#define DB_GET_STRUCT(var, ta, ptr, type) \ + ({ td_err_e _err = TD_OK; \ + if ((ta)->ta_sizeof_##type == 0) \ + _err = _td_check_sizeof ((ta), &(ta)->ta_sizeof_##type, \ + SYM_SIZEOF_##type); \ + if (_err == TD_OK) \ + _err = ps_pdread ((ta)->ph, (ptr), \ + (var) = __alloca ((ta)->ta_sizeof_##type), \ + (ta)->ta_sizeof_##type) \ + == PS_OK ? TD_OK : TD_ERR; \ + else \ + (var) = NULL; \ + _err; \ + }) +#define DB_PUT_STRUCT(ta, ptr, type, copy) \ + ({ assert ((ta)->ta_sizeof_##type != 0); \ + ps_pdwrite ((ta)->ph, (ptr), (copy), (ta)->ta_sizeof_##type) \ + == PS_OK ? TD_OK : TD_ERR; \ + }) + +extern td_err_e _td_check_sizeof (td_thragent_t *ta, uint32_t *sizep, + int sizep_name) attribute_hidden; + +#endif /* thread_dbP.h */ |