Kerala Cyber
Warriors
KCW Uploader V1.1
--- /dev/null
+++ b/fbtl/ANNOUNCE
@@ -0,0 +1,92 @@
+Now that the Linux kernel is once again able to run all the tests we
+have and since glibc 2.3 was released it was time for a new code drop.
+I've uploaded the second code drop for the Native POSIX Thread
+Library:
+
+ ftp://people.redhat.com/drepper/nptl/nptl-0.2.tar.bz2
+
+You need
+
+- the latest of Linus' kernel from BitKeeper (or 2.5.41 when it
+ is released);
+
+- glibc 2.3
+
+- the very latest in tools such as
+
+ + gcc either from the current development branch or the gcc 3.2
+ from Red Hat Linux 8;
+
+ + binutils preferrably from CVS, from H.J. Lu's latest release for
+ Linux, or from RHL 8.
+
+
+Compiling glibc should proceed smoothly. But there are a number of
+tests which fail, mostly because some functionality is missing in
+glibc. Ignore those errors. It is only important that all tests in
+nptl/ are passing. Run
+
+ make subdirs=nptl check
+
+to run all thread tests.
+
+
+This version features several improvements:
+
+- all APIs are now implemented;
+
+- fork handling has been improved; stacks in the child are freed;
+ atfork handlers are removed if they were registered from a module
+ which gets unloaded.
+
+- pthread_tryjoin_np and pthread_timedjoin_np are implemented
+
+- TSD handling corrected and optimized.
+
+- many more tests which also test the underlying kernel implementation.
+
+- the build infrastructure has been implemented so that the DSO and
+ archives are built in usable form and with correct named.
+
+- libthread_db has been implemented. This is the library which is
+ needed by all program which need to get access to internals of
+ libpthread (mainly debuggers).
+
+- the CPU clock functions are implemented
+
+
+
+The white paper hasn't yet been updated. It's still available at
+
+ http://people.redhat.com/drepper/nptl-design.pdf
+
+
+This release should be ready for some serious testing. I know it is
+hard to compile which I why I'm looking into providing binary RPMs.
+They can be used on non-critical systems. I'll only be able to
+provide binaries for RHL8 based systems, though, and the kernel still
+must be installed separately.
+
+
+The next steps will include:
+
+- write more tests and fix the bugs which are discovered this way
+
+- update the white paper
+
+- write and run more performance tests
+
+- port to IA-64
+
+
+Interested parties are once again invited to join the mailing we
+created:
+
+
+ phil-list@redhat.com
+
+Go to
+
+ https://listman.redhat.com/mailman/listinfo/phil-list
+
+to subscribe, unsubscribe, or review the archive.
--- /dev/null
+++ b/fbtl/Banner
@@ -0,0 +1 @@
+Native POSIX Threads Library by Ulrich Drepper et al
--- /dev/null
+++ b/fbtl/ChangeLog
@@ -0,0 +1,12903 @@
+2013-06-24 Vladimir Nikulichev <v.nikulichev@gmail.com>
+
+ [BZ #12310]
+ * pthread_exit.c: Add reference to pthread_create.
+
+2013-06-22 Joseph Myers <joseph@codesourcery.com>
+
+ * pthread_getattr_default_np.c: Include <string.h>.
+
+2013-06-15 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ * Versions (libpthread): Add GLIBC_2.18.
+ (GLIBC_2.18): Add pthread_setattr_default_np and
+ pthread_getattr_default_np.
+ * allocatestack.c (allocate_stack): Synchronize read from
+ __default_pthread_attr.
+ (__reclaim_stacks): Initialize __default_pthread_attr_lock.
+ * nptl-init.c (__pthread_initialize_minimal_internal):
+ Synchronize write to __default_pthread_attr.
+ * pthreadP.h (__default_pthread_attr_lock): Declare.
+ * pthread_attr_getstacksize (__pthread_attr_getstacksize):
+ Synchronize read from __default_pthread_attr.
+ * pthread_create.c (__pthread_create_2_1): Make a local copy of
+ __default_pthread_attr. Check value of flags in IATTR even if
+ input ATTR is NULL.
+ * pthread_getattr_default_np.c: New file.
+ * pthread_setattr_default_np.c: New file.
+ * sysdeps/pthread/pthread.h [__USE_GNU]
+ (pthread_getattr_default_np, pthread_setattr_default_np):
+ Declare.
+ * tst-default-attr.c: New test case.
+ * Makefile (libpthread-routines): Add
+ pthread_setattr_default_np and pthread_getattr_default_np.
+ (tests): Add tst-default-attr.
+ * vars.c (__default_pthread_attr_lock): Declare and initialize.
+
+2013-06-13 Siddhesh Poyarekar <siddhesh@redhat.com>
+ Carlos O'Donell <carlos@redhat.com>
+
+ [BZ #15618]
+ * tst-pthread-attr-affinity: New test case.
+ * Makefile (tests): Add it.
+ * sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c
+ (__pthread_attr_getaffinity_new): Copy minimum of source and
+ destination sizes to avoid a buffer overrun.
+
+2013-06-10 Carlos O'Donell <carlos@redhat.com>
+
+ * sysdeps/unix/sysv/linux/i386/lowlevellock.h
+ (lll_futex_wake): Return syscall error.
+ * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
+ (lll_futex_wake): Return syscall error.
+
+2013-08-06 Ondřej Bílka <neleai@seznam.cz>
+
+ * sysdeps/pthread/allocalim.h: (__libc_use_alloca): Fix warning.
+
+2013-06-06 Ondřej Bílka <neleai@seznam.cz>
+
+ * tst-cond22.c: Fix leading whitespaces.
+ * tst-umask1.c: Likewise.
+
+2013-06-06 Joseph Myers <joseph@codesourcery.com>
+
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: Remove
+ trailing whitespace.
+ * sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c: Likewise.
+ * sysdeps/unix/sysv/linux/sh/lowlevellock.h: Likewise.
+ * sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S: Likewise.
+ * 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_once.S: Likewise.
+ * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: Likewise.
+ * sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S: Likewise.
+ * sysdeps/unix/sysv/linux/sparc/lowlevellock.h: Likewise.
+ * tst-mutexpp10.c: Likewise.
+ * tst-stackguard1.c: Likewise.
+
+2013-05-31 Joseph Myers <joseph@codesourcery.com>
+
+ * Makefile ($(objpfx)libpthread.so): Remove dependencies on libc
+ and ld.so.
+
+2013-05-16 Ryan S. Arnold <rsa@linux.vnet.ibm.com>
+
+ * pthread_create.c: Add missing #include <stdint.h> due to uint64_t or
+ uint32_t usage.
+ * sysdeps/pthread/createthread.c: Likewise.
+
+2013-05-14 Andreas Jaeger <aj@suse.de>
+
+ [BZ #10686]
+ * sysdeps/x86_64/tls.h (struct tcbhead_t): Add __private_ss field.
+ * sysdeps/i386/tls.h (struct tcbhead_t): Likewise.
+
+2013-05-09 Andi Kleen <ak@linux.intel.com>
+
+ * tst-mutex8.c (do_test): Check for ENABLE_PI.
+
+2013-04-22 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ * pthreadP.h (check_sched_policy_attr): New inline function.
+ (check_sched_priority_attr): Likewise.
+ (check_stacksize_attr): Likewise.
+ (__kernel_cpumask_size, __determine_cpumask_size): Declare
+ extern.
+ (check_cpuset_attr): New inline function.
+ * pthread_attr_setschedparam (__pthread_attr_setschedparam):
+ Use check_sched_priority_attr.
+ * pthread_attr_setschedpolicy.c
+ (__pthread_attr_setschedpolicy): Use check_sched_policy_attr.
+ * pthread_attr_setstack.c (__pthread_attr_setstack): Use
+ check_stacksize_attr.
+ * pthread_attr_setstacksize.c (__pthread_attr_setstacksize):
+ Likewise.
+ * sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c
+ (__pthread_attr_setaffinity_new): Use check_cpuset_attr.
+
+2013-04-11 Andreas Schwab <schwab@suse.de>
+
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
+ (__pthread_cond_timedwait): If possible use FUTEX_WAIT_BITSET to
+ directly use absolute timeout.
+
+2013-04-07 Carlos O'Donell <carlos@redhat.com>
+
+ * sysdeps/unix/sysv/linux/sem_post.c: Include atomic.h.
+
+2013-04-04 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ [BZ #15337]
+ * sysdeps/unix/sysv/linux/x86_64/cancellation.S
+ [IS_IN_libpthread]
+ [SHARED && defined DO_VERSIONING && !defined NO_HIDDEN]: Mark
+ __pthread_unwind hidden.
+
+2013-03-28 Roland McGrath <roland@hack.frob.com>
+
+ * pthread_create.c (start_thread) [!SHARED]:
+ Call __call_tls_dtors only if it's not NULL.
+
+2013-03-19 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ * allocatestack.c (allocate_stack): Use __default_pthread_attr
+ instead of __default_stacksize.
+ * nptl-init.c (__pthread_initialize_minimal_internal):
+ Likewise. Initialize guardsize.
+ * pthreadP.h (__default_pthread_attr): Declare.
+ * pthread_attr_getstacksize.c (__pthread_attr_getstacksize):
+ Use __default_pthread_attr instead of __default_stacksize.
+ * pthread_create.c (default_attr): Remove.
+ (__pthread_create_2_1): Use __default_pthread_attr instead of
+ default_attr.
+ * vars.c (__default_stacksize): Remove.
+ (__default_pthread_attr): New static variable to store
+ default thread attributes.
+
+2013-03-18 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ * pthread_barrier_init.c (default_attr): Rename to
+ default_barrierattr.
+ (pthread_barrier_init): Adjust for the rename.
+ * pthread_mutex_init.c (default_attr): Rename to
+ default_mutexattr.
+ (__pthread_mutex_init): Adjust for the rename.
+ * pthread_rwlock_init.c (default_attr): Rebane to
+ default_rwlockattr.
+ (__pthread_rwlock_init): Adjust for the rename.
+
+2013-03-12 Carlos O'Donell <carlos@redhat.com>
+
+ * sysdeps/unix/sysv/linux/lowlevellock.c: Include <atomic.h>.
+
+2013-03-04 Roland McGrath <roland@hack.frob.com>
+
+ * sysdeps/unix/sysv/linux/i386/i686/dl-sysdep.h:
+ Change multiple inclusion guard to _LINUX_I686_DL_SYSDEP_H.
+ Use #include_next.
+ (HAVE_DL_DISCOVER_OSVERSION): Remove definition, now redundant.
+ (RTLD_PRIVATE_ERRNO): Likewise.
+ (NEED_DL_SYSINFO, DL_SYSINFO_DEFAULT, DL_SYSINFO_IMPLEMENTATION):
+ Move macros and associated declaration to ...
+ * sysdeps/unix/sysv/linux/i386/dl-sysdep.h: ... here.
+ Change multiple include guard to _LINUX_I386_DL_SYSDEP_H.
+ Use #include_next.
+
+2013-03-01 Carlos O'Donell <carlos@redhat.com>
+
+ * Makefile (tests): Revert last change.
+ (tst-pthread-stack-env-ENV): Likewise.
+ * nptl-init.c (set_default_stacksize): Likewise.
+ (__pthread_initialize_minimal_internal): Likewise.
+ * tst-pthread-stack-env.c: Likewise.
+
+2013-03-01 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ * tst-oddstacklimit.c: Include stdlib.h.
+
+ * Makefile (tests): Add tst-pthread-stack-env.
+ (tst-pthread-stack-env-ENV): Set environment for test.
+ * nptl-init.c (set_default_stacksize): New function.
+ (__pthread_initialize_minimal_internal): Accept ARGC, ARGV and
+ ENVP. Initialize __ENVIRON and set __DEFAULT_STACKSIZE.
+ * tst-pthread-stack-env.c: New test case.
+
+2013-02-21 David S. Miller <davem@davemloft.net>
+
+ * sysdeps/unix/sysv/linux/sparc/lowlevellock.h
+ (FUTEX_WAIT_REQUEUE_PI): Define.
+ (FUTEX_CMP_REQUEUE_PI): Likewise.
+ (lll_futex_wait_requeue_pi): Likewise.
+ (lll_futex_timed_wait_requeue_pi): Likewise.
+ (lll_futex_cmp_requeue_pi): Likewise.
+
+2013-02-21 Carlos O'Donell <carlos@redhat.com>
+
+ * sysdeps/unix/sysv/linux/fork.c: Fix comment typo.
+
+2013-02-18 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ * sysdeps/pthread/tst-timer.c: Include stdlib.h for declaration
+ of exit.
+ * tst-barrier4.c: Likewise.
+ * tst-robust7.c: Likewise.
+
+ [BZ #14920]
+ * pthreadP.h (USE_REQUEUE_PI): New macro to check if mutex is
+ PI-aware.
+ * pthread_cond_broadcast.c (__pthread_cond_broadcast): Use
+ PI-aware futex operations if available and mutex is PI-aware.
+ * pthread_cond_signal.c (__pthread_cond_signal): Likewise.
+ * nptl/pthread_cond_timedwait.c (__pthread_cond_timedwait):
+ Likewise.
+ * pthread_cond_wait.c (__condvar_cleanup): Adjust lock if
+ cancellation occurred just after futex returned successfully
+ from a PI operation with the mutex held.
+ (__pthread_cond_wait): Use PI-aware futex operations if
+ available and mutex is PI-aware.
+ * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
+ (FUTEX_WAIT_REQUEUE_PI): Define.
+ (FUTEX_CMP_REQUEUE_PI): Likewise.
+ (lll_futex_wait_requeue_pi): Likewise.
+ (lll_futex_timed_wait_requeue_pi): Likewise.
+ (lll_futex_cmp_requeue_pi): Likewise.
+ * nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h
+ (FUTEX_WAIT_REQUEUE_PI): Define.
+ (FUTEX_CMP_REQUEUE_PI): Likewise.
+ (lll_futex_wait_requeue_pi): Likewise.
+ (lll_futex_timed_wait_requeue_pi): Likewise.
+ (lll_futex_cmp_requeue_pi): Likewise.
+ * sysdeps/unix/sysv/linux/kernel-features.h: Define
+ __ASSUME_REQUEUE_PI for Linux version higher than 2.6.31.
+
+2013-02-04 Andreas Schwab <schwab@suse.de>
+
+ [BZ #14142]
+ * tst-cancel14.c: Include <sys/time.h>.
+ * tst-cancel15.c: Likewise.
+ * tst-mutex9.c: Include <stdint.h>, <stdlib.h> and <sys/time.h>.
+ * tst-stackguard1.c: Include <tls.h>
+
+2013-01-16 Andreas Schwab <schwab@suse.de>
+
+ [BZ #14327]
+ * sem_open.c (sem_open): Use __mktemp instead of mktemp.
+
+2013-01-11 Carlos O'Donell <codonell@redhat.com>
+
+ * allocatestack.c (allocate_stack): Add comment. Remove assert
+ on attr.
+
+2013-01-11 H.J. Lu <hongjiu.lu@intel.com>
+
+ * Makefile (tst-cancel7-ARGS: Replace $(host-built-program-cmd)
+ with $(host-test-program-cmd).
+ (tst-exec4-ARGS): Likewise.
+ (tst-stackguard1-ARGS): Likewise.
+ ($(objpfx)tst-tls6.out): Don't pass $(elf-objpfx) to tst-tls6.sh.
+ Replace $(rtld-installed-name) with $(test-via-rtld-prefix).
+ * tst-tls6.sh (elf_objpfx): Removed.
+ (rtld_installed_name): Renamed to ...
+ (test_via_rtld_prefix): This.
+ (tst_tls5): Prepend ${test_via_rtld_prefix}.
+
+2013-01-02 Joseph Myers <joseph@codesourcery.com>
+
+ * All files with FSF copyright notices: Update copyright dates
+ using scripts/update-copyrights.
+
+2013-01-01 Joseph Myers <joseph@codesourcery.com>
+
+ * sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S: Reformat
+ copyright notice.
+
+2012-12-28 Andi Kleen <ak@linux.intel.com>
+
+ * pthread_rwlock_tryrdlock.c (__pthread_rwlock_tryrdlock): Convert
+ to prototype.
+ * pthread_rwlock_trywrlock.c (__pthread_rwlock_trywrlock):
+ Likewise.
+
+2012-12-27 David S. Miller <davem@davemloft.net>
+
+ * sysdeps/unix/sysv/linux/sparc/lowlevellock.h
+ (lll_futex_timed_wait_bitset): New macro.
+
+2012-12-27 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ * sysdeps/unix/sysv/linux/s390/lowlevellock.h (SYS_futex):
+ Remove definition.
+ (lll_futex_timed_wait): Replace assembly code with
+ INTERNAL_SYSCALL.
+ (lll_futex_timed_wait_bitset): Likewise.
+ (lll_futex_wake): Likewise.
+ (lll_futex_requeue): Likewise.
+ (lll_futex_wake_unlock): Likewise.
+
+2012-12-08 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ * sysdeps/unix/sysv/linux/s390/jmp-unwind.c (_longjmp_unwind):
+ Declare LOCAL_VAR as char.
+
+2012-12-04 Joseph Myers <joseph@codesourcery.com>
+
+ * sysdeps/unix/sysv/linux/powerpc/sem_post.c (__old_sem_post):
+ Cast result of atomic_increment_val to (void) instead of storing
+ in otherwise-unused variable.
+
+2012-12-03 Allan McRae <allan@archlinux.org>
+
+ * Makefile (LDFLAGS-tst-cond24, LDFLAGS-tst-cond25): Remove.
+
+2012-11-26 H.J. Lu <hongjiu.lu@intel.com>
+
+ * unwind.c (__pthread_unwind): Pass address of unwind_cleanup
+ to THREAD_SETMEM.
+ * sysdeps/i386/tls.h: Include <libc-internal.h>.
+ (THREAD_SETMEM): Use cast_to_integer before casting to uint64_t.
+ (THREAD_SETMEM_NC): Likewise.
+ * sysdeps/x86_64/tls.h: Include <libc-internal.h>.
+ (THREAD_SETMEM): Use cast_to_integer before casting to uint64_t.
+ (THREAD_SETMEM_NC): Likewise.
+
+2012-11-21 Joseph Myers <joseph@codesourcery.com>
+
+ * sysdeps/unix/sysv/linux/sem_post.c (__old_sem_post): Cast result
+ of atomic_increment_val to (void) instead of storing in
+ otherwise-unused variable.
+
+ * pthread_cond_timedwait.c (__pthread_cond_timedwait)
+ [__NR_clock_gettime]: Cast result of INTERNAL_VSYSCALL to void
+ instead of storing in otherwise-unused variable.
+
+2012-11-14 Marcus Shawcroft <marcus.shawcroft@linaro.org>
+
+ * Makefile (CFLAGS-open.c, CFLAGS-open64.c, CFLAGS-pause.c)
+ (CFLAGS-recv.c, CFLAGS-send.c): Define.
+
+2012-11-06 Chris Metcalf <cmetcalf@tilera.com>
+
+ * tst-sem14.c (TIMEOUT): Set timeout to 10 seconds.
+ * tst-cond24.c (TIMEOUT): Increase from 10 to 20 seconds.
+
+2012-11-05 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ * pthread_cond_timedwait.c (__pthread_cond_timedwait): Time out
+ if absolute timeout is negative.
+ [__ASSUME_FUTEX_CLOCK_REALTIME &&
+ lll_futex_timed_wait_bitset]: Use lll_futex_timed_wait_bitset.
+ * pthread_rwlock_timedrdlock.c (pthread_rwlock_timedrdlock):
+ Likewise.
+ * pthread_rwlock_timedwrlock.c (pthread_rwlock_timedwrlock):
+ Likewise.
+ * sysdeps/unix/sysv/linux/lowlevelrobustlock.c
+ (__lll_robust_timedlock_wait): Likewise.
+ * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
+ (lll_futex_timed_wait_bitset): New macro.
+ * sysdeps/unix/sysv/linux/s390/lowlevellock.h
+ (lll_futex_timed_wait_bitset): Likewise.
+
+2012-11-03 David S. Miller <davem@davemloft.net>
+
+ * sysdeps/unix/sysv/linux/sparc/lowlevellock.h (BUSY_WAIT_NOP):
+ Add missing spaces.
+ (__cpu_relax): Likewise.
+
+2012-11-02 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/x86_64/tls.h: Don't include <xmmintrin.h>.
+ (__128bits): New struct typedef.
+ (tcbhead_t): Replace __m128 with __128bits.
+
+2012-10-30 Aurelien Jarno <aurelien@aurel32.net>
+ Joseph Myers <joseph@codesourcery.com>
+
+ * Makefile (tst-cancel7-ARGS): Use exec in --command argument.
+
+2012-10-28 David S. Miller <davem@davemloft.net>
+
+ * sysdeps/unix/sysv/linux/sparc/lowlevellock.h (BUSY_WAIT_NOP):
+ Define when we have v9 instructions available.
+ * sysdeps/unix/sysv/linux/sparc/sparc64/cpu_relax.S: New file.
+ * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/cpu_relax.S: New
+ file.
+ * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/Makefile: New
+ file.
+ * sysdeps/unix/sysv/linux/sparc/sparc64/Makefile: Add cpu_relax
+ to libpthread-routines.
+
+2012-10-25 Roland McGrath <roland@hack.frob.com>
+
+ * tst-cond-except.c (TEST_FUNCTION): New macro.
+
+2012-10-25 Joseph Myers <joseph@codesourcery.com>
+
+ * Makefile ($(objpfx)tst-tls6.out): Use $(BASH) not $(SHELL) to
+ run tst-tls6.sh.
+ * tst-tls6.sh: Use /bin/bash not /bin/sh.
+
+2012-10-25 Roland McGrath <roland@hack.frob.com>
+
+ * tst-basic2.c (do_test): Return RESULT, not always zero.
+
+ * tst-cond25.c: Include <stdint.h>
+ (waiter): Add casts to uintptr_t between casting integer<->pointer.
+ (timed_waiter): Likewise.
+ (do_test_wait): Likewise.
+ * tst-cond-except.c (thr): Likewise.
+ (do_test): Use prototype definition.
+
+2012-10-24 Joseph Myers <joseph@codesourcery.com>
+ Jim Blandy <jimb@codesourcery.com>
+
+ * Makefile ($(objpfx)tst-tls6.out): Pass $(test-wrapper-env) to
+ tst-tls6.sh.
+ * tst-tls6.sh (test_wrapper_env): New variable. Use it to run
+ programs with LD_PRELOAD set.
+
+2012-10-24 Roland McGrath <roland@hack.frob.com>
+
+ * Makefile ($(objpfx)tst-cond11, $(objpfx)tst-cond19): Targets removed.
+ ($(objpfx)tst-sem5, $(objpfx)tst-cancel18): Likewise.
+ ((objpfx)tst-cancelx18, $(objpfx)tst-clock2): Likewise.
+ ($(objpfx)tst-rwlock14): Likewise.
+
+2012-10-24 Joseph Myers <joseph@codesourcery.com>
+
+ * Makefile (tests): Remove tst-oddstacklimit.
+ (test-srcs): New variable.
+ (tst-oddstacklimit-ENV): Remove.
+ [$(run-built-tests) = yes] (tests): Depend on
+ $(objpfx)tst-oddstacklimit.out.
+ [$(run-built-tests) = yes] ($(objpfx)tst-oddstacklimit.out): New
+ target.
+ * tst-oddstacklimit.c: Do not include "tst-basic1.c". Use
+ setrlimit before executing tst-basic1 test passed to --command.
+
+2012-10-23 Joseph Myers <joseph@codesourcery.com>
+
+ * Makefile [$(cross-compiling) = no]: Change condition to
+ [$(run-built-tests) = yes].
+
+2012-10-23 Jim Blandy <jimb@codesourcery.com>
+ Joseph Myers <joseph@codesourcery.com>
+
+ * Makefile (tst-cancel7-ARGS): Use $(host-built-program-cmd).
+ (tst-exec4-ARGS): Likewise.
+ (tst-stackguard1-ARGS): Likewise.
+
+2012-10-21 Jim Blandy <jimb@codesourcery.com>
+ Joseph Myers <joseph@codesourcery.com>
+
+ * Makefile ($(objpfx)tst-cancel-wrappers.out): Pass $(NM) to
+ tst-cancel-wrappers.sh.
+ * tst-cancel-wrappers.sh: Use nm program given as first argument,
+ not hardcoded "nm".
+
+2012-10-17 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ * tst-cond25.c (do_test_wait): Don't check for return value from
+ pthread_cancel.
+
+2012-10-16 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ [BZ #14652]
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
+ (__condvar_tw_cleanup): Adjust the mutex data structure if it
+ was locked by FUTEX_WAIT_REQUEUE_PI.
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait
+ (__condvar_w_cleanup): Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
+ (__condvar_cleanup2): Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
+ (__condvar_cleanup1): Likewise.
+
+2012-10-10 Carlos O'Donell <carlos@systemhalted.org>
+
+ * sysdeps/pthread/pthread.h [!(defined __GNUC__ &&
+ defined __EXCEPTIONS) && defined __USE_GNU]
+ (pthread_cleanup_push_defer_np): Fix formatting.
+
+2012-10-10 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ [BZ #14652]
+ * Makefile (tests): New test case tst-cond25.
+ (LDFLAGS-tst-cond25): Link tst-cond25 against librt.
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
+ (__condvar_tw_cleanup): Lock mutex only if we don't already
+ own it.
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
+ (__condvar_w_cleanup): Likewise.
+ * sysdeps/unix/sysv/linux/pthread-pi-defines.sym: Add TID_MASK.
+ * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
+ (__condvar_cleanup2): Lock mutex only if we don't already
+ own it.
+ * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
+ (__condvar_cleanup1): Likewise.
+ * tst-cond25.c: New test case.
+
+2012-10-09 Roland McGrath <roland@hack.frob.com>
+
+ * sysdeps/pthread/configure: Regenerated.
+ * sysdeps/x86_64/configure: Regenerated.
+
+2012-10-05 David S. Miller <davem@davemloft.net>
+
+ [BZ #14568]
+ * sysdeps/sparc/tls.h (DB_THREAD_SELF_INCLUDE): Delete.
+ (DB_THREAD_SELF): Use constants for the register offsets. Correct
+ the case of a 64-bit debugger with a 32-bit inferior.
+
+2012-10-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ [BZ #14557]
+ * Makefile (tests-static): Add tst-cancel24-static,
+ tst-cond8-static tst-mutex8-static, tst-mutexpi8-static,
+ tst-sem11-static and tst-sem12-static.
+ (tests): Likewise.
+ (LDLIBS-tst-cancel24-static): New macro.
+ * tst-cancel24-static.cc: New file.
+ * tst-cond8-static.c: Likewise.
+ * tst-mutex8-static.c: Likewise.
+ * tst-mutexpi8-static.c: Likewise.
+ * tst-sem11-static.c: Likewise.
+ * tst-sem12-static.c: Likewise.
+
+2012-10-05 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ [BZ #14417]
+ * Makefile (tests): New test case tst-cond24.
+ (LDFLAGS-tst-cond24): Link tst-cond24 against librt.
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
+ (__pthread_cond_timedwait): Unlock mutex before going back to
+ wait in PI case.
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
+ (__pthread_cond_wait): Likewise. Revert handling of EAGAIN
+ return from futex_wait.
+ * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
+ (__pthread_cond_timedwait): Unlock mutex before going back to
+ wait in PI case. Set requeue_pi flag only if wait returned 0.
+ * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S
+ (__pthread_cond_wait): Likewise. Revert handling of EAGAIN
+ return from futex_wait.
+ * tst-cond24.c: New test case.
+
+2012-10-04 Roland McGrath <roland@hack.frob.com>
+
+ * pthread_create.c (start_thread): Use __madvise, not madvise.
+
+2012-10-02 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/i386/tls.h: Update copyright years.
+
+2012-10-02 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ * pthread_create.c (start_thread): Fix clone flag name in
+ comment to CLONE_CHILD_CLEARTID.
+ * sysdeps/unix/sysv/linux/i386/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/x86_64/lowlevellock.h: Likewise.
+
+2012-10-01 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ [BZ #14477]
+ * Makefile (tests): Add tst-cond-except.
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
+ (__pthread_cond_timedwait): Mark instructions where %ebx is
+ incremented in PI case.
+ (.gcc_except_table): Add entry to jump to __condvar_tw_cleanup2
+ for the marked PI case instructions.
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S
+ (__pthread_cond_wait): Mark instructions where %ebx is
+ incremented in PI case.
+ (.gcc_except_table): Add entry to jump to __condvar_w_cleanup2
+ for the marked PI case instructions.
+ * tst-cond-except.c: New test case.
+
+2012-09-24 Dmitry V. Levin <ldv@altlinux.org>
+
+ * tst-tls6.sh: Add "set -e".
+ * Makefile: Do not specify -e option when running testsuite
+ shell scripts.
+
+ * tst-tls6.sh: Add copyright header.
+
+2012-09-24 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/x86_64/tls.h (THREAD_SETMEM): Add "()" when casting
+ to uint64_t for 64-bit store.
+ (THREAD_SETMEM_NC): Likewise.
+
+2012-09-19 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/i386/tls.h (THREAD_SETMEM): Cast to uint64_t for
+ 64-bit store.
+ (THREAD_SETMEM_NC): Likewise.
+
+2012-09-14 Jeff Law <law@redhat.com>
+
+ [BZ #14583]
+ * sysdeps/pthread/pthread.h: Fix prototype of __sigsetjmp.
+
+2012-09-13 H.J. Lu <hongjiu.lu@intel.com>
+
+ [BZ #14576]
+ * sysdeps/pthread/bits/libc-lockP.h (__rtld_lock_init_recursive):
+ Removed.
+
+2012-09-07 H.J. Lu <hongjiu.lu@intel.com>
+
+ * Makefile (LDFLAGS-tst-cancel24): Renamed to ...
+ (LDLIBS-tst-cancel24): This.
+
+2012-09-06 H.J. Lu <hongjiu.lu@intel.com>
+
+ [BZ #14545]
+ * Makefile (tests-static): Add tst-cancel21-static.
+ (tests): Likewise.
+ * tst-cancel21-static.c: New file.
+
+2012-09-01 Joseph Myers <joseph@codesourcery.com>
+
+ * sysdeps/unix/sysv/linux/pthread_getcpuclockid.c
+ [!__ASSUME_POSIX_CPU_TIMERS]: Remove conditional code.
+ [__NR_clock_getres]: Make code unconditional.
+ (pthread_getcpuclockid): Remove code left unreachable by removal
+ of conditionals.
+
+2012-08-31 Joseph Myers <joseph@codesourcery.com>
+
+ [BZ #14532]
+ * sysdeps/unix/sysv/linux/sem_post.c (__new_sem_post): Use
+ atomic_compare_and_exchange_bool_rel.
+ * tst-sem14.c: New file.
+ * Makefile (tests): Add tst-sem14.
+
+2012-08-15 Roland McGrath <roland@hack.frob.com>
+
+ * Makefile (CFLAGS-flockfile.c): Use $(libio-mtsafe) instead
+ of -D_IO_MTSAFE_IO.
+ (CFLAGS-ftrylockfile.c, CFLAGS-funlockfile.c): Likewise.
+ * sysdeps/unix/sysv/linux/Makefile (CFLAGS-fork.c): Likewise.
+
+2012-08-16 Joseph Myers <joseph@codesourcery.com>
+
+ * pthread_cond_timedwait.c (__pthread_cond_timedwait)
+ [!__ASSUME_POSIX_TIMERS]: Remove conditional code.
+ * pthread_condattr_setclock.c (pthread_condattr_setclock)
+ [!__ASSUME_POSIX_TIMERS]: Likewise.
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S
+ (__pthread_cond_timedwait) [!__ASSUME_POSIX_TIMERS]: Likewise.
+ * sysdeps/unix/sysv/linux/pthread_getcpuclockid.c
+ [!__ASSUME_POSIX_TIMERS]: Likewise.
+ * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S
+ (__pthread_cond_timedwait) [!__ASSUME_POSIX_TIMERS]: Likewise.
+ * sysdeps/unix/sysv/linux/timer_create.c [__NR_timer_create]: Make
+ code unconditional.
+ [!__NR-timer_create]: Remove conditional code.
+ (timer_create) [!__ASSUME_POSIX_TIMERS]: Likewise.
+ * sysdeps/unix/sysv/linux/timer_delete.c [__NR_timer_delete]: Make
+ code unconditional.
+ [!__NR_timer_delete]: Remove conditional code.
+ (timer_delete) [!__ASSUME_POSIX_TIMERS]: Likewise.
+ * sysdeps/unix/sysv/linux/timer_getoverr.c
+ [__NR_timer_getoverrun]: Make code unconditional.
+ [!__NR_timer_getoverrun]: Remove conditional code.
+ (timer_getoverrun) [!__ASSUME_POSIX_TIMERS]: Likewise.
+ * sysdeps/unix/sysv/linux/timer_gettime.c [__NR_timer_gettime]:
+ Make code unconditional.
+ [!__NR_timer_gettime]: Remove conditional code.
+ (timer_gettime) [!__ASSUME_POSIX_TIMERS]: Likewise.
+ * sysdeps/unix/sysv/linux/timer_routines.c [__NR_timer_create]:
+ Make code unconditional.
+ [!__ASSUME_POSIX_TIMERS]: Remove conditional code.
+ * sysdeps/unix/sysv/linux/timer_settime.c [__NR_timer_settime]:
+ Make code unconditional.
+ [!__NR_timer_settime]: Remove conditional code.
+ (timer_settime) [!__ASSUME_POSIX_TIMERS]: Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
+ (__pthread_cond_timedwait) [!__ASSUME_POSIX_TIMERS]: Remove
+ conditional code.
+
+2012-08-15 Tom de Vries <vries@codesourcery.com>
+ Maxim Kuvyrkov <maxim@codesourcery.com>
+
+ * sysdeps/pthread/bits/libc-lockP.h (__libc_lock_lock)
+ (__libc_lock_trylock): Allow pre-existing definitions.
+
+2012-08-15 Maxim Kuvyrkov <maxim@codesourcery.com>
+
+ * pthread_spin_lock.c: New file.
+ * pthread_spin_trylock.c: New file.
+
+2012-08-08 Joseph Myers <joseph@codesourcery.com>
+
+ * allocatestack.c (setxid_signal_thread) [__ASSUME_TGKILL]: Make
+ code unconditional.
+ (setxid_signal_thread) [!__ASSUME_TGKILL]: Remove conditional code.
+ * pthread_cancel.c (pthread_cancel) [__ASSUME_TGKILL]: Make code
+ unconditional.
+ (pthread_cancel) [!__ASSUME_TGKILL]: Remove conditional code.
+ * sysdeps/pthread/createthread.c (do_clone) [__ASSUME_TGKILL]:
+ Make code unconditional.
+ (do_clone) [!__ASSUME_TGKILL]: Remove conditional code.
+ * sysdeps/unix/sysv/linux/pt-raise.c (raise) [__ASSUME_TGKILL ||
+ __NR_tgkill]: Make code unconditional.
+ (raise) [__ASSUME_TGKILL]: Likewise.
+ (raise) [!__ASSUME_TGKILL]: Remove conditional code.
+ * sysdeps/unix/sysv/linux/pthread_kill.c (__pthread_kill)
+ [__ASSUME_TGKILL]: Make code unconditional.
+ (__pthread_kill) [!__ASSUME_TGKILL]: Remove conditional code.
+ * sysdeps/unix/sysv/linux/raise.c (raise) [__ASSUME_TGKILL ||
+ __NR_tgkill]: Make code unconditional.
+ (raise) [__ASSUME_TGKILL]: Likewise.
+ (raise) [!__ASSUME_TGKILL]: Remove conditional code.
+
+2012-08-07 Joseph Myers <joseph@codesourcery.com>
+
+ * sysdeps/pthread/createthread.c (create_thread)
+ [!__ASSUME_NO_CLONE_DETACHED]: Remove conditional code.
+
+2012-08-03 Joseph Myers <joseph@codesourcery.com>
+
+ * nptl-init.c (sigcancel_handler) [__ASSUME_CORRECT_SI_PID]: Make
+ code unconditional.
+ (sighandler_setxid) [__ASSUME_CORRECT_SI_PID]: Likewise.
+
+2012-07-28 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ * tst-pthread-getattr.c (MAX_STACK_SIZE): New macro.
+ (pagesize): New static variable.
+ (allocate_and_test): Return MEM. Rename parameter to TARGET.
+ (check_stack_top): New local variables MEM and PAGEMASK. Cap
+ stack size to MAX_STACK_SIZE. Call allocate_and_test for
+ halfway up the stack top page. Verify that the top page was
+ written into.
+ (do_test): Get pagesize using sysconf.
+
+2012-07-25 Andreas Schwab <schwab@linux-m68k.org>
+
+ * sysdeps/unix/sysv/linux/i386/pt-vfork.S: Remove pseudo_end
+ label.
+ * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (PSEUDO): Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h (PSEUDO):
+ Likewise.
+
+2012-07-25 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ * tst-pthread-getattr.c: Revert last change.
+
+2012-07-20 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ * tst-pthread-getattr.c (MAX_STACK_SIZE): New max cap for stack
+ size.
+ (_MIN): New macro.
+ (allocate_and_test): Return STACKADDR. Access STACKADDR instead
+ of MEM to test.
+ (check_stack_top): Read valued written into STACKADDR in
+ allocate_and_test. Cap stack size to MAX_STACK_SIZE.
+
+2012-07-19 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ * nptl-init.c (sighandler_setxid): Fix the comment that
+ describes it.
+
+2012-06-23 Thomas Schwinge <thomas@codesourcery.com>
+
+ * sysdeps/unix/sysv/linux/sh/lowlevelrobustlock.S
+ (__lll_robust_timedlock_wait): Simplify CFI directives.
+
+2012-06-20 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ [BZ #12416]
+ * Makefile (tests): Add test case.
+ * pthread_getattr_np.c (pthread_getattr_np): Deduct pages below
+ the __libc_stack_end page from stacksize. Truncate stacksize to
+ make it page aligned when it is computed from RLIMIT_STACK.
+ * tst-pthread-getattr.c: New test case. Verify that stackaddr is
+ accessible.
+
+2012-06-07 Carlos Sánchez de La Lama <csanchezdll@gmail.com>
+
+ [BZ #14205]
+ * sysdeps/sparc/sparc32/pthread_spin_lock.S: Do not use v9
+ branches.
+
+2012-06-04 Siddhesh Poyarekar <siddhesh@redhat.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ [BZ #14188]
+ * sysdeps/pthread/pthread.h
+ [!(defined __GNUC__ && defined __EXCEPTIONS)]
+ (pthread_cleanup_push, pthread_cleanup_push_defer_np): Use
+ __libc_unlikely instead of __builtin_expect.
+
+2012-05-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ [BZ #14117]
+ * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Removed.
+ * sysdeps/unix/sysv/linux/i386/bits/semaphore.h: Likewise.
+ * sysdeps/unix/sysv/linux/i386/Implies: New file.
+ * sysdeps/unix/sysv/linux/x86_64/Implies: Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Renamed
+ to ...
+ * sysdeps/unix/sysv/linux/x86/bits/pthreadtypes.h: This.
+ * sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h: Renamed
+ to ...
+ * sysdeps/unix/sysv/linux/x86/bits/semaphore.h: This.
+
+2012-05-30 Andreas Schwab <schwab@linux-m68k.org>
+
+ [BZ #14132]
+ * nptl-init.c (pthread_functions): Remove use of INTUSE and
+ _internal aliases.
+ (__pthread_initialize_minimal_internal): Likewise.
+ * sem_open.c: Likewise.
+ * sem_unlink.c: Likewise.
+ * pthreadP.h: Replace _internal aliases by hidden_proto
+ declarations.
+ * pthread_getspecific.c: Replace _internal alias by hidden_def.
+ * pthread_key_create.c: Likewise.
+ * pthread_mutex_destroy.c: Likewise.
+ * pthread_mutex_init.c: Likewise.
+ * pthread_mutex_lock.c: Likewise.
+ * pthread_mutex_unlock.c: Likewise.
+ * pthread_once.c: Likewise.
+ * pthread_rwlock_rdlock.c: Likewise.
+ * pthread_rwlock_unlock.c: Likewise.
+ * pthread_rwlock_wrlock.c: Likewise.
+ * pthread_setspecific.c: 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/pthread_once.S: Likewise.
+ * sysdeps/unix/sysv/linux/powerpc/pthread_once.c: Likewise.
+ * sysdeps/unix/sysv/linux/s390/pthread_once.c: Likewise.
+ * sysdeps/unix/sysv/linux/sh/pthread_once.S: Likewise.
+ * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.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/sparc/pthread_once.c: Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S:
+ Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S:
+ Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S:
+ Likewise.
+
+2012-05-27 Chung-Lin Tang <cltang@codesourcery.com>
+
+ * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h (PSEUDO, LOAD_ARGS_1)
+ (LOAD_ARGS_2 ,LOAD_ARGS_3 ,LOAD_ARGS_4): Add CFI restores.
+
+ * sysdeps/unix/sysv/linux/sh/lowlevellock.S (__lll_lock_wait_private)
+ (__lll_lock_wait, __lll_timedlock_wait, __lll_timedwait_tid): Add CFI
+ directives.
+ * sysdeps/unix/sysv/linux/sh/lowlevelrobustlock.S
+ (__lll_robust_lock_wait, __lll_robust_timedlock_wait): Likewise.
+ * sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S
+ (pthread_barrier_wait): Likewise.
+ * sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S
+ (__pthread_cond_broadcast): Likewise.
+ * sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S
+ (__pthread_cond_signal): Likewise.
+ * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S
+ (__pthread_cond_timedwait): Likewise.
+ * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S (__pthread_cond_wait):
+ Likewise.
+ * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S
+ (__pthread_rwlock_rdlock): 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.
+ * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S
+ (__pthread_rwlock_wrlock): Likewise.
+ * 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.
+
+2012-05-26 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ [BZ #12416]
+ * nptl/pthread_getattr_np.c (pthread_getattr_np): Use
+ __libc_stack_end rounded to the end of containing page as the
+ real stack end.
+
+2012-05-25 Rayson Ho <rho@redhat.com>
+
+ * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Low-level SystemTap
+ probes for i386.
+ * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Likewise.
+ * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: 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/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_wrlock.S: Likewise.
+
+2012-05-25 Rayson Ho <rho@redhat.com>
+ Roland McGrath <roland@hack.frob.com>
+
+ * DESIGN-systemtap-probes.txt: New file.
+ * pthread_cond_broadcast.c: SystemTap probes.
+ * pthread_cond_init.c: Likewise.
+ * pthread_cond_signal.c: Likewise.
+ * pthread_cond_wait.c: Likewise.
+ * pthread_cond_destroy.c: Likewise.
+ * pthread_create.c: Likewise.
+ * pthread_join.c: Likewise.
+ * pthread_mutex_destroy.c: Likewise.
+ * pthread_mutex_init.c: Likewise.
+ * pthread_mutex_lock.c: Likewise.
+ * pthread_mutex_timedlock.c: Likewise.
+ * pthread_mutex_unlock.c: Likewise.
+ * pthread_rwlock_destroy.c: Likewise.
+ * pthread_rwlock_rdlock.c: Likewise.
+ * pthread_rwlock_unlock.c: Likewise.
+ * pthread_rwlock_wrlock.c: Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.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_wrlock.S: Likewise.
+
+2012-05-24 Roland McGrath <roland@hack.frob.com>
+
+ * pthread_create.c (start_thread): Define pthread_start LIBC_PROBE.
+
+2012-05-17 Andreas Jaeger <aj@suse.de>
+
+ * sysdeps/unix/sysv/linux/i386/i686/dl-sysdep.h
+ (HAVE_DL_DISCOVER_OSVERSION): Don't declare _dl_discover_osversion
+ only for older kernels.
+
+2012-05-15 Joseph Myers <joseph@codesourcery.com>
+
+ * pthreadP.h [!__NR_set_robust_list] (__NR_set_robust_list): Do
+ not define.
+
+2012-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (lll_lock): Load
+ futex pointer into RDI_LP. Use RSP_LP to operate on stack.
+ (lll_robust_lock): Likewise.
+ (lll_cond_lock): Likewise.
+ (lll_robust_cond_lock): Likewise.
+ (lll_timedlock): Likewise.
+ (lll_robust_timedlock): Likewise.
+ (lll_unlock): Likewise.
+ (lll_robust_unlock): Likewise.
+
+2012-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Use
+ LP_OP(cmp) and RCX_LP on dep_mutex pointer.
+
+2012-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Use LP_OP(op)
+ on NWAITERS.
+ (__gcc_personality_v0): Replace 8-byte data alignment with
+ LP_SIZE alignment and .quad with ASM_ADDR.
+
+2012-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Use LP_OP(op)
+ on NWAITERS.
+ (__gcc_personality_v0): Replace 8-byte data alignment with
+ LP_SIZE alignment and .quad with ASM_ADDR.
+
+2012-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/unix/sysv/linux/x86_64/sem_post.S: Use LP_OP(cmp) on
+ NWAITERS, which is unsigned long int.
+
+2012-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/unix/sysv/linux/x86_64/pthread_once.S
+ (__gcc_personality_v0): Replace 8-byte data alignment with
+ LP_SIZE alignment and .quad with ASM_ADDR.
+
+2012-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Use
+ LP_OP(cmp), RSI_LP and R8_LP on dep_mutex pointer. Load
+ __vdso_clock_gettime pointer into RAX_LP.
+ (__gcc_personality_v0): Replace 8-byte data alignment with
+ LP_SIZE alignment and .quad with ASM_ADDR.
+
+2012-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Use
+ LP_OP(cmp), RSI_LP and R8_LP on dep_mutex pointer. Load
+ __vdso_clock_gettime pointer into RAX_LP.
+ (__gcc_personality_v0): Replace 8-byte data alignment with
+ LP_SIZE alignment and .quad with ASM_ADDR.
+
+2012-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: Use
+ LP_OP(cmp) and R8_LP on dep_mutex pointer.
+
+2012-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/unix/sysv/linux/x86_64/cancellation.S: Use LP_OP(mov)
+ to update pointer in memory. Load pointer into RDI_LP.
+
+2012-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h
+ (LLL_STUB_UNWIND_INFO_START): Align label to LP_SIZE instead
+ of 8.
+ (LLL_STUB_UNWIND_INFO_END): Likewise.
+ (lll_timedlock): Load timeout pointer into RDX_LP.
+ (lll_robust_timedlock): Likewise.
+
+2012-05-15 Siddhesh Poyarekar <siddhesh@redhat.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ [BZ #13613]
+ * Makefile (tests): Add test cases.
+ * descr.h (struct pthread): Add a comment describing multiple_threads.
+ * pthreadP.h (__pthread_multiple_threads): Expand comment to include
+ single-process case.
+ * pthread_cancel.c (pthread_cancel): Enable multiple_threads
+ before setting cancelstate of the thread.
+ * sysdeps/unix/sysv/linux/libc_multiple_threads.c
+ (__libc_multiple_threads): Add explanatory comment.
+ * tst-cancel-self-cancelstate.c: New test case.
+ * tst-cancel-self-canceltype.c: Likewise.
+ * tst-cancel-self-cleanup.c: Supporting file for test cases.
+ * tst-cancel-self-testcancel.c: New test case.
+ * tst-cancel-self.c: Likewise.
+ * vars.c: Expand comment to include single-process case.
+
+2012-05-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/x86_64/tls.h: Don't include <bits/wordsize.h>.
+ (tcbhead_t): Remove __x86_64__ check. Align rtld_savespace_sse
+ to 32 bytes.
+
+2012-05-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/pthread/pthread.h (__PTHREAD_RWLOCK_INT_FLAGS_SHARED):
+ New.
+ (PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP): Check
+ __PTHREAD_RWLOCK_INT_FLAGS_SHARED instead of __WORDSIZE.
+
+2012-05-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ * shlib-versions: Move x86_64-.*-linux.* entry to ...
+ * sysdeps/x86_64/64/shlib-versions: Here. New file.
+ * sysdeps/x86_64/x32/shlib-versions: New file.
+
+2012-05-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Define x32
+ __SIZEOF_PTHREAD_XXX_T.
+ (__pthread_internal_list): Check __x86_64__ instead of __WORDSIZE.
+ (pthread_mutex_t): Likewise.
+ (pthread_rwlock_t): Likewise.
+ (__PTHREAD_RWLOCK_INT_FLAGS_SHARED): New. Defined if __x86_64__
+ is defined.
+
+2012-05-11 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/x86_64/x32/tls.h: New file.
+
+2012-05-11 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/x86_64/tls.h (THREAD_SETMEM): Use uint64_t on 64-bit
+ integer.
+ (THREAD_SETMEM_NC): Likewise.
+
+2012-05-11 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/x86_64/tls.h (THREAD_SELF): Replace movq/%q0 with
+ mov/%0.
+
+2012-05-11 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h
+ (__cleanup_fct_attribute): Check __x86_64__ instead of
+ __WORDSIZE.
+
+2012-05-11 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/pthread/pthread.h (PTHREAD_MUTEX_INITIALIZER): Check
+ __PTHREAD_MUTEX_HAVE_PREV instead of __WORDSIZE.
+ (PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP): Likewise.
+ (PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP): Likewise.
+ (PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP): Likewise.
+
+2012-05-11 H.J. Lu <hongjiu.lu@intel.com>
+
+ * pthread_create.c (start_thread): Check __PTHREAD_MUTEX_HAVE_PREV
+ instead of __WORDSIZE.
+
+2012-05-10 Thomas Schwinge <thomas@schwinge.name>
+
+ [BZ #3748]
+ * sysdeps/pthread/bits/libc-lockP.h (__libc_once_get): New macro.
+
+2012-05-09 Chung-Lin Tang <cltang@codesourcery.com>
+
+ * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S
+ (__pthread_cond_timedwait): Use CFI directives.
+ * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S
+ (__pthread_cond_wait): Likewise.
+ * sysdeps/unix/sysv/linux/sh/sem_timedwait.S (sem_timedwait): Likewise.
+ * sysdeps/unix/sysv/linux/sh/sem_wait.S (__new_sem_wait): Likewise.
+
+2012-05-03 David S. Miller <davem@davemloft.net>
+
+ * sysdeps/sparc/sparc64/pthread_spin_unlock.S: Fix thinko, we
+ always have to return 0, especially for the pthread_spin_init
+ alias.
+ * sysdeps/sparc/sparc32/pthread_spin_lock.S: Add missing trailing
+ newline.
+ * sysdeps/sparc/sparc32/sparcv9/pthread_spin_lock.S: Likewise.
+ * sysdeps/sparc/sparc64/pthread_spin_lock.S: Likewise.
+
+2012-05-02 David S. Miller <davem@davemloft.net>
+
+ * sysdeps/sparc/sparc64/pthread_spin_lock.S: New.
+ * sysdeps/sparc/sparc64/pthread_spin_lock.c: Delete.
+ * sysdeps/sparc/sparc64/pthread_spin_unlock.S: New.
+ * sysdeps/sparc/sparc64/pthread_spin_unlock.c: Delete.
+ * sysdeps/sparc/sparc64/pthread_spin_trylock.S: New.
+ * sysdeps/sparc/sparc64/pthread_spin_trylock.c: Delete.
+ * sysdeps/sparc/sparc64/pthread_spin_init.c: New.
+ * sysdeps/sparc/sparc32/pthread_spin_lock.S: New.
+ * sysdeps/sparc/sparc32/pthread_spin_lock.c: Delete.
+ * sysdeps/sparc/sparc32/pthread_spin_trylock.S: New.
+ * sysdeps/sparc/sparc32/pthread_spin_trylock.c: Delete.
+ * sysdeps/sparc/sparc32/sparcv9/pthread_spin_lock.S: New.
+ * sysdeps/sparc/sparc32/sparcv9/pthread_spin_lock.c: Delete.
+ * sysdeps/sparc/sparc32/sparcv9/pthread_spin_trylock.S: New.
+ * sysdeps/sparc/sparc32/sparcv9/pthread_spin_trylock.c: Delete.
+ * sysdeps/sparc/sparc32/sparcv9/pthread_spin_unlock.S: New.
+ * sysdeps/sparc/sparc32/sparcv9/pthread_spin_unlock.c: Delete.
+ * sysdeps/sparc/sparc32/sparcv9/pthread_spin_init.c: New.
+
+2012-05-02 Allan McRae <allan@archlinux.org>
+
+ * Makefile: (LDFLAGS-tst-tls5): Use $(no-as-needed).
+ (LDFLAGS-tst-cancel24): Likewise.
+
+2012-05-02 Paul Pluzhnikov <ppluzhnikov@google.com>
+
+ * sysdeps/i386/pthread_spin_lock.S: New.
+ * sysdeps/i386/pthread_spin_lock.c: Delete.
+ * sysdeps/x86_64/pthread_spin_lock.S: New.
+ * sysdeps/x86_64/pthread_spin_lock.c: Delete.
+
+2012-04-28 Andreas Schwab <schwab@linux-m68k.org>
+
+ * Makefile ($(objpfx)tst-stack3-mem, $(objpfx)tst-tls6.out): Don't
+ run when cross-compiling.
+
+2012-04-26 Siddhesh Poyarekar <siddhesh@redhat.com>
+
+ * sysdeps/pthread/unwind-forcedunwind.c: Include gnu/lib-names.h
+ instead of libgcc_s.h.
+
+2012-04-20 Paul Pluzhnikov <ppluzhnikov@google.com>
+
+ * sysdeps/x86_64/tls.h (TLS_GET_FS, TLS_SET_FS): Delete.
+
+2012-03-27 David S. Miller <davem@davemloft.net>
+
+ * tst-cond16.c (do_test): Use a thread stack size which is either
+ PTHREAD_STACK_MIN or the page size, whichever is larger.
+ * tst-cond18.c (do_test): Likewise.
+
+2012-03-19 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/x86_64/pthreaddef.h (CURRENT_STACK_FRAME): Use
+ register char * __asm__("rsp") to get stack frame.
+
+2012-03-19 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (SYS_futex): Use
+ __NR_futex directly.
+
+2012-03-19 H.J. Lu <hongjiu.lu@intel.com>
+
+ * unwind.c (unwind_stop): Cast _Unwind_GetCFA return to
+ _Unwind_Ptr first.
+
+2012-03-16 David S. Miller <davem@davemloft.net>
+
+ [BZ #13844]
+ * sysdeps/unix/sysv/linux/libc-lowlevellock.c: Include using <..>
+ instead of "...".
+ * sysdeps/unix/sysv/linux/sparc/sparc32/libc-lowlevellock.c:
+ Delete, not needed.
+
+2012-03-15 David S. Miller <davem@davemloft.net>
+
+ [BZ #13844]
+ * sysdeps/unix/sysv/linux/sparc/sparc32/libc-lowlevellock.c: New file.
+
+2012-03-09 Paul Eggert <eggert@cs.ucla.edu>
+
+ [BZ #13673]
+ * pt-crti.S: Replace FSF snail mail address with URL.
+
+2012-03-09 Joseph Myers <joseph@codesourcery.com>
+
+ * sysdeps/pthread/pthread.h (__need_clockid_t, __need_timespec):
+ Do not define before including <time.h>.
+
+2012-03-08 David S. Miller <davem@davemloft.net>
+
+ * sysdeps/unix/sysv/linux/sparc/sem_post.c: Update copyright year.
+
+2012-03-08 Thomas Schwinge <thomas@codesourcery.com>
+
+ * sysdeps/unix/sysv/linux/sh/lowlevellock.S (__lll_timedlock_wait):
+ Check for timestamp before the Epoch.
+
+ * sysdeps/unix/sysv/linux/sh/sem_timedwait.S (sem_timedwait): Fix
+ updating nwaiters.
+
+ * tst-sem13.c (do_test): Add another test case.
+ * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S (sem_timedwait):
+ Fix updating nwaiters.
+
+2012-03-07 Joseph Myers <joseph@codesourcery.com>
+
+ [BZ #10545]
+ * sysdeps/pthread/configure.in (libc_cv_forced_unwind): Change
+ link test to a compile test.
+ (libc_cv_c_cleanup): Likewise. Declare puts rather than including
+ <stdio.h>.
+ * sysdeps/pthread/configure: Regenerated.
+
+2012-03-07 Ulrich Drepper <drepper@gmail.com>
+
+ * Makefile (distribute): Remove variable.
+
+2012-01-23 Thomas Schwinge <thomas@codesourcery.com>
+
+ * sysdeps/unix/sysv/linux/sem_timedwait.c (sem_timedwait): Get rid of
+ superfluous assignment.
+ * sysdeps/unix/sysv/linux/sparc/sem_timedwait.c (sem_timedwait):
+ Likewise.
+ * sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c
+ (sem_timedwait): Likewise.
+
+2012-03-06 Ulrich Drepper <drepper@gmail.com>
+
+ * sysdeps/pthread/bits/libc-lock.h: Move information not needed in
+ installed headers to...
+ * sysdeps/pthread/bits/libc-lockP.h: ...here. New file.
+
+2012-03-06 David S. Miller <davem@davemloft.net>
+
+ * sysdeps/unix/sysv/linux/sparc/sem_post.c (__new_sem_post): Use
+ atomic_increment and remove unused local variable.
+ (__old_sem_post): Likewise.
+
+2012-02-27 David S. Miller <davem@davemloft.net>
+
+ * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Don't refer to
+ non-existing __pthread_attr.
+ * 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.
+
+2012-02-26 Ulrich Drepper <drepper@gmail.com>
+
+ * sysdeps/pthread/pthread.h: Define __need_clockid_t for __USE_XOPEN2K.
+
+ * sysdeps/pthread/pthread.h: Define __need_timespec before including
+ <time.h>.
+ * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Name pthread_attr_t
+ union.
+ * 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.
+
+2012-02-21 Joseph Myers <joseph@codesourcery.com>
+
+ [BZ #13695]
+ * Makefile (generated): Remove crti.S, crtn.S, defs.h and
+ pt-initfini.s.
+ [crti.S not in sysdirs] (omit-deps): Do not append.
+ [crti.S not in sysdirs] (CFLAGS-pt-initfini.s): Remove variable.
+ [crti.S not in sysdirs] (pt-initfini.c): Remove vpath directive.
+ [crti.S not in sysdirs] ($(objpfx)crti.S): Remove rule.
+ [crti.S not in sysdirs] ($(objpfx)crtn.S): Likewise.
+ [crti.S not in sysdirs] ($(objpfx)defs.h): Likewise.
+ [crti.S not in sysdirs] ($(objpfx)crti.o): Likewise.
+ [crti.S not in sysdirs] ($(objpfx)crtn.o): Likewise.
+ [crti.S in sysdirs] (extra-objs): Append unconditionally.
+ [crti.S in sysdirs] ($(objpfx)crti.o): Define rule
+ unconditionally.
+ * sysdeps/pthread/pt-initfini.c: Remove file.
+
+2012-02-16 Richard Henderson <rth@twiddle.net>
+
+ * sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c: Remove file.
+ * sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c: Remove file.
+
+2012-02-15 Kaz Kojima <kkojima@rr.iij4u.or.jp>
+
+ * sysdeps/unix/sysv/linux/sh/pt-initfini.c: Remove file.
+
+2012-02-16 David S. Miller <davem@davemloft.net>
+
+ * sysdeps/sparc/Makefile: Add -fPIC when building pt-crti.S and crtn.S
+
+2012-02-15 Marek Polacek <polacek@redhat.com>
+
+ * sysdeps/unix/sysv/linux/x86_64/Makefile: Remove file.
+
+2012-02-09 Paul Eggert <eggert@cs.ucla.edu>
+
+ Replace FSF snail mail address with URLs, as per GNU coding standards.
+
+2012-02-08 Andreas Schwab <schwab@linux-m68k.org>
+
+ * Makefile (extra-objs) [crti.S in sysdirs]: Add pt-crti.o.
+
+2012-02-08 Joseph Myers <joseph@codesourcery.com>
+
+ Support crti.S and crtn.S provided directly by architectures.
+ * Makefile [crti.S in sysdirs] (omit-deps): Do not append.
+ [crti.S in sysdirs] (CFLAGS-pt-initfini.s): Do not define variable.
+ [crti.S in sysdirs] ($(objpfx)pt-initfini.s): Disable rule.
+ [crti.S in sysdirs] ($(objpfx)crti.S): Likewise.
+ [crti.S in sysdirs] ($(objpfx)crtn.S): Likewise.
+ [crti.S in sysdirs] ($(objpfx)defs.h): Likewise.
+ [crti.S in sysdirs] ($(objpfx)crti.o): Likewise.
+ [crti.S in sysdirs] ($(objpfx)crtn.o): Likewise.
+ [crti.S in sysdirs] (pt-initfini.c): Remove vpath directive.
+ [crti.S in sysdirs] ($(objpfx)crti.o): New rule.
+ * pt-crti.S: New file.
+ * sysdeps/unix/sysv/linux/i386/Makefile: Remove file.
+
+2012-02-03 Joseph Myers <joseph@codesourcery.com>
+
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Use
+ macros for PIC register setup.
+ * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Likewise.
+ * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise.
+ * sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S: Likewise.
+ * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Likewise.
+ * sysdeps/unix/sysv/linux/i386/pthread_once.S: Likewise.
+
+2012-01-11 Marek Polacek <polacek@redhat.com>
+
+ * forward.c (FORWARD_NORETURN): Define macro.
+ (__pthread_unwind): Use FORWARD_NORETURN macro to avoid warning.
+ (__pthread_exit): Likewise.
+
+2012-01-10 Ulrich Drepper <drepper@gmail.com>
+
+ * sysdeps/pthread/pthread.h: Add const attribute to pthread_equal.
+
+ * pthreadP.h: Add noreturn to __pthread_exit.
+ * sysdeps/pthread/pthread-functions.h: Likewise for ptr___pthread_exit.
+
+2011-12-30 Adhemerval Zanella <azanella@linux.vnet.ibm.com>
+
+ * sysdeps/unix/sysv/linux/aio_misc.h (__aio_create_helper_thread):
+ Call pthread_attr_setstacksize() with result of
+ __pthread_get_minstack() to account for application TLS usage.
+
+2012-01-08 Marek Polacek <polacek@redhat.com>
+
+ * sysdeps/unix/sysv/linux/mq_notify.c: Include <nptl/pthreadP.h>.
+
+2012-01-07 Ulrich Drepper <drepper@gmail.com>
+
+ [BZ #13553]
+ * pthreadP.h: Use const instead of __const.
+ * semaphore.h: Likewise.
+ * sysdeps/pthread/bits/libc-lock.h: Likewise.
+ * sysdeps/pthread/bits/sigthread.h: Likewise.
+ * sysdeps/pthread/pthread.h: Likewise.
+
+ * Makefile: Remove elf=yes test, only ELF is supported.
+
+ * shlib-versions: Remove entries for ports architectures.
+
+ In case anyone cares, the IA-64 architecture could move to ports.
+ * sysdeps/ia64/*: Removed.
+ * sysdeps/unix/sysv/linux/ia64/*: Removed.
+
+2011-12-22 Ulrich Drepper <drepper@gmail.com>
+
+ * sysdeps/pthread/gai_misc.h (__gai_create_helper_thread): Use
+ __pthread_get_minstack.
+ * sysdeps/unix/sysv/linux/mq_notify.c (init_mq_netlink): Likewise.
+
+ [BZ #13088]
+ * sysdeps/unix/sysv/linux/timer_routines.c: Get minimum stack size
+ through __pthread_get_minstack.
+ * nptl-init.c (__pthread_initialize_minimal_internal): Get page size
+ directly from _rtld_global_ro.
+ (__pthread_get_minstack): New function.
+ * pthreadP.h: Declare __pthread_get_minstack.
+ * Versions (libpthread) [GLIBC_PRIVATE]: Add __pthread_get_minstack.
+
+2011-12-21 Ulrich Drepper <drepper@gmail.com>
+
+ [BZ #13515]
+ * sysdeps/unix/sysv/linux/pthread_getname.c (pthread_getname_np):
+ Correct reading name from file.
+
+2011-12-14 Carlos O'Donell <carlos@systemhalted.org>
+
+ * allocatestack.c (allocate_stack): Return errno on failure.
+
+2011-12-14 Jeff Law <law@redhat.com>
+
+ [BZ #5245]
+ * pthread_create.c (__pthread_create_2_1): Translate ENOMEM to EAGAIN.
+
+2011-11-28 Andreas Schwab <schwab@redhat.com>
+
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Handle
+ EAGAIN from FUTEX_WAIT_REQUEUE_PI.
+ * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise.
+
+2011-11-15 Ulrich Drepper <drepper@gmail.com>
+
+ * pthread_getattr_np.c (pthread_getattr_np): Set FD_CLOEXEC for
+ /proc/self/maps.
+
+2011-10-29 Ulrich Drepper <drepper@gmail.com>
+
+ [BZ #13358]
+ * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
+ (__pthread_cond_timedwait): Initialize %r15 correctly also for code
+ path for kernels with FUTEX_CLOCK_REALTIME.
+ Debugged by H.J. Lu <hjl.tools@gmail.com>.
+
+2011-10-27 Andreas Schwab <schwab@redhat.com>
+
+ [BZ #13344]
+ * sysdeps/pthread/pthread.h: Use __THREADNL instead of __THREAD
+ for memory synchronization functions.
+ * semaphore.h: Likewise.
+
+2011-10-24 Ulrich Drepper <drepper@gmail.com>
+
+ * tst-cancel7.c: Avoid warning.
+ * tst-mutex6.c: Likewise.
+ * tst-mutex9.c: Likewise.
+ * tst-mutexpi6.c: Likewise.
+
+2011-10-23 Ulrich Drepper <drepper@gmail.com>
+
+ * sysdeps/i386/tls.h: Remove #include <list.h>.
+
+2011-10-15 Ulrich Drepper <drepper@gmail.com>
+
+ * pthread_create.c (start_thread): Call __ctype_init.
+
+2011-09-15 Andreas Schwab <schwab@redhat.com>
+
+ * sysdeps/pthread/list.h: Define only list_t if __need_list_t is
+ defined.
+ (list_add): Add atomic_write_barrier.
+ * descr.h: Define __need_list_t before including <list.h>.
+ * nptl-init.c: Include <list.h>
+ * allocatestack.c: Likewise.
+
+2011-09-11 Ulrich Drepper <drepper@gmail.com>
+
+ * sysdeps/i386/tls.h: Remove HAVE_TLS_SUPPORT test.
+ * 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.
+
+2011-09-10 Ulrich Drepper <drepper@gmail.com>
+
+ * sysdeps/pthread/malloc-machine.h: Define MUTEX_INITIALIZER.
+
+ * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Don't handle
+ !USE___THREAD.
+ * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise.
+ * sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S: Likewise.
+ * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Likewise.
+ * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h: Likewise.
+ * sysdeps/unix/sysv/linux/sh/sem_post.S: Likewise.
+ * sysdeps/unix/sysv/linux/sh/sem_timedwait.S: Likewise.
+ * sysdeps/unix/sysv/linux/sh/sem_trywait.S: Likewise.
+ * sysdeps/unix/sysv/linux/sh/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_trywait.S: Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise.
+
+ * tst-tls1.c: Support for __thread is now mandatory.
+ * tst-tls2.c: Likewise.
+ * tst-tls3.c: Likewise.
+ * tst-tls3mod.c: Likewise.
+ * tst-tls4.c: Likewise.
+ * tst-tls4moda.c: Likewise.
+ * tst-tls4modb.c: Likewise.
+ * tst-tls5.h: Likewise.
+
+2011-09-08 Ulrich Drepper <drepper@gmail.com>
+
+ [BZ #12403]
+ * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S
+ (pthread_rwlock_timedwrlock): Use correct macro in test.
+ Patch by H.J. Lu <hongjiu.lu@intel.com>.
+
+2011-09-06 Ulrich Drepper <drepper@gmail.com>
+
+ * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S (sem_timedwait): Don't
+ use gettimeofday vsyscall, just call gettimeofday.
+ * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.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_cond_timedwait.S: Likewise.
+ Simplify __vdso_clock_gettime use.
+
+2011-09-05 David S. Miller <davem@davemloft.net>
+
+ * sysdeps/unix/sysv/linux/sem_timedwait.c (do_futex_timed_wait):
+ New function.
+ (sem_timedwait): Call it to force an exception region around
+ the async cancel enable and the futex operation.
+ * sysdeps/unix/sysv/linux/sparc/sem_timedwait.c: Likewise.
+ * sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c: Likewise.
+ * sysdeps/unix/sysv/linux/sem_wait.c (do_futex_wait): New function.
+ (__new_sem_wait): Call it to force an exception region around
+ the async cancel enable and the futex operation.
+ * sysdeps/unix/sysv/linux/sparc/sem_wait.c: Likewise.
+ * sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c: Likewise.
+
+2011-08-31 Andreas Schwab <schwab@redhat.com>
+
+ * allocatestack.c (setxid_mark_thread): Ensure that the exiting
+ thread is woken up.
+
+2011-08-20 David S. Miller <davem@davemloft.net>
+
+ * Makefile (tst-cleanup0.out): Fix typo in output redirection.
+
+2011-08-14 Roland McGrath <roland@hack.frob.com>
+
+ * sysdeps/i386/pthreaddef.h (TCB_ALIGNMENT): Set to 64, optimal on Atom.
+ * sysdeps/x86_64/pthreaddef.h (TCB_ALIGNMENT): Likewise.
+
+2011-08-08 Andreas Schwab <schwab@redhat.com>
+
+ * sysdeps/unix/sysv/linux/x86_64/cancellation.S: Maintain aligned
+ stack.
+ * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise.
+
+2011-07-22 Ulrich Drepper <drepper@gmail.com>
+
+ * sysdeps/pthread/unwind-forcedunwind.c (_Unwind_Resume): Add read
+ barrier.
+ (__gcc_personality_v0): Likewise.
+ (_Unwind_ForcedUnwind): Likewise.
+ (_Unwind_GetCFA): Likewise.
+
+2011-07-14 Roland McGrath <roland@hack.frob.com>
+
+ * allocatestack.c (__reclaim_stacks): Use uintptr_t cast rather than
+ UINTMAX_C.
+
+2011-06-30 Ulrich Drepper <drepper@gmail.com>
+
+ * nptl-init.c (__nptl_set_robust): New function.
+ (pthread_functions): Add reference.
+ * npthreadP.h: Declare __nptl_set_robust.
+ * sysdeps/pthread/pthread-functions.h (pthread_functions): Add
+ ptr_set_robust member.
+ * sysdeps/unix/sysv/linux/fork.c: Call set_robust_list syscall in
+ child if threads are used.
+
+2011-06-14 Andreas Jaeger <aj@suse.de>
+
+ * pthread_rwlock_init.c: Include <string.h> for memset declaration.
+
+2011-05-11 Ulrich Drepper <drepper@gmail.com>
+
+ [BZ #386]
+ * allocatestack.c (allocate_stack): Convert ENOMEM error to EAGAIN.
+
+2011-04-10 Ulrich Drepper <drepper@gmail.com>
+
+ [BZ #12650]
+ * allocatestack.c (get_cached_stack): Deallocate DTV entries before
+ clearing memory.
+ Patch partly by Robert Rex <robert.rex@exasol.com>.
+
+2011-01-19 Roland McGrath <roland@redhat.com>
+
+ * pthread_cond_wait.c (__pthread_cond_wait): Fix comment typo.
+ * pthread_cond_timedwait.c (__pthread_cond_timedwait): Likewise.
+ * pthread_rwlock_rdlock.c (__pthread_rwlock_rdlock): Likewise.
+ * pthread_rwlock_wrlock.c (__pthread_rwlock_wrlock): Likewise.
+ * pthread_rwlock_timedrdlock.c (pthread_rwlock_timedrdlock): Likewise.
+ * pthread_rwlock_timedwrlock.c (pthread_rwlock_timedwrlock): Likewise.
+
+2011-01-16 Andreas Schwab <schwab@linux-m68k.org>
+
+ * Makefile (test-extras): Add tst-cleanup4aux.
+
+2011-01-14 Ulrich Drepper <drepper@gmail.com>
+
+ [BZ #10563]
+ * sysdeps/pthread/setxid.h (__SETXID_1): Add cast to assignment.
+ (__SETXID_2): Likewise.
+ (__SETXID_3): Likewise.
+
+2011-01-13 Ulrich Drepper <drepper@gmail.com>
+
+ [BZ #10484]
+ * Versions [libc] (GLIBC_PRIVATE): Export __libc_alloca_cutoff.
+ * alloca_cutoff.c: Add libc_hidden_def.
+
+2010-10-13 H.J. Lu <hongjiu.lu@intel.com>
+
+ [BZ #12113]
+ * sysdeps/x86_64/pthreaddef.h (TCB_ALIGNMENT): Changed to 32.
+ * sysdeps/x86_64/tls.h (TLS_TCB_ALIGN): Defined with alignment
+ of "struct pthread".
+
+2010-09-21 Andreas Schwab <schwab@redhat.com>
+
+ * sysdeps/pthread/pthread.h (pthread_cleanup_push)
+ [!__EXCEPTIONS]: Mangle local variable not_first_call.
+ (pthread_cleanup_push_defer_np): Likewise.
+
+2010-09-03 Ulrich Drepper <drepper@redhat.com>
+
+ * sysdeps/pthread/allocalim.h (__libc_use_alloca): Expect blocks are
+ small.
+
+2010-08-10 Dinakar Guniguntala <dino@in.ibm.com>
+ Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
+
+ * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: If
+ FUTEX_WAKE_OP fails make sure to call FUTEX_WAKE instead.
+
+2010-08-12 H.J. Lu <hongjiu.lu@intel.com>
+
+ * sysdeps/unix/sysv/linux/i386/Makefile: New file.
+
+2010-05-01 Alan Modra <amodra@gmail.com>
+
+ * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h
+ (PSEUDO): Use correct cr save. Don't use wrong parm save area
+ to save temps. Correct cfi for possible later frame manipulation.
+ (DOCARGS_1, UNDOCARGS_1): Use the correct parm save area.
+ (DOCARGS_2, UNDOCARGS_2, DOCARGS_3, UNDOCARGS_3): Likewise.
+ (DOCARGS_4, UNDOCARGS_4, DOCARGS_5, UNDOCARGS_5): Likewise.
+ (DOCARGS_6, UNDOCARGS_6): Likewise.
+ (CENABLE, CDISABLE): Add nops for non-shared calls.
+
+2010-07-06 Andreas Schwab <schwab@redhat.com>
+
+ * sysdeps/unix/sysv/linux/pthread_getname.c (pthread_getname_np):
+ Fix type mismatch.
+
+2010-07-03 Ulrich Drepper <drepper@redhat.com>
+
+ * tst-abstime.c (do_test): Some more cleanups
+
+2010-07-02 Ulrich Drepper <drepper@redhat.com>
+
+ * tst-abstime.c: Correct testing and add test for sem_timedwait.
+
+2010-07-01 Andreas Schwab <schwab@redhat.com>
+ Ulrich Drepper <drepper@redhat.com>
+
+ * Makefile (tests): Add tst-abstime.
+ * tst-abstime.c: New file.
+ * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S
+ (__lll_timedlock_wait): Check for timestamp before the Epoch.
+ * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S
+ (__lll_timedlock_wait): Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S
+ (__lll_robust_timedlock_wait): Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S
+ (__pthread_cond_timedwait): Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S
+ (pthread_rwlock_timedrdlock): Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S
+ (pthread_rwlock_timedwrlock): Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S (sem_timedwait):
+ Likewise.
+
+2010-07-01 Ulrich Drepper <drepper@redhat.com>
+
+ * Makefile (tst-_res1): Add tst-_res1mod1 to dependency list.
+
+2010-06-01 Takashi Yoshii <takashi.yoshii.zj@renesas.com>
+
+ * sysdeps/unix/sysv/linux/sh/lowlevellock.S: Fix incorrect
+ location of ifndef __ASSUME_FUTEX_CLOCK_REALTIME.
+
+2010-04-09 Ulrich Drepper <drepper@redhat.com>
+
+ [BZ #11390]
+ * sysdeps/unix/sysv/linux/pthread_getname.c: New file.
+ * sysdeps/unix/sysv/linux/pthread_setname.c: New file.
+ * nptl/sysdeps/pthread/pthread.h: Declare pthread_getname and
+ pthread_setname.
+ * Makefile (libpthread-routines): Add pthread_getname and
+ pthread_setname.
+ * Versions: Export pthread_getname and pthread_setname for GLIBC_2.12.
+
+2010-04-05 Thomas Schwinge <thomas@schwinge.name>
+
+ * sysdeps/pthread/unwind-resume.c: Moved to main tree sysdeps/gnu/.
+ * sysdeps/pthread/rt-unwind-resume.c: Likewise.
+ * sysdeps/pthread/Makefile: Remove csu section and rt section's
+ unwind-resume bits, now in main tree sysdeps/gnu/Makefile instead.
+
+2010-03-23 Luis Machado <luisgpm@br.ibm.com>
+
+ * pthread_cond_timedwait.c: Add check for
+ HAVE_CLOCK_GETTIME_VSYSCALL to use VDSO whenever possible.
+ (pthread_cond_timedwait): Use INTERNAL_VSYSCALL instead of
+ INTERNAL_SYSCALL.
+
+2010-03-09 Ulrich Drepper <drepper@redhat.com>
+
+ * pthread_create.c (__pthread_create_2_1): If priorities are incorrect
+ and the call fails wake eventually waiting setxid threads. Don't free
+ stack here if we try starting a thread.
+ * sysdeps/pthread/createthread.c (do_clone): Only wake setxid waiter
+ if the clone call failed.
+
+2010-03-08 Andreas Schwab <schwab@redhat.com>
+
+ * pthread_create.c (__pthread_create_2_1): Don't set setxid_futex.
+ * allocatestack.c (get_cached_stack): Set setxid_futex.
+ (allocate_stack): Likewise.
+
+2010-03-05 Andreas Schwab <schwab@redhat.com>
+ Ulrich Drepper <drepper@redhat.com>
+
+ * allocatestack.c (setxid_mark_thread): Delay handling of thread if
+ it is creating a thread or it is just being created.
+ * pthread_create.c (start_thread): Wake setxid thread if it is
+ waiting.
+ (__pthread_create_2_1): Initialize setxid_futex.
+ * sysdeps/pthread/createthread.c (do_clone): Wake setxid thread if it
+ is waiting.
+
+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.
--- /dev/null
+++ b/fbtl/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;
+}
--- /dev/null
+++ b/fbtl/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);
+}
--- /dev/null
+++ b/fbtl/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);
+}
--- /dev/null
+++ b/fbtl/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();
+}
--- /dev/null
+++ b/fbtl/DESIGN-systemtap-probes.txt
@@ -0,0 +1,89 @@
+Systemtap is a dynamic tracing/instrumenting tool available on Linux. Probes
+that are not fired at run time have close to zero overhead.
+
+The following probes are available for NPTL:
+
+Thread creation & Join Probes
+=============================
+pthread_create - probe for pthread_create
+ arg1 = pointer (pthread_t*) to thread
+ arg2 = pointer (pthread_attr_t*) to attr
+ arg3 = pointer (void *) to start_routine
+ arg4 = arguments to start_routine
+pthread_start - probe for actual thread creation
+ arg1 = struct pthread (members include thread ID, process ID)
+ arg2 = address of start_routine
+ arg3 = pointer to the list of arguments
+pthread_join - probe for pthread_join
+ arg1 = thread ID
+pthread_join_ret - probe for pthread_join return
+ arg1 = thread ID
+ arg2 = return value
+
+Lock-related Probes
+===================
+mutex_init - probe for pthread_mutex_init
+ arg1 = address of mutex lock
+mutex_acquired - probe for succ. return of pthread_mutex_lock
+ arg1 = address of mutex lock
+mutex_timedlock_acquired - probe for succ. return of pthread_mutex_timedlock
+ arg1 = address of mutex lock
+mutex_entry - probe for entry to the pthread_mutex_lock function
+ arg1 = address of mutex lock
+mutex_timedlock_entry - probe for entry to the pthread_mutex_timedlock function
+ arg1 = address of mutex lock, arg2 = address of timespec
+mutex_release - probe for pthread_mutex_unlock after the successful release of a
+ mutex lock
+ arg1 = address of mutex lock
+mutex_destroy - probe for pthread_mutex_destroy
+ arg1 = address of mutex lock
+
+wrlock_entry - probe for entry to the pthread_rwlock_wrlock function
+ arg1 = address of rw lock
+rdlock_entry - probe for entry to the pthread_rwlock_rdlock function
+ arg1 = address of rw lock
+
+rwlock_destroy - probe for pthread_rwlock_destroy
+ arg1 = address of rw lock
+wrlock_acquire_write - probe for pthread_rwlock_wrlock (after getting the lock)
+ arg1 = address of rw lock
+rdlock_acquire_read - probe for pthread_rwlock_rdlock after successfully getting
+ the lock
+ arg1 = address of rw lock
+rwlock_unlock - probe for pthread_rwlock_unlock
+ arg1 = address of rw lock
+
+lll_lock_wait - probe in low-level (assembly language) locking code, only fired
+ when futex/FUTEX_WAIT is called (i.e. when trying to acquire a
+ contented lock)
+ arg1 = pointer to futex
+ arg2 = flags passed to the futex system call
+lll_lock_wait_private - probe in low-level (assembly language) locking code,
+ only fired when futex/FUTEX_WAIT is called (i.e. when
+ trying to acquire a contented lock)
+ arg1 = pointer to futex
+
+lll_futex_wake - probe in low-level (assembly language) locking code, only fired
+ when futex (FUTEX_WAKE) is called
+ arg1 = pointer to futex
+ arg2 = number of processes to wake
+ arg3 = additional flags
+
+Condition variable Probes
+=========================
+cond_init - probe for pthread_cond_init
+ arg1 = condition
+ arg2 = attr
+cond_destroy - probe for pthread_cond_destroy
+ arg1 = cond
+cond_wait - probe for pthread_cond_wait
+ arg1 = condition
+ arg2 = mutex lock
+cond_timedwait - probe for pthread_cond_timedwait
+ arg1 = condition
+ arg2 = mutex lock
+ arg3 = timespec
+cond_signal - probe for pthread_cond_signal
+ arg1 = condition
+cond_broadcast - probe for pthread_cond_broadcast
+ arg1 = condition
--- /dev/null
+++ b/fbtl/Makeconfig
@@ -0,0 +1,32 @@
+# Copyright (C) 2002-2013 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, see
+# <http://www.gnu.org/licenses/>.
+
+# Makeconfig fragment for NPTL add-on.
+# This gets included at the end of the main glibc Makeconfig.
+
+have-thread-library = yes
+
+shared-thread-library = $(common-objpfx)fbtl/libpthread_nonshared.a \
+ $(common-objpfx)fbtl/libpthread.so
+static-thread-library = $(common-objpfx)fbtl/libpthread.a
+
+rpath-dirs += fbtl
+
+# This makes for ptw-*.? object rules in sysd-rules.
+ptw-CPPFLAGS := -DPTW
+sysd-rules-patterns += ptw-%:%
--- /dev/null
+++ b/fbtl/Makefile
@@ -0,0 +1,642 @@
+# Copyright (C) 2002-2013 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+#
+# Sub-makefile for NPTL portion of the library.
+#
+subdir := fbtl
+
+headers := pthread.h semaphore.h bits/semaphore.h
+
+extra-libs := libpthread
+extra-libs-others := $(extra-libs)
+install-lib-ldscripts := libpthread.so
+
+routines = alloca_cutoff forward libc-lowlevellock libc-cancellation \
+ libc-cleanup
+shared-only-routines = forward
+
+libpthread-routines = nptl-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_mutexattr_init pthread_mutexattr_destroy \
+ pthread_mutexattr_getpshared \
+ pthread_mutexattr_setpshared \
+ 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 \
+ old_pthread_cond_init old_pthread_cond_destroy \
+ old_pthread_cond_wait old_pthread_cond_timedwait \
+ old_pthread_cond_signal old_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 \
+ old_pthread_atfork pthread_atfork \
+ pthread_getcpuclockid \
+ pthread_clock_gettime pthread_clock_settime \
+ shm-directory \
+ 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 ptw-sigsuspend \
+ pt-raise pt-system \
+ flockfile ftrylockfile funlockfile \
+ sigaction \
+ herrno res pt-allocrtsig \
+ pthread_kill_other_threads \
+ pthread_getaffinity pthread_setaffinity \
+ pthread_attr_getaffinity pthread_attr_setaffinity \
+ cleanup_routine unwind-forcedunwind \
+ pthread_setname pthread_getname \
+ pthread_setattr_default_np pthread_getattr_default_np
+
+# lowlevelrobustlock
+# pthread_sigqueue
+
+# post linuxthreads interfaces
+
+# pthread_mutexattr_getrobust pthread_mutexattr_setrobust \
+# pthread_mutex_consistent \
+# pthread_mutexattr_getprotocol \
+# pthread_mutexattr_setprotocol \
+# pthread_mutexattr_getprioceiling \
+# pthread_mutexattr_setprioceiling tpp \
+# pthread_mutex_getprioceiling \
+# pthread_mutex_setprioceiling \
+
+# commented out also in nptl
+
+# pthread_setuid pthread_seteuid pthread_setreuid \
+# pthread_setresuid \
+# pthread_setgid pthread_setegid pthread_setregid \
+# pthread_setresgid
+
+libpthread-shared-only-routines = version pt-allocrtsig unwind-forcedunwind
+libpthread-static-only-routines = pthread_atfork
+
+# 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.
+
+# nptl-init.c contains sigcancel_handler().
+CFLAGS-nptl-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-open.c = -fexceptions -fasynchronous-unwind-tables
+CFLAGS-open64.c = -fexceptions -fasynchronous-unwind-tables
+CFLAGS-pause.c = -fexceptions -fasynchronous-unwind-tables
+CFLAGS-recv.c = -fexceptions -fasynchronous-unwind-tables
+CFLAGS-send.c = -fexceptions -fasynchronous-unwind-tables
+
+CFLAGS-pt-system.c = -fexceptions
+
+
+tests = tst-typesizes \
+ tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
+ tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex5 tst-mutex6 \
+ tst-mutex7 tst-mutex8 tst-mutex9 tst-mutex5a tst-mutex7a \
+ tst-spin1 tst-spin2 tst-spin3 \
+ tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \
+ tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \
+ tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \
+ tst-cond20 tst-cond21 tst-cond22 tst-cond23 \
+ tst-rwlock1 tst-rwlock2 tst-rwlock2a tst-rwlock3 tst-rwlock4 \
+ tst-rwlock5 tst-rwlock6 tst-rwlock7 tst-rwlock8 tst-rwlock9 \
+ tst-rwlock10 tst-rwlock11 tst-rwlock12 tst-rwlock13 tst-rwlock14 \
+ tst-once1 tst-once2 tst-once3 tst-once4 \
+ tst-key1 tst-key2 tst-key3 tst-key4 \
+ tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \
+ tst-sem8 tst-sem9 tst-sem10 tst-sem11 tst-sem12 tst-sem13 tst-sem14 \
+ tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 \
+ tst-align tst-align2 tst-align3 \
+ tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \
+ tst-basic7 \
+ tst-kill1 tst-kill2 tst-kill3 tst-kill4 tst-kill5 tst-kill6 \
+ tst-raise1 \
+ tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 tst-join6 \
+ tst-detach1 \
+ tst-eintr1 tst-eintr2 tst-eintr3 tst-eintr4 tst-eintr5 \
+ tst-tsd1 tst-tsd2 tst-tsd3 tst-tsd4 tst-tsd5 tst-tsd6 \
+ tst-tls1 tst-tls2 \
+ tst-fork1 tst-fork2 tst-fork3 tst-fork4 \
+ tst-atfork1 \
+ tst-cancel1 tst-cancel2 tst-cancel3 tst-cancel4 tst-cancel5 \
+ tst-cancel6 tst-cancel7 tst-cancel8 tst-cancel9 tst-cancel10 \
+ tst-cancel11 tst-cancel12 tst-cancel13 tst-cancel14 tst-cancel15 \
+ tst-cancel16 tst-cancel17 tst-cancel18 tst-cancel19 tst-cancel20 \
+ tst-cancel21 tst-cancel22 tst-cancel23 tst-cancel24 tst-cancel25 \
+ tst-cancel-self tst-cancel-self-cancelstate \
+ tst-cancel-self-canceltype tst-cancel-self-testcancel \
+ tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 tst-cleanup4 \
+ tst-flock1 tst-flock2 \
+ tst-signal1 tst-signal2 tst-signal3 tst-signal4 tst-signal5 \
+ tst-signal6 tst-signal7 \
+ tst-exec1 tst-exec2 tst-exec3 tst-exec4 \
+ tst-exit1 tst-exit2 tst-exit3 \
+ tst-stdio1 tst-stdio2 \
+ tst-stack1 tst-stack2 tst-stack3 tst-pthread-getattr \
+ tst-pthread-attr-affinity \
+ tst-unload \
+ tst-dlsym1 \
+ tst-sysconf \
+ tst-locale1 tst-locale2 \
+ tst-umask1 \
+ tst-popen1 \
+ tst-clock1 \
+ tst-context1 \
+ tst-sched1 \
+ tst-backtrace1 \
+ tst-abstime \
+ tst-vfork1 tst-vfork2 tst-vfork1x tst-vfork2x \
+ tst-getpid1 tst-getpid2 tst-getpid3 \
+ tst-initializers1 $(patsubst %,tst-initializers1-%,c89 gnu89 c99 gnu99)
+
+# These tests do not even compile due to missing pthread_* functions
+# tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 tst-mutexpi5 \
+# tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a tst-mutexpi8 \
+# tst-mutexpi9 \
+# tst-cond24 tst-cond25 \
+# tst-cond-except \
+# tst-robust1 tst-robust2 tst-robust3 tst-robust4 tst-robust5 \
+# tst-robust6 tst-robust7 tst-robust8 tst-robust9 \
+# tst-robustpi1 tst-robustpi2 tst-robustpi3 tst-robustpi4 tst-robustpi5 \
+# tst-robustpi6 tst-robustpi7 tst-robustpi8 tst-robustpi9 \
+
+xtests = tst-setuid1 tst-setuid1-static tst-mutexpp1 tst-mutexpp6 tst-mutexpp10
+test-srcs = tst-oddstacklimit
+
+# Files which must not be linked with libpthread.
+tests-nolibpthread = tst-unload
+
+gen-as-const-headers = pthread-errnos.sym
+
+LDFLAGS-pthread.so = -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst
+
+include ../Makeconfig
+
+tests += tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx5 \
+ tst-cancelx6 tst-cancelx7 tst-cancelx8 tst-cancelx9 tst-cancelx10 \
+ tst-cancelx11 tst-cancelx12 tst-cancelx13 tst-cancelx14 tst-cancelx15 \
+ tst-cancelx16 tst-cancelx17 tst-cancelx18 tst-cancelx20 tst-cancelx21 \
+ tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3 tst-cleanupx4 \
+ tst-oncex3 tst-oncex4
+ifeq ($(build-shared),yes)
+tests += tst-atfork2 tst-tls3 tst-tls4 tst-tls5 tst-_res1 tst-fini1 \
+ tst-stackguard1
+tests-nolibpthread += tst-fini1
+ifeq ($(have-z-execstack),yes)
+tests += tst-execstack
+endif
+endif
+
+modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \
+ tst-tls5mod tst-tls5moda tst-tls5modb tst-tls5modc \
+ tst-tls5modd tst-tls5mode tst-tls5modf \
+ tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod
+extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) tst-cleanup4aux.o
+test-extras += $(modules-names) tst-cleanup4aux
+test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names)))
+
+tst-atfork2mod.so-no-z-defs = yes
+tst-tls3mod.so-no-z-defs = yes
+tst-tls5mod.so-no-z-defs = yes
+tst-tls5moda.so-no-z-defs = yes
+tst-tls5modb.so-no-z-defs = yes
+tst-tls5modc.so-no-z-defs = yes
+tst-tls5modd.so-no-z-defs = yes
+tst-tls5mode.so-no-z-defs = yes
+tst-tls5modf.so-no-z-defs = yes
+
+ifeq ($(build-shared),yes)
+# Build all the modules even when not actually running test programs.
+tests: $(test-modules)
+endif
+
+ifeq ($(build-shared),yes)
+
+# Set the `multidir' variable by grabbing the variable from the compiler.
+# We do it once and save the result in a generated makefile.
+-include $(objpfx)multidir.mk
+$(objpfx)multidir.mk: $(common-objpfx)config.make
+ $(make-target-directory)
+ dir=`$(CC) $(CFLAGS) $(CPPFLAGS) -print-multi-directory`; \
+ echo "multidir := $$dir" > $@T
+ mv -f $@T $@
+
+crti-objs := crti.o
+crtn-objs := crtn.o
+ifneq (,$(patsubst .,,$(multidir)))
+generated-dirs := $(firstword $(subst /, , $(multidir)))
+crti-objs += $(multidir)/crti.o
+crtn-objs += $(multidir)/crtn.o
+$(objpfx)$(multidir):
+ mkdir -p $@
+endif
+extra-objs += $(crti-objs) $(crtn-objs)
+extra-objs += pt-crti.o
+endif
+
+CFLAGS-flockfile.c = $(libio-mtsafe)
+CFLAGS-ftrylockfile.c = $(libio-mtsafe)
+CFLAGS-funlockfile.c = $(libio-mtsafe)
+
+link-libc-static := $(common-objpfx)libc.a $(static-gnulib) \
+ $(common-objpfx)libc.a
+
+tests-static += tst-locale1 tst-locale2 tst-stackguard1-static \
+ tst-cancel21-static tst-cancel24-static tst-cond8-static \
+ tst-mutex8-static tst-sem11-static \
+ tst-sem12-static
+# This test does not even compile due to missing pthread_* functions
+# tst-mutexpi8-static
+tests += tst-stackguard1-static tst-cancel21-static tst-cancel24-static \
+ tst-cond8-static tst-mutex8-static \
+ tst-sem11-static tst-sem12-static
+# This test does not even compile due to missing pthread_* functions
+# tst-mutexpi8-static
+
+xtests-static += tst-setuid1-static
+
+# These tests are linked with libc before libpthread
+tests-reverse += tst-cancel5 tst-cancel23 tst-vfork1x tst-vfork2x
+
+include ../Rules
+
+ifeq (yes,$(build-shared))
+# Make sure these things are built in the `make lib' pass so they can be used
+# to run programs during the `make others' pass.
+lib-noranlib: $(addprefix $(objpfx),$(extra-objs))
+
+# What we install as libpthread.so for programs to link against is in fact a
+# link script. It contains references for the various libraries we need.
+# The libpthread.so object is not complete since some functions are only
+# defined in libpthread_nonshared.a.
+# We need to use absolute paths since otherwise local copies (if they exist)
+# of the files are taken by the linker.
+install: $(inst_libdir)/libpthread.so
+
+$(inst_libdir)/libpthread.so: $(common-objpfx)format.lds \
+ $(objpfx)libpthread.so$(libpthread.so-version) \
+ $(inst_libdir)/$(patsubst %,$(libtype.oS),\
+ $(libprefix)pthread) \
+ $(+force)
+ (echo '/* GNU ld script';\
+ echo ' Use the shared library, but some functions are only in';\
+ echo ' the static library, so try that secondarily. */';\
+ cat $<; \
+ echo 'GROUP ( $(slibdir)/libpthread.so$(libpthread.so-version)' \
+ '$(libdir)/$(patsubst %,$(libtype.oS),$(libprefix)pthread)'\
+ ')' \
+ ) > $@.new
+ mv -f $@.new $@
+endif
+
+
+# 'pthread_self' is a simple memory or register load. Setting up the
+# stack frame is more work than the actual operation. Disable the
+# frame creation entirely. This will help applications which call the
+# function frequently to get a thread-specific handle.
+CFLAGS-pthread_self.os += -fomit-frame-pointer
+
+# Run the cancellation and cleanup tests also for the modern, exception-based
+# implementation. For this we have to pass the -fexceptions parameter.
+CFLAGS-tst-cancelx2.c += -fexceptions
+CFLAGS-tst-cancelx3.c += -fexceptions
+CFLAGS-tst-cancelx4.c += -fexceptions
+CFLAGS-tst-cancelx5.c += -fexceptions
+CFLAGS-tst-cancelx6.c += -fexceptions
+CFLAGS-tst-cancelx7.c += -fexceptions
+CFLAGS-tst-cancelx8.c += -fexceptions
+CFLAGS-tst-cancelx9.c += -fexceptions
+CFLAGS-tst-cancelx10.c += -fexceptions
+CFLAGS-tst-cancelx11.c += -fexceptions
+CFLAGS-tst-cancelx12.c += -fexceptions
+CFLAGS-tst-cancelx13.c += -fexceptions
+CFLAGS-tst-cancelx14.c += -fexceptions
+CFLAGS-tst-cancelx15.c += -fexceptions
+CFLAGS-tst-cancelx16.c += -fexceptions
+CFLAGS-tst-cancelx17.c += -fexceptions
+CFLAGS-tst-cancelx18.c += -fexceptions
+CFLAGS-tst-cancelx20.c += -fexceptions -fasynchronous-unwind-tables
+CFLAGS-tst-cancelx21.c += -fexceptions -fasynchronous-unwind-tables
+CFLAGS-tst-cleanupx0.c += -fexceptions -fasynchronous-unwind-tables
+CFLAGS-tst-cleanupx1.c += -fexceptions -fasynchronous-unwind-tables
+CFLAGS-tst-cleanupx2.c += -fexceptions
+CFLAGS-tst-cleanupx3.c += -fexceptions
+CFLAGS-tst-cleanupx4.c += -fexceptions
+CFLAGS-tst-oncex3.c += -fexceptions
+CFLAGS-tst-oncex4.c += -fexceptions
+
+ldflags-libgcc_s = -Wl,--as-needed -lgcc_s -Wl,--no-as-needed
+LDFLAGS-tst-cancelx2 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cancelx3 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cancelx4 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cancelx5 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cancelx6 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cancelx7 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cancelx8 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cancelx9 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cancelx10 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cancelx11 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cancelx12 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cancelx13 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cancelx14 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cancelx15 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cancelx16 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cancelx17 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cancelx18 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cancelx20 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cancelx21 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cleanupx0 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cleanupx1 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cleanupx2 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cleanupx3 += $(ldflags-libgcc_s)
+LDFLAGS-tst-cleanupx4 += $(ldflags-libgcc_s)
+LDFLAGS-tst-oncex3 += $(ldflags-libgcc_s)
+LDFLAGS-tst-oncex4 += $(ldflags-libgcc_s)
+
+CFLAGS-tst-align.c += $(stack-align-test-flags)
+CFLAGS-tst-align3.c += $(stack-align-test-flags)
+CFLAGS-tst-initializers1.c = -W -Wall -Werror
+CFLAGS-tst-initializers1-< = $(CFLAGS-tst-initializers1.c) \
+ $(patsubst tst-initializers1-%.c,-std=%,$<)
+CFLAGS-tst-initializers1-c89.c = $(CFLAGS-tst-initializers1-<)
+CFLAGS-tst-initializers1-c99.c = $(CFLAGS-tst-initializers1-<)
+CFLAGS-tst-initializers1-gnu89.c = $(CFLAGS-tst-initializers1-<)
+CFLAGS-tst-initializers1-gnu99.c = $(CFLAGS-tst-initializers1-<)
+
+tst-cancel7-ARGS = --command "exec $(host-test-program-cmd)"
+tst-cancelx7-ARGS = $(tst-cancel7-ARGS)
+tst-umask1-ARGS = $(objpfx)tst-umask1.temp
+
+$(objpfx)tst-atfork2: $(libdl) $(shared-thread-library)
+LDFLAGS-tst-atfork2 = -rdynamic
+tst-atfork2-ENV = MALLOC_TRACE=$(objpfx)tst-atfork2.mtrace
+$(objpfx)tst-atfork2mod.so: $(shared-thread-library)
+
+ifeq ($(run-built-tests),yes)
+tests: $(objpfx)tst-stack3-mem
+endif
+tst-stack3-ENV = MALLOC_TRACE=$(objpfx)tst-stack3.mtrace
+$(objpfx)tst-stack3-mem: $(objpfx)tst-stack3.out
+ $(common-objpfx)malloc/mtrace $(objpfx)tst-stack3.mtrace > $@
+generated += tst-stack3-mem tst-stack3.mtrace
+
+$(objpfx)tst-cleanup4: $(objpfx)tst-cleanup4aux.o $(shared-thread-library)
+$(objpfx)tst-cleanupx4: $(objpfx)tst-cleanup4aux.o $(shared-thread-library)
+
+$(objpfx)tst-tls3: $(libdl) $(shared-thread-library)
+LDFLAGS-tst-tls3 = -rdynamic
+$(objpfx)tst-tls3.out: $(objpfx)tst-tls3mod.so
+$(objpfx)tst-tls3mod.so: $(shared-thread-library)
+
+$(objpfx)tst-tls4: $(libdl) $(shared-thread-library)
+$(objpfx)tst-tls4.out: $(objpfx)tst-tls4moda.so $(objpfx)tst-tls4modb.so
+
+$(objpfx)tst-tls5: $(objpfx)tst-tls5mod.so $(shared-thread-library)
+LDFLAGS-tst-tls5 = $(no-as-needed)
+LDFLAGS-tst-tls5mod.so = -Wl,-soname,tst-tls5mod.so
+
+ifeq ($(build-shared),yes)
+ifeq ($(run-built-tests),yes)
+tests: $(objpfx)tst-tls6.out
+endif
+$(objpfx)tst-tls6.out: tst-tls6.sh $(objpfx)tst-tls5 \
+ $(objpfx)tst-tls5moda.so $(objpfx)tst-tls5modb.so \
+ $(objpfx)tst-tls5modc.so $(objpfx)tst-tls5modd.so \
+ $(objpfx)tst-tls5mode.so $(objpfx)tst-tls5modf.so
+ $(BASH) $< $(common-objpfx) '$(test-via-rtld-prefix)' \
+ '$(test-wrapper-env)'
+endif
+
+$(objpfx)tst-dlsym1: $(libdl) $(shared-thread-library)
+
+$(objpfx)tst-fini1: $(shared-thread-library) $(objpfx)tst-fini1mod.so
+
+ifeq (yes,$(build-shared))
+librt = $(common-objpfx)rt/librt.so
+else
+librt = $(common-objpfx)rt/librt.a
+endif
+
+$(objpfx)tst-cancel17: $(librt)
+$(objpfx)tst-cancelx17: $(librt)
+$(objpfx)tst-_res1mod2.so: $(objpfx)tst-_res1mod1.so
+LDFLAGS-tst-_res1mod1.so = -Wl,-soname,tst-_res1mod1.so
+LDFLAGS-tst-_res1mod2.so = -Wl,-soname,tst-_res1mod2.so
+$(objpfx)tst-_res1: $(objpfx)tst-_res1mod1.so $(objpfx)tst-_res1mod2.so \
+ $(shared-thread-library)
+
+LDLIBS-tst-cancel24 = $(no-as-needed) -lstdc++
+LDLIBS-tst-cancel24-static = $(LDLIBS-tst-cancel24)
+
+extra-B-pthread.so = -B$(common-objpfx)fbtl/
+$(objpfx)libpthread.so: $(addprefix $(objpfx),$(crti-objs) $(crtn-objs))
+$(objpfx)libpthread.so: +preinit += $(addprefix $(objpfx),$(crti-objs))
+$(objpfx)libpthread.so: +postinit += $(addprefix $(objpfx),$(crtn-objs))
+
+# Make sure we link with the thread library.
+ifeq ($(build-shared),yes)
+$(addprefix $(objpfx), \
+ $(filter-out $(tests-static) $(xtests-static) $(tests-reverse) \
+ $(tests-nolibpthread), \
+ $(tests) $(xtests) $(test-srcs))): $(objpfx)libpthread.so \
+ $(objpfx)libpthread_nonshared.a
+$(objpfx)tst-unload: $(common-objpfx)dlfcn/libdl.so
+# $(objpfx)../libc.so is used instead of $(common-objpfx)libc.so,
+# since otherwise libpthread.so comes before libc.so when linking.
+$(addprefix $(objpfx), $(tests-reverse)): \
+ $(objpfx)../libc.so $(objpfx)libpthread.so \
+ $(objpfx)libpthread_nonshared.a
+$(objpfx)../libc.so: $(common-objpfx)libc.so ;
+$(addprefix $(objpfx),$(tests-static) $(xtests-static)): $(objpfx)libpthread.a
+
+$(objpfx)tst-atfork2.out: $(objpfx)tst-atfork2mod.so
+else
+$(addprefix $(objpfx),$(tests) $(test-srcs)): $(objpfx)libpthread.a
+endif
+
+ifeq ($(build-shared),yes)
+
+$(objpfx)tst-cleanup0.out: /dev/null $(objpfx)tst-cleanup0
+ $(make-test-out) 2>&1 | cmp - tst-cleanup0.expect > $@
+
+$(objpfx)crti.o: $(objpfx)pt-crti.o
+ ln -f $< $@
+
+ifneq ($(multidir),.)
+$(objpfx)$(multidir)/crti.o: $(objpfx)crti.o $(objpfx)$(multidir)/
+ ln -f $< $@
+
+$(objpfx)$(multidir)/crtn.o: $(objpfx)crtn.o $(objpfx)$(multidir)/
+ ln -f $< $@
+endif
+
+generated += libpthread_nonshared.a \
+ multidir.mk tst-atfork2.mtrace tst-cancel-wrappers.out \
+ tst-tls6.out
+
+generated += $(objpfx)tst-atfork2.mtrace \
+ $(addsuffix .so,$(strip $(modules-names)))
+
+$(objpfx)version.d: $(objpfx)banner.h
+$(objpfx)version.os: $(objpfx)banner.h
+$(objpfx)banner.h: Banner
+ sed 's/\(.*\)/"\1\\n"/' $< > $@
+generated += banner.h
+# Give libpthread.so an entry point and make it directly runnable itself.
+LDFLAGS-pthread.so += -e __nptl_main
+endif
+
+ifeq ($(run-built-tests),yes)
+ifeq (yes,$(build-shared))
+tests: $(objpfx)tst-cancel-wrappers.out
+$(objpfx)tst-cancel-wrappers.out: tst-cancel-wrappers.sh
+ $(SHELL) $< '$(NM)' \
+ $(common-objpfx)libc_pic.a \
+ $(common-objpfx)libc.a \
+ $(objpfx)libpthread_pic.a \
+ $(objpfx)libpthread.a > $@
+endif
+endif
+
+tst-exec4-ARGS = $(host-test-program-cmd)
+
+$(objpfx)tst-execstack: $(libdl)
+$(objpfx)tst-execstack.out: $(objpfx)tst-execstack-mod.so
+LDFLAGS-tst-execstack = -Wl,-z,noexecstack
+
+$(objpfx)tst-fini1mod.so: $(shared-thread-library)
+
+tst-stackguard1-ARGS = --command "$(host-test-program-cmd) --child"
+tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child"
+
+ifeq ($(run-built-tests),yes)
+tests: $(objpfx)tst-oddstacklimit.out
+
+$(objpfx)tst-oddstacklimit.out: $(objpfx)tst-oddstacklimit $(objpfx)tst-basic1
+ $(test-program-prefix) $< --command '$(host-test-program-cmd)' > $@
+endif
+
+# The tests here better do not run in parallel
+ifneq ($(filter %tests,$(MAKECMDGOALS)),)
+.NOTPARALLEL:
+endif
--- /dev/null
+++ b/fbtl/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
--- /dev/null
+++ b/fbtl/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.
--- /dev/null
+++ b/fbtl/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?
--- /dev/null
+++ b/fbtl/Versions
@@ -0,0 +1,251 @@
+libc {
+ GLIBC_2.0 {
+ pthread_attr_destroy; pthread_attr_init;
+ pthread_attr_getdetachstate; pthread_attr_setdetachstate;
+ pthread_attr_getinheritsched; pthread_attr_setinheritsched;
+ pthread_attr_getschedparam; pthread_attr_setschedparam;
+ pthread_attr_getschedpolicy; pthread_attr_setschedpolicy;
+ pthread_attr_getscope; pthread_attr_setscope;
+ pthread_condattr_destroy; pthread_condattr_init;
+ pthread_cond_broadcast; pthread_cond_destroy;
+ pthread_cond_init; pthread_cond_signal; pthread_cond_wait;
+ pthread_cond_timedwait;
+ pthread_equal; pthread_exit;
+ pthread_getschedparam; pthread_setschedparam;
+ pthread_mutex_destroy; pthread_mutex_init;
+ pthread_mutex_lock; pthread_mutex_unlock;
+ pthread_self;
+ pthread_setcancelstate; pthread_setcanceltype;
+ }
+ GLIBC_2.1 {
+ pthread_attr_init;
+ }
+ GLIBC_2.3.2 {
+ # Changed pthread_cond_t.
+ pthread_cond_init; pthread_cond_destroy;
+ pthread_cond_wait; pthread_cond_signal;
+ pthread_cond_broadcast; pthread_cond_timedwait;
+ }
+ GLIBC_PRIVATE {
+ __libc_alloca_cutoff;
+ # Internal libc interface to libpthread
+ __libc_dl_error_tsd;
+ }
+}
+
+libpthread {
+ GLIBC_2.0 {
+ pthread_create; pthread_join; pthread_self; pthread_equal;
+ pthread_exit; pthread_detach;
+
+ pthread_getschedparam; pthread_setschedparam;
+
+ pthread_attr_init; pthread_attr_destroy;
+ pthread_attr_getdetachstate; pthread_attr_setdetachstate;
+ 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_mutex_init; pthread_mutex_destroy;
+ pthread_mutex_lock; pthread_mutex_trylock; pthread_mutex_unlock;
+
+ pthread_mutexattr_init; pthread_mutexattr_destroy;
+
+ pthread_cond_init; pthread_cond_destroy;
+ pthread_cond_wait; pthread_cond_timedwait;
+ pthread_cond_signal; pthread_cond_broadcast;
+
+ pthread_condattr_destroy; pthread_condattr_init;
+
+ pthread_cancel; pthread_testcancel;
+ pthread_setcancelstate; pthread_setcanceltype;
+
+ pthread_sigmask; pthread_kill;
+
+ pthread_key_create; pthread_key_delete;
+ pthread_getspecific; pthread_setspecific;
+
+ pthread_once;
+
+ pthread_atfork;
+
+ flockfile; funlockfile; ftrylockfile;
+
+ # Non-standard POSIX1.x functions.
+ pthread_mutexattr_getkind_np; pthread_mutexattr_setkind_np;
+
+ # Protected names for functions used in other shared objects.
+ __pthread_mutex_init; __pthread_mutex_destroy;
+ __pthread_mutex_lock; __pthread_mutex_trylock; __pthread_mutex_unlock;
+ __pthread_mutexattr_init; __pthread_mutexattr_destroy;
+ __pthread_mutexattr_settype;
+ __pthread_key_create; __pthread_getspecific; __pthread_setspecific;
+ __pthread_once; __pthread_atfork;
+ _IO_flockfile; _IO_ftrylockfile; _IO_funlockfile;
+
+ # Hidden entry point (through macros).
+ #_pthread_cleanup_pop; _pthread_cleanup_pop_restore; _pthread_cleanup_push;
+ #_pthread_cleanup_push_defer;
+
+ # Semaphores.
+ sem_destroy; sem_getvalue; sem_init; sem_post; sem_trywait; sem_wait;
+
+ # Special fork handling.
+ fork; __fork; vfork;
+
+ # Cancellation points.
+ close; __close; fcntl; __fcntl; read; __read; write; __write; accept;
+ connect; __connect; recv; recvfrom; recvmsg; send; __send; sendmsg; sendto;
+ fsync; lseek; __lseek; msync; nanosleep; open; __open; pause; tcdrain;
+ system; wait; __wait; waitpid;
+
+ # Hidden entry point (through macros).
+ _pthread_cleanup_push; _pthread_cleanup_pop;
+ _pthread_cleanup_push_defer; _pthread_cleanup_pop_restore;
+
+ pthread_kill_other_threads_np;
+
+ # The error functions.
+ __errno_location; __h_errno_location;
+
+ # Functions which previously have been overwritten.
+ sigwait; sigaction; __sigaction; _exit; _Exit; longjmp; siglongjmp;
+ raise;
+ }
+
+ GLIBC_2.1 {
+ pthread_create;
+ pthread_attr_init;
+
+ pthread_attr_getguardsize; pthread_attr_setguardsize;
+ pthread_attr_getstackaddr; pthread_attr_setstackaddr;
+ pthread_attr_getstacksize; pthread_attr_setstacksize;
+
+ pthread_mutexattr_gettype; pthread_mutexattr_settype;
+
+ pthread_rwlock_init; pthread_rwlock_destroy;
+ pthread_rwlock_rdlock; pthread_rwlock_wrlock; pthread_rwlock_unlock;
+ pthread_rwlock_tryrdlock; pthread_rwlock_trywrlock;
+
+ pthread_rwlockattr_init; pthread_rwlockattr_destroy;
+ pthread_rwlockattr_getpshared; pthread_rwlockattr_setpshared;
+ pthread_rwlockattr_getkind_np; pthread_rwlockattr_setkind_np;
+
+ pthread_getconcurrency; pthread_setconcurrency;
+
+ # Semaphores.
+ sem_destroy; sem_getvalue; sem_init; sem_post; sem_trywait; sem_wait;
+
+ __libc_current_sigrtmin; __libc_current_sigrtmax;
+ __libc_allocate_rtsig;
+ }
+
+ GLIBC_2.1.1 {
+ sem_close; sem_open; sem_unlink;
+ }
+
+ GLIBC_2.1.2 {
+ __vfork;
+ }
+
+ GLIBC_2.2 {
+ pthread_mutexattr_getpshared; pthread_mutexattr_setpshared;
+
+ pthread_condattr_getpshared; pthread_condattr_setpshared;
+
+ # New functions from IEEE Std. 1003.1-2001.
+ pthread_mutex_timedlock;
+
+ pthread_rwlock_timedrdlock; pthread_rwlock_timedwrlock;
+
+ pthread_attr_getstack; pthread_attr_setstack;
+
+ pthread_spin_destroy; pthread_spin_init; pthread_spin_lock;
+ pthread_spin_trylock; pthread_spin_unlock;
+
+ pthread_barrier_init; pthread_barrier_destroy; pthread_barrier_wait;
+ pthread_barrierattr_destroy; pthread_barrierattr_init;
+ pthread_barrierattr_setpshared;
+
+ sem_timedwait;
+
+ pthread_yield;
+
+ pthread_getcpuclockid;
+
+ # Cancellation points.
+ lseek64; open64; __open64; pread; pread64; __pread64; pwrite; pwrite64;
+ __pwrite64;
+
+ # Names used internally.
+ __pthread_rwlock_init; __pthread_rwlock_destroy;
+ __pthread_rwlock_rdlock; __pthread_rwlock_tryrdlock;
+ __pthread_rwlock_wrlock; __pthread_rwlock_trywrlock;
+ __pthread_rwlock_unlock;
+
+ __res_state;
+ }
+
+ GLIBC_2.2.3 {
+ # Extensions.
+ pthread_getattr_np;
+ }
+
+ GLIBC_2.2.6 {
+ # Cancellation wrapper
+ __nanosleep;
+ }
+
+ GLIBC_2.3.2 {
+ # Changed pthread_cond_t.
+ pthread_cond_init; pthread_cond_destroy;
+ pthread_cond_wait; pthread_cond_timedwait;
+ pthread_cond_signal; pthread_cond_broadcast;
+ }
+
+ GLIBC_2.3.3 {
+ # 1003.1-2001 function accidentally left out in 2.2.
+ pthread_barrierattr_getpshared;
+
+ # Unix CS option.
+ pthread_condattr_getclock; pthread_condattr_setclock;
+
+ # Proposed API extensions.
+ pthread_tryjoin_np; pthread_timedjoin_np;
+
+ # New cancellation cleanup handling.
+ __pthread_register_cancel; __pthread_unregister_cancel;
+ __pthread_register_cancel_defer; __pthread_unregister_cancel_restore;
+ __pthread_unwind_next;
+ __pthread_cleanup_routine;
+
+ # affinity interfaces without size parameter
+ # have not been in linuxthreads and
+ # will be overriden by version from GLIBC_2.3.4
+ pthread_getaffinity_np; pthread_setaffinity_np;
+ pthread_attr_getaffinity_np; pthread_attr_setaffinity_np;
+ }
+
+ GLIBC_2.3.4 {
+ # New affinity interfaces.
+ pthread_getaffinity_np; pthread_setaffinity_np;
+ pthread_attr_getaffinity_np; pthread_attr_setaffinity_np;
+ }
+
+ GLIBC_2.12 {
+ pthread_setname_np; pthread_getname_np;
+ };
+
+ GLIBC_2.18 {
+ pthread_getattr_default_np;
+ pthread_setattr_default_np;
+ }
+
+ GLIBC_PRIVATE {
+ __pthread_initialize_minimal;
+ __pthread_clock_gettime; __pthread_clock_settime;
+ __pthread_unwind; __pthread_get_minstack;
+ __shm_directory;
+ }
+}
--- /dev/null
+++ b/fbtl/alloca_cutoff.c
@@ -0,0 +1,36 @@
+/* Determine whether block of given size can be allocated on the stack or not.
+ Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#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));
+}
+libc_hidden_def (__libc_alloca_cutoff)
--- /dev/null
+++ b/fbtl/allocatestack.c
@@ -0,0 +1,1258 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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 <dl-sysdep.h>
+#include <dl-tls.h>
+#include <tls.h>
+#include <list.h>
+#include <lowlevellock.h>
+#include <kernel-features.h>
+#include <stack-aliasing.h>
+
+
+#if !(defined(NEED_SEPARATE_REGISTER_STACK) || defined(NEED_STACK_SIZE_FOR_PTH_CREATE))
+
+/* 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
+
+/*
+ Unfortunately, under FreeBSD mmap fails with addr=NULL, flags=MAP_STACK
+
+ See http://www.freebsd.org/cgi/query-pr.cgi?pr=158755
+
+ do not use MAP_STACK at all
+*/
+
+#undef MAP_STACK
+
+
+/* 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 TLS_TCB_AT_TP
+# define TLS_TPADJ(pd) (pd)
+#elif 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 <= KTID_TERMINATED)
+
+
+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;
+ }
+
+ /* Don't allow setxid until cloned. */
+ result->setxid_futex = -1;
+
+ /* 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));
+ for (size_t cnt = 0; cnt < dtv[-1].counter; ++cnt)
+ free (dtv[1 + cnt].pointer.to_free);
+ 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 (__glibc_unlikely (stack_cache_actsize > stack_cache_maxsize))
+ __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;
+}
+
+
+/* Returns a usable stack for a new thread either by allocating a
+ new stack or reusing a cached stack of sufficient size.
+ ATTR must be non-NULL and point to a valid pthread_attr.
+ PDP must be non-NULL. */
+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 (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. */
+ if (attr->stacksize != 0)
+ size = attr->stacksize;
+ else
+ {
+ lll_lock (__default_pthread_attr_lock, LLL_PRIVATE);
+ size = __default_pthread_attr.stacksize;
+ lll_unlock (__default_pthread_attr_lock, LLL_PRIVATE);
+ }
+
+ /* Get memory for the stack. */
+ if (__glibc_unlikely (attr->flags & ATTR_FLAG_STACKADDR))
+ {
+ 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 TLS_TCB_AT_TP
+ adj = ((uintptr_t) attr->stackaddr - TLS_TCB_SIZE)
+ & __static_tls_align_m1;
+ assert (size > adj + TLS_TCB_SIZE);
+#elif 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 TLS_TCB_AT_TP
+ pd = (struct pthread *) ((uintptr_t) attr->stackaddr
+ - TLS_TCB_SIZE - adj);
+#elif 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
+
+ /* Don't allow setxid until cloned. */
+ pd->setxid_futex = -1;
+
+ /* Allocate the DTV for this thread. */
+ if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL)
+ {
+ /* Something went wrong. */
+ assert (errno == ENOMEM);
+ return errno;
+ }
+
+
+ /* 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;
+ const int prot = (PROT_READ | PROT_WRITE
+ | ((GL(dl_stack_flags) & PF_X) ? PROT_EXEC : 0));
+
+#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 (__glibc_unlikely (mem == MAP_FAILED))
+ 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 (__glibc_unlikely ((coloring & __static_tls_align_m1) != 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 TLS_TCB_AT_TP
+ pd = (struct pthread *) ((char *) mem + size - coloring) - 1;
+#elif 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
+
+ /* Don't allow setxid until cloned. */
+ pd->setxid_futex = -1;
+
+ /* 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 errno;
+ }
+
+
+ /* 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);
+
+
+ /* There might have been a race. Another thread might have
+ caused the stacks to get exec permission while this new
+ stack was prepared. Detect if this was possible and
+ change the permission if necessary. */
+ if (__builtin_expect ((GL(dl_stack_flags) & PF_X) != 0
+ && (prot & PROT_EXEC) == 0, 0))
+ {
+ int err = change_stack_perm (pd
+#ifdef NEED_SEPARATE_REGISTER_STACK
+ , ~pagesize_m1
+#endif
+ );
+ if (err != 0)
+ {
+ /* Free the stack memory we just allocated. */
+ (void) munmap (mem, size);
+
+ return err;
+ }
+ }
+
+
+ /* 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 (__glibc_unlikely (guardsize > pd->guardsize))
+ {
+#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)
+ {
+ mprot_error:
+ 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 errno;
+ }
+
+ 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 TLS_TCB_AT_TP
+ /* The stack begins before the TCB and the static TLS block. */
+ stacktop = ((char *) (pd + 1) - __static_tls_size);
+#elif TLS_DTV_AT_TP
+ stacktop = (char *) (pd - 1);
+#endif
+
+#if defined(NEED_SEPARATE_REGISTER_STACK) || defined(NEED_STACK_SIZE_FOR_PTH_CREATE)
+ *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 (__glibc_likely (! pd->user_stack))
+ (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 = _dl_make_stack_executable (stack_endp);
+ 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 & ~(uintptr_t) 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;
+
+ /* 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;
+ }
+ }
+ }
+ }
+
+ /* 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 (__glibc_unlikely (THREAD_GETMEM (self, user_stack)))
+ 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 locks. */
+ stack_cache_lock = LLL_LOCK_INITIALIZER;
+ __default_pthread_attr_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;
+
+ /* Wait until this thread is cloned. */
+ if (t->setxid_futex == -1
+ && ! atomic_compare_and_exchange_bool_acq (&t->setxid_futex, -2, -1))
+ do
+ lll_futex_wait (&t->setxid_futex, -2, LLL_PRIVATE);
+ while (t->setxid_futex == -2);
+
+ /* 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)
+ {
+ /* Release the futex if there is no other setxid in
+ progress. */
+ if ((ch & SETXID_BITMASK) == 0)
+ {
+ t->setxid_futex = 1;
+ lll_futex_wake (&t->setxid_futex, 1, LLL_PRIVATE);
+ }
+ 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;
+
+#warning setxid fixup needed
+#if 0
+ int val;
+ pid_t pid = __getpid ();
+ INTERNAL_SYSCALL_DECL (err);
+ val = INTERNAL_SYSCALL (tgkill, err, pid, t->tid, SIGSETXID);
+
+ /* 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
+#endif
+ return 0;
+}
+
+
+int
+attribute_hidden
+__nptl_setxid (struct xid_command *cmdp)
+{
+#warning setxid fixup needed
+#if 0
+ 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;
+#endif
+}
+
+static inline void __attribute__((always_inline))
+init_one_static_tls (struct pthread *curp, struct link_map *map)
+{
+# if TLS_TCB_AT_TP
+ void *dest = (char *) curp - map->l_tls_offset;
+# elif 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
+
+ /* We cannot delay the initialization of the Static TLS area, since
+ it can be accessed with LE or IE, but since the DTV is only used
+ by GD and LD, we can delay its update to avoid a race. */
+ 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);
+}
--- /dev/null
+++ b/fbtl/cancellation.c
@@ -0,0 +1,99 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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 (__glibc_likely (curval == oldval))
+ {
+ 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 (__glibc_likely (curval == oldval))
+ 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);
+ }
+}
--- /dev/null
+++ b/fbtl/cleanup.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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)
--- /dev/null
+++ b/fbtl/cleanup_compat.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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)
--- /dev/null
+++ b/fbtl/cleanup_defer.c
@@ -0,0 +1,91 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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 (__glibc_unlikely (cancelhandling & CANCELTYPE_BITMASK))
+ while (1)
+ {
+ int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
+ cancelhandling
+ & ~CANCELTYPE_BITMASK,
+ cancelhandling);
+ if (__glibc_likely (curval == cancelhandling))
+ /* 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 (__glibc_likely (curval == cancelhandling))
+ /* Successfully replaced the value. */
+ break;
+
+ /* Prepare for the next round. */
+ cancelhandling = curval;
+ }
+
+ CANCELLATION_P (self);
+ }
+}
--- /dev/null
+++ b/fbtl/cleanup_defer_compat.c
@@ -0,0 +1,94 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP.h"
+
+
+void
+_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 (__glibc_unlikely (cancelhandling & CANCELTYPE_BITMASK))
+ while (1)
+ {
+ int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling,
+ cancelhandling
+ & ~CANCELTYPE_BITMASK,
+ cancelhandling);
+ if (__glibc_likely (curval == cancelhandling))
+ /* 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
+_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 (__glibc_likely (curval == cancelhandling))
+ /* 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)
--- /dev/null
+++ b/fbtl/cleanup_routine.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+
+
+void
+__pthread_cleanup_routine (struct __pthread_cleanup_frame *f)
+{
+ if (f->__do_it)
+ f->__cancel_routine (f->__cancel_arg);
+}
--- /dev/null
+++ b/fbtl/cond-perf.c
@@ -0,0 +1,103 @@
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <atomic.h>
+
+static pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut1 = PTHREAD_MUTEX_INITIALIZER;
+
+static pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut2 = PTHREAD_MUTEX_INITIALIZER;
+
+static bool last_round;
+static int ntogo;
+static bool alldone;
+
+
+static void *
+cons (void *arg)
+{
+ pthread_mutex_lock (&mut1);
+
+ do
+ {
+ if (atomic_decrement_and_test (&ntogo))
+ {
+ pthread_mutex_lock (&mut2);
+ alldone = true;
+ pthread_cond_signal (&cond2);
+ pthread_mutex_unlock (&mut2);
+ }
+
+ pthread_cond_wait (&cond1, &mut1);
+ }
+ while (! last_round);
+
+ pthread_mutex_unlock (&mut1);
+
+ return NULL;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ int opt;
+ int err;
+ int nthreads = 10;
+ int nrounds = 100;
+ bool keeplock = false;
+
+ while ((opt = getopt (argc, argv, "n:r:k")) != -1)
+ switch (opt)
+ {
+ case 'n':
+ nthreads = atol (optarg);
+ break;
+ case 'r':
+ nrounds = atol (optarg);
+ break;
+ case 'k':
+ keeplock = true;
+ break;
+ }
+
+ ntogo = nthreads;
+
+ pthread_t th[nthreads];
+ int i;
+ for (i = 0; __builtin_expect (i < nthreads, 1); ++i)
+ if (__glibc_unlikely ((err = pthread_create (&th[i], NULL, cons, (void *) (long) i)) != 0))
+ printf ("pthread_create: %s\n", strerror (err));
+
+ for (i = 0; __builtin_expect (i < nrounds, 1); ++i)
+ {
+ pthread_mutex_lock (&mut2);
+ while (! alldone)
+ pthread_cond_wait (&cond2, &mut2);
+ pthread_mutex_unlock (&mut2);
+
+ pthread_mutex_lock (&mut1);
+ if (! keeplock)
+ pthread_mutex_unlock (&mut1);
+
+ ntogo = nthreads;
+ alldone = false;
+ if (i + 1 >= nrounds)
+ last_round = true;
+
+ pthread_cond_broadcast (&cond1);
+
+ if (keeplock)
+ pthread_mutex_unlock (&mut1);
+ }
+
+ for (i = 0; i < nthreads; ++i)
+ if ((err = pthread_join (th[i], NULL)) != 0)
+ printf ("pthread_create: %s\n", strerror (err));
+
+ return 0;
+}
--- /dev/null
+++ b/fbtl/configure
@@ -0,0 +1,13 @@
+# This is a shell script fragment sourced by the main configure script.
+# We're obliged to give here the canonical name that will be used to
+# as a subdirectory to search for in other add-ons' sysdeps trees.
+
+libc_add_on_canonical=fbtl
+
+# Only linux configurations support NPTL.
+if test $add_ons_automatic = yes; then
+ case "$config_os" in
+# *linux*) ;;
+ *) libc_add_on= ;;
+ esac
+fi
--- /dev/null
+++ b/fbtl/descr.h
@@ -0,0 +1,406 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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>
+#define __need_list_t
+#include <list.h>
+#include <lowlevellock.h>
+#include <pthreaddef.h>
+#include <dl-sysdep.h>
+#include "../fbtl_db/thread_db.h"
+#include <tls.h>
+#include <unwind.h>
+#define __need_res_state
+#include <resolv.h>
+#include <kernel-features.h>
+#include <fpu_control.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 !TLS_DTV_AT_TP
+ /* This overlaps the TCB as used for TLS without threads (see tls.h). */
+ tcbhead_t header;
+#else
+ struct
+ {
+ /* multiple_threads is enabled either when the process has spawned at
+ least one thread or when a single-threaded process cancels itself.
+ This enables additional code to introduce locking before doing some
+ compare_and_exchange operations and also enable cancellation points.
+ The concepts of multiple threads and cancellation points ideally
+ should be separate, since it is not necessary for multiple threads to
+ have been created for cancellation points to be enabled, as is the
+ case is when single-threaded process cancels itself.
+
+ Since enabling multiple_threads enables additional code in
+ cancellation points and compare_and_exchange operations, there is a
+ potential for an unneeded performance hit when it is enabled in a
+ single-threaded, self-canceling process. This is OK though, since a
+ single-threaded process will enable async cancellation only when it
+ looks to cancel itself and is hence going to end anyway. */
+ 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. */
+#if (__BYTE_ORDER == __LITTLE_ENDIAN) || (__WORDSIZE == 32)
+ union {
+ pid_t tid;
+ long ktid;
+ };
+#else
+#error untested padding layout:
+ union {
+ struct {
+ int __pad_tid;
+ pid_t tid;
+ };
+ long ktid;
+ };
+#endif
+
+ /* Process ID - thread group ID in kernel speak. */
+ pid_t pid_unused;
+
+ /* 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;
+
+ /* Machine-specific unwind info. */
+ struct _Unwind_Exception exc;
+
+ /* 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;
+
+ /* FPU initial control word */
+ fpu_control_t fpu_control_init;
+
+ /* 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 */
--- /dev/null
+++ b/fbtl/eintr.c
@@ -0,0 +1,88 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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);
+ }
+}
--- /dev/null
+++ b/fbtl/errno-loc.c
@@ -0,0 +1 @@
+#include "../csu/errno-loc.c"
--- /dev/null
+++ b/fbtl/events.c
@@ -0,0 +1,33 @@
+/* Event functions used while debugging.
+ Copyright (C) 1999-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+/* 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)
--- /dev/null
+++ b/fbtl/forward.c
@@ -0,0 +1,219 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <dlfcn.h>
+#include <pthreadP.h>
+#include <signal.h>
+#include <stdlib.h>
+
+#include <shlib-compat.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); \
+}
+
+/* Same as FORWARD2, only without return. */
+#define FORWARD_NORETURN(name, rettype, decl, params, defaction) \
+rettype \
+name decl \
+{ \
+ if (!__libc_pthread_functions_init) \
+ defaction; \
+ \
+ 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)
+
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_1)
+FORWARD (__pthread_attr_init_2_0, (pthread_attr_t *attr), (attr), 0)
+compat_symbol (libc, __pthread_attr_init_2_0, pthread_attr_init, GLIBC_2_0);
+#endif
+
+FORWARD (__pthread_attr_init_2_1, (pthread_attr_t *attr), (attr), 0)
+versioned_symbol (libc, __pthread_attr_init_2_1, pthread_attr_init, GLIBC_2_1);
+
+FORWARD (pthread_attr_getdetachstate,
+ (const pthread_attr_t *attr, int *detachstate), (attr, detachstate),
+ 0)
+FORWARD (pthread_attr_setdetachstate, (pthread_attr_t *attr, int detachstate),
+ (attr, detachstate), 0)
+
+FORWARD (pthread_attr_getinheritsched,
+ (const pthread_attr_t *attr, int *inherit), (attr, inherit), 0)
+FORWARD (pthread_attr_setinheritsched, (pthread_attr_t *attr, int inherit),
+ (attr, inherit), 0)
+
+FORWARD (pthread_attr_getschedparam,
+ (const pthread_attr_t *attr, struct sched_param *param),
+ (attr, param), 0)
+FORWARD (pthread_attr_setschedparam,
+ (pthread_attr_t *attr, const struct sched_param *param),
+ (attr, param), 0)
+
+FORWARD (pthread_attr_getschedpolicy,
+ (const pthread_attr_t *attr, int *policy), (attr, policy), 0)
+FORWARD (pthread_attr_setschedpolicy, (pthread_attr_t *attr, int policy),
+ (attr, policy), 0)
+
+FORWARD (pthread_attr_getscope,
+ (const pthread_attr_t *attr, int *scope), (attr, scope), 0)
+FORWARD (pthread_attr_setscope, (pthread_attr_t *attr, int scope),
+ (attr, scope), 0)
+
+
+FORWARD (pthread_condattr_destroy, (pthread_condattr_t *attr), (attr), 0)
+FORWARD (pthread_condattr_init, (pthread_condattr_t *attr), (attr), 0)
+
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3_2)
+FORWARD2 (__pthread_cond_broadcast_2_0, int attribute_compat_text_section,
+ (pthread_cond_2_0_t *cond), (cond), return 0)
+compat_symbol (libc, __pthread_cond_broadcast_2_0, pthread_cond_broadcast,
+ GLIBC_2_0);
+#endif
+FORWARD (__pthread_cond_broadcast, (pthread_cond_t *cond), (cond), 0)
+versioned_symbol (libc, __pthread_cond_broadcast, pthread_cond_broadcast,
+ GLIBC_2_3_2);
+
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3_2)
+FORWARD2 (__pthread_cond_destroy_2_0, int attribute_compat_text_section,
+ (pthread_cond_2_0_t *cond), (cond), return 0)
+compat_symbol (libc, __pthread_cond_destroy_2_0, pthread_cond_destroy,
+ GLIBC_2_0);
+#endif
+FORWARD (__pthread_cond_destroy, (pthread_cond_t *cond), (cond), 0)
+versioned_symbol (libc, __pthread_cond_destroy, pthread_cond_destroy,
+ GLIBC_2_3_2);
+
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3_2)
+FORWARD2 (__pthread_cond_init_2_0, int attribute_compat_text_section,
+ (pthread_cond_2_0_t *cond, const pthread_condattr_t *cond_attr),
+ (cond, cond_attr), return 0)
+compat_symbol (libc, __pthread_cond_init_2_0, pthread_cond_init, GLIBC_2_0);
+#endif
+FORWARD (__pthread_cond_init,
+ (pthread_cond_t *cond, const pthread_condattr_t *cond_attr),
+ (cond, cond_attr), 0)
+versioned_symbol (libc, __pthread_cond_init, pthread_cond_init, GLIBC_2_3_2);
+
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3_2)
+FORWARD2 (__pthread_cond_signal_2_0, int attribute_compat_text_section,
+ (pthread_cond_2_0_t *cond), (cond), return 0)
+compat_symbol (libc, __pthread_cond_signal_2_0, pthread_cond_signal,
+ GLIBC_2_0);
+#endif
+FORWARD (__pthread_cond_signal, (pthread_cond_t *cond), (cond), 0)
+versioned_symbol (libc, __pthread_cond_signal, pthread_cond_signal,
+ GLIBC_2_3_2);
+
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3_2)
+FORWARD2 (__pthread_cond_wait_2_0, int attribute_compat_text_section,
+ (pthread_cond_2_0_t *cond, pthread_mutex_t *mutex), (cond, mutex),
+ return 0)
+compat_symbol (libc, __pthread_cond_wait_2_0, pthread_cond_wait,
+ GLIBC_2_0);
+#endif
+FORWARD (__pthread_cond_wait, (pthread_cond_t *cond, pthread_mutex_t *mutex),
+ (cond, mutex), 0)
+versioned_symbol (libc, __pthread_cond_wait, pthread_cond_wait,
+ GLIBC_2_3_2);
+
+#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3_2)
+FORWARD2 (__pthread_cond_timedwait_2_0, int attribute_compat_text_section,
+ (pthread_cond_2_0_t *cond, pthread_mutex_t *mutex,
+ const struct timespec *abstime), (cond, mutex, abstime),
+ return 0)
+compat_symbol (libc, __pthread_cond_timedwait_2_0, pthread_cond_timedwait,
+ GLIBC_2_0);
+#endif
+FORWARD (__pthread_cond_timedwait,
+ (pthread_cond_t *cond, pthread_mutex_t *mutex,
+ const struct timespec *abstime), (cond, mutex, abstime), 0)
+versioned_symbol (libc, __pthread_cond_timedwait, pthread_cond_timedwait,
+ GLIBC_2_3_2);
+
+
+FORWARD (pthread_equal, (pthread_t thread1, pthread_t thread2),
+ (thread1, thread2), 1)
+
+
+FORWARD_NORETURN (__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)
+strong_alias (__pthread_setcancelstate, pthread_setcancelstate)
+
+FORWARD (pthread_setcanceltype, (int type, int *oldtype), (type, oldtype), 0)
+
+FORWARD_NORETURN(__pthread_unwind,
+ void attribute_hidden __attribute ((noreturn)) __cleanup_fct_attribute
+ attribute_compat_text_section,
+ (__pthread_unwind_buf_t *buf), (buf), {
+ /* We cannot call abort() here. */
+#if 1
+#warning the kill syscall have two arguments, not one ...
+#warning elaborate what to do properly
+ asm("hlt");
+#else
+ INTERNAL_SYSCALL_DECL (err);
+ INTERNAL_SYSCALL (kill, err, 1, SIGKILL);
+#endif
+ })
--- /dev/null
+++ b/fbtl/herrno.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 1996-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl/libc-cancellation.c
@@ -0,0 +1,24 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP.h"
+
+
+#define __pthread_enable_asynccancel __libc_enable_asynccancel
+#define __pthread_disable_asynccancel __libc_disable_asynccancel
+#include <fbtl/cancellation.c>
--- /dev/null
+++ b/fbtl/libc-cleanup.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP.h"
+
+
+void
+__libc_cleanup_routine (struct __pthread_cleanup_frame *f)
+{
+ if (f->__do_it)
+ f->__cancel_routine (f->__cancel_arg);
+}
--- /dev/null
+++ b/fbtl/lowlevellock.h
@@ -0,0 +1,83 @@
+/* Low level locking macros used in NPTL implementation. Stub version.
+ Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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))
--- /dev/null
+++ b/fbtl/nptl-init.c
@@ -0,0 +1,460 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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 <list.h>
+#include <fork.h>
+#include <version.h>
+#include <shlib-compat.h>
+#include <smp.h>
+#include <lowlevellock.h>
+#include <kernel-features.h>
+#include <libc-internal.h>
+
+/* Size and alignment of static TLS block. */
+size_t __static_tls_size;
+size_t __static_tls_align_m1;
+
+#warning TODO whole file
+#if 1
+# define set_robust_list_not_avail() do { } while (0)
+#else
+#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
+#endif
+
+/* Version of the library, used in libthread_db to detect mismatches. */
+static const char nptl_version[] __attribute_used__ = VERSION;
+
+
+#ifdef SHARED
+static
+#else
+extern
+#endif
+void __nptl_set_robust (struct pthread *);
+
+#ifdef SHARED
+static void nptl_freeres (void);
+
+
+static const struct pthread_functions pthread_functions =
+ {
+ .ptr_pthread_attr_destroy = __pthread_attr_destroy,
+# if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
+ .ptr___pthread_attr_init_2_0 = __pthread_attr_init_2_0,
+# endif
+ .ptr___pthread_attr_init_2_1 = __pthread_attr_init_2_1,
+ .ptr_pthread_attr_getdetachstate = __pthread_attr_getdetachstate,
+ .ptr_pthread_attr_setdetachstate = __pthread_attr_setdetachstate,
+ .ptr_pthread_attr_getinheritsched = __pthread_attr_getinheritsched,
+ .ptr_pthread_attr_setinheritsched = __pthread_attr_setinheritsched,
+ .ptr_pthread_attr_getschedparam = __pthread_attr_getschedparam,
+ .ptr_pthread_attr_setschedparam = __pthread_attr_setschedparam,
+ .ptr_pthread_attr_getschedpolicy = __pthread_attr_getschedpolicy,
+ .ptr_pthread_attr_setschedpolicy = __pthread_attr_setschedpolicy,
+ .ptr_pthread_attr_getscope = __pthread_attr_getscope,
+ .ptr_pthread_attr_setscope = __pthread_attr_setscope,
+ .ptr_pthread_condattr_destroy = __pthread_condattr_destroy,
+ .ptr_pthread_condattr_init = __pthread_condattr_init,
+ .ptr___pthread_cond_broadcast = __pthread_cond_broadcast,
+ .ptr___pthread_cond_destroy = __pthread_cond_destroy,
+ .ptr___pthread_cond_init = __pthread_cond_init,
+ .ptr___pthread_cond_signal = __pthread_cond_signal,
+ .ptr___pthread_cond_wait = __pthread_cond_wait,
+ .ptr___pthread_cond_timedwait = __pthread_cond_timedwait,
+# if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2)
+ .ptr___pthread_cond_broadcast_2_0 = __pthread_cond_broadcast_2_0,
+ .ptr___pthread_cond_destroy_2_0 = __pthread_cond_destroy_2_0,
+ .ptr___pthread_cond_init_2_0 = __pthread_cond_init_2_0,
+ .ptr___pthread_cond_signal_2_0 = __pthread_cond_signal_2_0,
+ .ptr___pthread_cond_wait_2_0 = __pthread_cond_wait_2_0,
+ .ptr___pthread_cond_timedwait_2_0 = __pthread_cond_timedwait_2_0,
+# endif
+ .ptr_pthread_equal = __pthread_equal,
+ .ptr___pthread_exit = __pthread_exit,
+ .ptr_pthread_getschedparam = __pthread_getschedparam,
+ .ptr_pthread_setschedparam = __pthread_setschedparam,
+ .ptr_pthread_mutex_destroy = __pthread_mutex_destroy,
+ .ptr_pthread_mutex_init = __pthread_mutex_init,
+ .ptr_pthread_mutex_lock = __pthread_mutex_lock,
+ .ptr_pthread_mutex_unlock = __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,
+ .ptr___pthread_rwlock_rdlock = __pthread_rwlock_rdlock,
+ .ptr___pthread_rwlock_wrlock = __pthread_rwlock_wrlock,
+ .ptr___pthread_rwlock_unlock = __pthread_rwlock_unlock,
+ .ptr___pthread_key_create = __pthread_key_create,
+ .ptr___pthread_getspecific = __pthread_getspecific,
+ .ptr___pthread_setspecific = __pthread_setspecific,
+ .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,
+ .ptr_set_robust = __nptl_set_robust
+ };
+# 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);
+}
+
+
+static
+#endif
+void
+__nptl_set_robust (struct pthread *self)
+{
+#if 0
+ INTERNAL_SYSCALL_DECL (err);
+ INTERNAL_SYSCALL (set_robust_list, err, 2, &self->robust_head,
+ sizeof (struct robust_list_head));
+#endif
+}
+
+
+/* For asynchronous cancellation we use a signal. This is the handler. */
+static void
+sigcancel_handler (int sig, siginfo_t *si, void *ctx)
+{
+ /* 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
+ || si->si_pid != __getpid()
+#if 1
+ )
+#else
+ || si->si_code != SI_TKILL)
+#endif
+ 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;
+
+/* We use the SIGSETXID signal in the setuid, setgid, etc. implementations to
+ tell each thread to call the respective setxid syscall on itself. This is
+ the handler. */
+static void
+sighandler_setxid (int sig, siginfo_t *si, void *ctx)
+{
+#if 0
+ /* 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
+ || si->si_pid != pid
+ || 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]);
+#endif
+ /* 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 ((unsigned int *)&__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)
+{
+ /* Minimal initialization of the thread descriptor. */
+ struct pthread *pd = THREAD_SELF;
+#if 1
+ INLINE_SYSCALL(thr_self, 1, &(pd->ktid));
+#else
+ INTERNAL_SYSCALL_DECL (err);
+ pd->tid = INTERNAL_SYSCALL (set_tid_address, err, 1, &pd->tid);
+#endif
+ 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 ();
+
+#if 0
+#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
+#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);
+ INLINE_SYSCALL (sigprocmask, 3, SIG_UNBLOCK, &sa.sa_mask, NULL);
+
+ /* 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;
+ else if (limit.rlim_cur > (4 * ARCH_STACK_DEFAULT_SIZE))
+ /* The system limit is unusably high.
+ Use the maximal size acceptable. */
+ limit.rlim_cur = (4 * ARCH_STACK_DEFAULT_SIZE);
+
+ /* Make sure it meets the minimum size that allocate_stack
+ (allocatestack.c) will demand, which depends on the page size. */
+ const uintptr_t pagesz = GLRO(dl_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 = ALIGN_UP (limit.rlim_cur, pagesz);
+ lll_lock (__default_pthread_attr_lock, LLL_PRIVATE);
+ __default_pthread_attr.stacksize = limit.rlim_cur;
+ __default_pthread_attr.guardsize = GLRO (dl_pagesize);
+ lll_unlock (__default_pthread_attr_lock, LLL_PRIVATE);
+
+#ifdef SHARED
+ /* Make __rtld_lock_{,un}lock_recursive use pthread_mutex_{,un}lock,
+ keep the lock count from the ld.so implementation. */
+ GL(dl_rtld_lock_recursive) = (void *) __pthread_mutex_lock;
+ GL(dl_rtld_unlock_recursive) = (void *) __pthread_mutex_unlock;
+ unsigned int rtld_lock_count = GL(dl_load_lock).mutex.__data.__count;
+ GL(dl_load_lock).mutex.__data.__count = 0;
+ while (rtld_lock_count-- > 0)
+ __pthread_mutex_lock (&GL(dl_load_lock).mutex);
+
+ GL(dl_make_stack_executable_hook) = &__make_stacks_executable;
+#endif
+
+ GL(dl_init_static_tls) = &__pthread_init_static_tls;
+
+ GL(dl_wait_lookup_done) = &__wait_lookup_done;
+
+ /* Register the fork generation counter with the libc. */
+#ifndef TLS_MULTIPLE_THREADS_IN_TCB
+ __libc_multiple_threads_ptr =
+#endif
+ __libc_pthread_init (&__fork_generation, __reclaim_stacks,
+ ptr_pthread_functions);
+
+ /* Determine whether the machine is SMP or not. */
+ __is_smp = is_smp_system ();
+}
+strong_alias (__pthread_initialize_minimal_internal,
+ __pthread_initialize_minimal)
+
+
+size_t
+__pthread_get_minstack (const pthread_attr_t *attr)
+{
+ struct pthread_attr *iattr = (struct pthread_attr *) attr;
+
+ return (GLRO(dl_pagesize) + __static_tls_size + PTHREAD_STACK_MIN
+ + iattr->guardsize);
+}
--- /dev/null
+++ b/fbtl/old_pthread_atfork.c
@@ -0,0 +1,26 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <shlib-compat.h>
+
+#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_3_2)
+# define __pthread_atfork __dyn_pthread_atfork
+# include "pthread_atfork.c"
+# undef __pthread_atfork
+compat_symbol (libpthread, __dyn_pthread_atfork, pthread_atfork, GLIBC_2_0);
+#endif
--- /dev/null
+++ b/fbtl/old_pthread_cond_broadcast.c
@@ -0,0 +1,56 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdlib.h>
+#include "pthreadP.h"
+#include <atomic.h>
+#include <shlib-compat.h>
+
+
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2)
+int
+__pthread_cond_broadcast_2_0 (pthread_cond_2_0_t *cond)
+{
+ if (cond->cond == NULL)
+ {
+ pthread_cond_t *newcond;
+
+#if LLL_LOCK_INITIALIZER == 0
+ newcond = (pthread_cond_t *) calloc (sizeof (pthread_cond_t), 1);
+ if (newcond == NULL)
+ return ENOMEM;
+#else
+ newcond = (pthread_cond_t *) malloc (sizeof (pthread_cond_t));
+ if (newcond == NULL)
+ return ENOMEM;
+
+ /* Initialize the condvar. */
+ (void) pthread_cond_init (newcond, NULL);
+#endif
+
+ if (atomic_compare_and_exchange_bool_acq (&cond->cond, newcond, NULL))
+ /* Somebody else just initialized the condvar. */
+ free (newcond);
+ }
+
+ return __pthread_cond_broadcast (cond->cond);
+}
+compat_symbol (libpthread, __pthread_cond_broadcast_2_0,
+ pthread_cond_broadcast, GLIBC_2_0);
+#endif
--- /dev/null
+++ b/fbtl/old_pthread_cond_destroy.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include "pthreadP.h"
+#include <shlib-compat.h>
+
+
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2)
+int
+__pthread_cond_destroy_2_0 (pthread_cond_2_0_t *cond)
+{
+ /* Free the memory which was eventually allocated. */
+ free (cond->cond);
+
+ return 0;
+}
+compat_symbol (libpthread, __pthread_cond_destroy_2_0, pthread_cond_destroy,
+ GLIBC_2_0);
+#endif
--- /dev/null
+++ b/fbtl/old_pthread_cond_init.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include "pthreadP.h"
+#include <shlib-compat.h>
+
+
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2)
+int
+__pthread_cond_init_2_0 (pthread_cond_2_0_t *cond,
+ const pthread_condattr_t *cond_attr)
+{
+ struct pthread_condattr *icond_attr = (struct pthread_condattr *) cond_attr;
+
+ /* The type of the first argument is actually that of the old, too
+ small pthread_cond_t. We use only the first word of it, as a
+ pointer. */
+ cond->cond = NULL;
+
+ /* We can't support PSHARED condvars in the old pthread_cond_*
+ functions and neither clocks other than CLOCK_REALTIME. */
+ if (icond_attr != NULL && icond_attr->value)
+ return EINVAL;
+
+ return 0;
+}
+compat_symbol (libpthread, __pthread_cond_init_2_0, pthread_cond_init,
+ GLIBC_2_0);
+#endif
--- /dev/null
+++ b/fbtl/old_pthread_cond_signal.c
@@ -0,0 +1,56 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdlib.h>
+#include "pthreadP.h"
+#include <atomic.h>
+#include <shlib-compat.h>
+
+
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2)
+int
+__pthread_cond_signal_2_0 (pthread_cond_2_0_t *cond)
+{
+ if (cond->cond == NULL)
+ {
+ pthread_cond_t *newcond;
+
+#if LLL_LOCK_INITIALIZER == 0
+ newcond = (pthread_cond_t *) calloc (sizeof (pthread_cond_t), 1);
+ if (newcond == NULL)
+ return ENOMEM;
+#else
+ newcond = (pthread_cond_t *) malloc (sizeof (pthread_cond_t));
+ if (newcond == NULL)
+ return ENOMEM;
+
+ /* Initialize the condvar. */
+ (void) pthread_cond_init (newcond, NULL);
+#endif
+
+ if (atomic_compare_and_exchange_bool_acq (&cond->cond, newcond, NULL))
+ /* Somebody else just initialized the condvar. */
+ free (newcond);
+ }
+
+ return __pthread_cond_signal (cond->cond);
+}
+compat_symbol (libpthread, __pthread_cond_signal_2_0, pthread_cond_signal,
+ GLIBC_2_0);
+#endif
--- /dev/null
+++ b/fbtl/old_pthread_cond_timedwait.c
@@ -0,0 +1,57 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdlib.h>
+#include "pthreadP.h"
+#include <atomic.h>
+#include <shlib-compat.h>
+
+
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2)
+int
+__pthread_cond_timedwait_2_0 (pthread_cond_2_0_t *cond, pthread_mutex_t *mutex,
+ const struct timespec *abstime)
+{
+ if (cond->cond == NULL)
+ {
+ pthread_cond_t *newcond;
+
+#if LLL_LOCK_INITIALIZER == 0
+ newcond = (pthread_cond_t *) calloc (sizeof (pthread_cond_t), 1);
+ if (newcond == NULL)
+ return ENOMEM;
+#else
+ newcond = (pthread_cond_t *) malloc (sizeof (pthread_cond_t));
+ if (newcond == NULL)
+ return ENOMEM;
+
+ /* Initialize the condvar. */
+ (void) pthread_cond_init (newcond, NULL);
+#endif
+
+ if (atomic_compare_and_exchange_bool_acq (&cond->cond, newcond, NULL))
+ /* Somebody else just initialized the condvar. */
+ free (newcond);
+ }
+
+ return __pthread_cond_timedwait (cond->cond, mutex, abstime);
+}
+compat_symbol (libpthread, __pthread_cond_timedwait_2_0,
+ pthread_cond_timedwait, GLIBC_2_0);
+#endif
--- /dev/null
+++ b/fbtl/old_pthread_cond_wait.c
@@ -0,0 +1,56 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdlib.h>
+#include "pthreadP.h"
+#include <atomic.h>
+#include <shlib-compat.h>
+
+
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2)
+int
+__pthread_cond_wait_2_0 (pthread_cond_2_0_t *cond, pthread_mutex_t *mutex)
+{
+ if (cond->cond == NULL)
+ {
+ pthread_cond_t *newcond;
+
+#if LLL_LOCK_INITIALIZER == 0
+ newcond = (pthread_cond_t *) calloc (sizeof (pthread_cond_t), 1);
+ if (newcond == NULL)
+ return ENOMEM;
+#else
+ newcond = (pthread_cond_t *) malloc (sizeof (pthread_cond_t));
+ if (newcond == NULL)
+ return ENOMEM;
+
+ /* Initialize the condvar. */
+ (void) pthread_cond_init (newcond, NULL);
+#endif
+
+ if (atomic_compare_and_exchange_bool_acq (&cond->cond, newcond, NULL))
+ /* Somebody else just initialized the condvar. */
+ free (newcond);
+ }
+
+ return __pthread_cond_wait (cond->cond, mutex);
+}
+compat_symbol (libpthread, __pthread_cond_wait_2_0, pthread_cond_wait,
+ GLIBC_2_0);
+#endif
--- /dev/null
+++ b/fbtl/perf.c
@@ -0,0 +1,759 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define _GNU_SOURCE 1
+#include <argp.h>
+#include <error.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/types.h>
+
+#ifndef MAX_THREADS
+# define MAX_THREADS 100000
+#endif
+#ifndef DEFAULT_THREADS
+# define DEFAULT_THREADS 50
+#endif
+
+
+#define OPT_TO_THREAD 300
+#define OPT_TO_PROCESS 301
+#define OPT_SYNC_SIGNAL 302
+#define OPT_SYNC_JOIN 303
+#define OPT_TOPLEVEL 304
+
+
+static const struct argp_option options[] =
+ {
+ { NULL, 0, NULL, 0, "\
+This is a test for threads so we allow ther user to selection the number of \
+threads which are used at any one time. Independently the total number of \
+rounds can be selected. This is the total number of threads which will have \
+run when the process terminates:" },
+ { "threads", 't', "NUMBER", 0, "Number of threads used at once" },
+ { "starts", 's', "NUMBER", 0, "Total number of working threads" },
+ { "toplevel", OPT_TOPLEVEL, "NUMBER", 0,
+ "Number of toplevel threads which start the other threads; this \
+implies --sync-join" },
+
+ { NULL, 0, NULL, 0, "\
+Each thread can do one of two things: sleep or do work. The latter is 100% \
+CPU bound. The work load is the probability a thread does work. All values \
+from zero to 100 (inclusive) are valid. How often each thread repeats this \
+can be determined by the number of rounds. The work cost determines how long \
+each work session (not sleeping) takes. If it is zero a thread would \
+effectively nothing. By setting the number of rounds to zero the thread \
+does no work at all and pure thread creation times can be measured." },
+ { "workload", 'w', "PERCENT", 0, "Percentage of time spent working" },
+ { "workcost", 'c', "NUMBER", 0,
+ "Factor in the cost of each round of working" },
+ { "rounds", 'r', "NUMBER", 0, "Number of rounds each thread runs" },
+
+ { NULL, 0, NULL, 0, "\
+There are a number of different methods how thread creation can be \
+synchronized. Synchronization is necessary since the number of concurrently \
+running threads is limited." },
+ { "sync-signal", OPT_SYNC_SIGNAL, NULL, 0,
+ "Synchronize using a signal (default)" },
+ { "sync-join", OPT_SYNC_JOIN, NULL, 0, "Synchronize using pthread_join" },
+
+ { NULL, 0, NULL, 0, "\
+One parameter for each threads execution is the size of the stack. If this \
+parameter is not used the system's default stack size is used. If many \
+threads are used the stack size should be chosen quite small." },
+ { "stacksize", 'S', "BYTES", 0, "Size of threads stack" },
+ { "guardsize", 'g', "BYTES", 0,
+ "Size of stack guard area; must fit into the stack" },
+
+ { NULL, 0, NULL, 0, "Signal options:" },
+ { "to-thread", OPT_TO_THREAD, NULL, 0, "Send signal to main thread" },
+ { "to-process", OPT_TO_PROCESS, NULL, 0,
+ "Send signal to process (default)" },
+
+ { NULL, 0, NULL, 0, "Administrative options:" },
+ { "progress", 'p', NULL, 0, "Show signs of progress" },
+ { "timing", 'T', NULL, 0,
+ "Measure time from startup to the last thread finishing" },
+ { NULL, 0, NULL, 0, NULL }
+ };
+
+/* Prototype for option handler. */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+/* Data structure to communicate with argp functions. */
+static struct argp argp =
+{
+ options, parse_opt
+};
+
+
+static unsigned long int threads = DEFAULT_THREADS;
+static unsigned long int workload = 75;
+static unsigned long int workcost = 20;
+static unsigned long int rounds = 10;
+static long int starts = 5000;
+static unsigned long int stacksize;
+static long int guardsize = -1;
+static bool progress;
+static bool timing;
+static bool to_thread;
+static unsigned long int toplevel = 1;
+
+
+static long int running;
+static pthread_mutex_t running_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static pid_t pid;
+static pthread_t tmain;
+
+static clockid_t cl;
+static struct timespec start_time;
+
+
+static pthread_mutex_t sum_mutex = PTHREAD_MUTEX_INITIALIZER;
+unsigned int sum;
+
+static enum
+ {
+ sync_signal,
+ sync_join
+ }
+sync_method;
+
+
+/* We use 64bit values for the times. */
+typedef unsigned long long int hp_timing_t;
+
+
+/* Attributes for all created threads. */
+static pthread_attr_t attr;
+
+
+static void *
+work (void *arg)
+{
+ unsigned long int i;
+ unsigned int state = (unsigned long int) arg;
+
+ for (i = 0; i < rounds; ++i)
+ {
+ /* Determine what to do. */
+ unsigned int rnum;
+
+ /* Uniform distribution. */
+ do
+ rnum = rand_r (&state);
+ while (rnum >= UINT_MAX - (UINT_MAX % 100));
+
+ rnum %= 100;
+
+ if (rnum < workload)
+ {
+ int j;
+ int a[4] = { i, rnum, i + rnum, rnum - i };
+
+ if (progress)
+ write (STDERR_FILENO, "c", 1);
+
+ for (j = 0; j < workcost; ++j)
+ {
+ a[0] += a[3] >> 12;
+ a[1] += a[2] >> 20;
+ a[2] += a[1] ^ 0x3423423;
+ a[3] += a[0] - a[1];
+ }
+
+ pthread_mutex_lock (&sum_mutex);
+ sum += a[0] + a[1] + a[2] + a[3];
+ pthread_mutex_unlock (&sum_mutex);
+ }
+ else
+ {
+ /* Just sleep. */
+ struct timespec tv;
+
+ tv.tv_sec = 0;
+ tv.tv_nsec = 10000000;
+
+ if (progress)
+ write (STDERR_FILENO, "w", 1);
+
+ nanosleep (&tv, NULL);
+ }
+ }
+
+ return NULL;
+}
+
+
+static void *
+thread_function (void *arg)
+{
+ work (arg);
+
+ pthread_mutex_lock (&running_mutex);
+ if (--running <= 0 && starts <= 0)
+ {
+ /* We are done. */
+ if (progress)
+ write (STDERR_FILENO, "\n", 1);
+
+ if (timing)
+ {
+ struct timespec end_time;
+
+ if (clock_gettime (cl, &end_time) == 0)
+ {
+ end_time.tv_sec -= start_time.tv_sec;
+ end_time.tv_nsec -= start_time.tv_nsec;
+ if (end_time.tv_nsec < 0)
+ {
+ end_time.tv_nsec += 1000000000;
+ --end_time.tv_sec;
+ }
+
+ printf ("\nRuntime: %lu.%09lu seconds\n",
+ (unsigned long int) end_time.tv_sec,
+ (unsigned long int) end_time.tv_nsec);
+ }
+ }
+
+ printf ("Result: %08x\n", sum);
+
+ exit (0);
+ }
+ pthread_mutex_unlock (&running_mutex);
+
+ if (sync_method == sync_signal)
+ {
+ if (to_thread)
+ /* This code sends a signal to the main thread. */
+ pthread_kill (tmain, SIGUSR1);
+ else
+ /* Use this code to test sending a signal to the process. */
+ kill (pid, SIGUSR1);
+ }
+
+ if (progress)
+ write (STDERR_FILENO, "f", 1);
+
+ return NULL;
+}
+
+
+struct start_info
+{
+ unsigned int starts;
+ unsigned int threads;
+};
+
+
+static void *
+start_threads (void *arg)
+{
+ struct start_info *si = arg;
+ unsigned int starts = si->starts;
+ pthread_t ths[si->threads];
+ unsigned int state = starts;
+ unsigned int n;
+ unsigned int i = 0;
+ int err;
+
+ if (progress)
+ write (STDERR_FILENO, "T", 1);
+
+ memset (ths, '\0', sizeof (pthread_t) * si->threads);
+
+ while (starts-- > 0)
+ {
+ if (ths[i] != 0)
+ {
+ /* Wait for the threads in the order they were created. */
+ err = pthread_join (ths[i], NULL);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "cannot join thread");
+
+ if (progress)
+ write (STDERR_FILENO, "f", 1);
+ }
+
+ err = pthread_create (&ths[i], &attr, work,
+ (void *) (long) (rand_r (&state) + starts + i));
+
+ if (err != 0)
+ error (EXIT_FAILURE, err, "cannot start thread");
+
+ if (progress)
+ write (STDERR_FILENO, "t", 1);
+
+ if (++i == si->threads)
+ i = 0;
+ }
+
+ n = i;
+ do
+ {
+ if (ths[i] != 0)
+ {
+ err = pthread_join (ths[i], NULL);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "cannot join thread");
+
+ if (progress)
+ write (STDERR_FILENO, "f", 1);
+ }
+
+ if (++i == si->threads)
+ i = 0;
+ }
+ while (i != n);
+
+ if (progress)
+ write (STDERR_FILENO, "F", 1);
+
+ return NULL;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ int remaining;
+ sigset_t ss;
+ pthread_t th;
+ pthread_t *ths = NULL;
+ int empty = 0;
+ int last;
+ bool cont = true;
+
+ /* Parse and process arguments. */
+ argp_parse (&argp, argc, argv, 0, &remaining, NULL);
+
+ if (sync_method == sync_join)
+ {
+ ths = (pthread_t *) calloc (threads, sizeof (pthread_t));
+ if (ths == NULL)
+ error (EXIT_FAILURE, errno,
+ "cannot allocate memory for thread descriptor array");
+
+ last = threads;
+ }
+ else
+ {
+ ths = &th;
+ last = 1;
+ }
+
+ if (toplevel > threads)
+ {
+ printf ("resetting number of toplevel threads to %lu to not surpass number to concurrent threads\n",
+ threads);
+ toplevel = threads;
+ }
+
+ if (timing)
+ {
+ if (clock_getcpuclockid (0, &cl) != 0
+ || clock_gettime (cl, &start_time) != 0)
+ timing = false;
+ }
+
+ /* We need this later. */
+ pid = getpid ();
+ tmain = pthread_self ();
+
+ /* We use signal SIGUSR1 for communication between the threads and
+ the main thread. We only want sychronous notification. */
+ if (sync_method == sync_signal)
+ {
+ sigemptyset (&ss);
+ sigaddset (&ss, SIGUSR1);
+ if (sigprocmask (SIG_BLOCK, &ss, NULL) != 0)
+ error (EXIT_FAILURE, errno, "cannot set signal mask");
+ }
+
+ /* Create the thread attributes. */
+ pthread_attr_init (&attr);
+
+ /* If the user provided a stack size use it. */
+ if (stacksize != 0
+ && pthread_attr_setstacksize (&attr, stacksize) != 0)
+ puts ("could not set stack size; will use default");
+ /* And stack guard size. */
+ if (guardsize != -1
+ && pthread_attr_setguardsize (&attr, guardsize) != 0)
+ puts ("invalid stack guard size; will use default");
+
+ /* All threads are created detached if we are not using pthread_join
+ to synchronize. */
+ if (sync_method != sync_join)
+ pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+
+ if (sync_method == sync_signal)
+ {
+ while (1)
+ {
+ int err;
+ bool do_wait = false;
+
+ pthread_mutex_lock (&running_mutex);
+ if (starts-- < 0)
+ cont = false;
+ else
+ do_wait = ++running >= threads && starts > 0;
+
+ pthread_mutex_unlock (&running_mutex);
+
+ if (! cont)
+ break;
+
+ if (progress)
+ write (STDERR_FILENO, "t", 1);
+
+ err = pthread_create (&ths[empty], &attr, thread_function,
+ (void *) starts);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "cannot start thread %lu", starts);
+
+ if (++empty == last)
+ empty = 0;
+
+ if (do_wait)
+ sigwaitinfo (&ss, NULL);
+ }
+
+ /* Do nothing anymore. On of the threads will terminate the program. */
+ sigfillset (&ss);
+ sigdelset (&ss, SIGINT);
+ while (1)
+ sigsuspend (&ss);
+ }
+ else
+ {
+ pthread_t ths[toplevel];
+ struct start_info si[toplevel];
+ unsigned int i;
+
+ for (i = 0; i < toplevel; ++i)
+ {
+ unsigned int child_starts = starts / (toplevel - i);
+ unsigned int child_threads = threads / (toplevel - i);
+ int err;
+
+ si[i].starts = child_starts;
+ si[i].threads = child_threads;
+
+ err = pthread_create (&ths[i], &attr, start_threads, &si[i]);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "cannot start thread");
+
+ starts -= child_starts;
+ threads -= child_threads;
+ }
+
+ for (i = 0; i < toplevel; ++i)
+ {
+ int err = pthread_join (ths[i], NULL);
+
+ if (err != 0)
+ error (EXIT_FAILURE, err, "cannot join thread");
+ }
+
+ /* We are done. */
+ if (progress)
+ write (STDERR_FILENO, "\n", 1);
+
+ if (timing)
+ {
+ struct timespec end_time;
+
+ if (clock_gettime (cl, &end_time) == 0)
+ {
+ end_time.tv_sec -= start_time.tv_sec;
+ end_time.tv_nsec -= start_time.tv_nsec;
+ if (end_time.tv_nsec < 0)
+ {
+ end_time.tv_nsec += 1000000000;
+ --end_time.tv_sec;
+ }
+
+ printf ("\nRuntime: %lu.%09lu seconds\n",
+ (unsigned long int) end_time.tv_sec,
+ (unsigned long int) end_time.tv_nsec);
+ }
+ }
+
+ printf ("Result: %08x\n", sum);
+
+ exit (0);
+ }
+
+ /* NOTREACHED */
+ return 0;
+}
+
+
+/* Handle program arguments. */
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+ unsigned long int num;
+ long int snum;
+
+ switch (key)
+ {
+ case 't':
+ num = strtoul (arg, NULL, 0);
+ if (num <= MAX_THREADS)
+ threads = num;
+ else
+ printf ("\
+number of threads limited to %u; recompile with a higher limit if necessary",
+ MAX_THREADS);
+ break;
+
+ case 'w':
+ num = strtoul (arg, NULL, 0);
+ if (num <= 100)
+ workload = num;
+ else
+ puts ("workload must be between 0 and 100 percent");
+ break;
+
+ case 'c':
+ workcost = strtoul (arg, NULL, 0);
+ break;
+
+ case 'r':
+ rounds = strtoul (arg, NULL, 0);
+ break;
+
+ case 's':
+ starts = strtoul (arg, NULL, 0);
+ break;
+
+ case 'S':
+ num = strtoul (arg, NULL, 0);
+ if (num >= PTHREAD_STACK_MIN)
+ stacksize = num;
+ else
+ printf ("minimum stack size is %d\n", PTHREAD_STACK_MIN);
+ break;
+
+ case 'g':
+ snum = strtol (arg, NULL, 0);
+ if (snum < 0)
+ printf ("invalid guard size %s\n", arg);
+ else
+ guardsize = snum;
+ break;
+
+ case 'p':
+ progress = true;
+ break;
+
+ case 'T':
+ timing = true;
+ break;
+
+ case OPT_TO_THREAD:
+ to_thread = true;
+ break;
+
+ case OPT_TO_PROCESS:
+ to_thread = false;
+ break;
+
+ case OPT_SYNC_SIGNAL:
+ sync_method = sync_signal;
+ break;
+
+ case OPT_SYNC_JOIN:
+ sync_method = sync_join;
+ break;
+
+ case OPT_TOPLEVEL:
+ num = strtoul (arg, NULL, 0);
+ if (num < MAX_THREADS)
+ toplevel = num;
+ else
+ printf ("\
+number of threads limited to %u; recompile with a higher limit if necessary",
+ MAX_THREADS);
+ sync_method = sync_join;
+ break;
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+
+ return 0;
+}
+
+
+static hp_timing_t
+get_clockfreq (void)
+{
+ /* We read the information from the /proc filesystem. It contains at
+ least one line like
+ cpu MHz : 497.840237
+ or also
+ cpu MHz : 497.841
+ We search for this line and convert the number in an integer. */
+ static hp_timing_t result;
+ int fd;
+
+ /* If this function was called before, we know the result. */
+ if (result != 0)
+ return result;
+
+ fd = open ("/proc/cpuinfo", O_RDONLY);
+ if (__glibc_likely (fd != -1))
+ {
+ /* XXX AFAIK the /proc filesystem can generate "files" only up
+ to a size of 4096 bytes. */
+ char buf[4096];
+ ssize_t n;
+
+ n = read (fd, buf, sizeof buf);
+ if (__builtin_expect (n, 1) > 0)
+ {
+ char *mhz = memmem (buf, n, "cpu MHz", 7);
+
+ if (__glibc_likely (mhz != NULL))
+ {
+ char *endp = buf + n;
+ int seen_decpoint = 0;
+ int ndigits = 0;
+
+ /* Search for the beginning of the string. */
+ while (mhz < endp && (*mhz < '0' || *mhz > '9') && *mhz != '\n')
+ ++mhz;
+
+ while (mhz < endp && *mhz != '\n')
+ {
+ if (*mhz >= '0' && *mhz <= '9')
+ {
+ result *= 10;
+ result += *mhz - '0';
+ if (seen_decpoint)
+ ++ndigits;
+ }
+ else if (*mhz == '.')
+ seen_decpoint = 1;
+
+ ++mhz;
+ }
+
+ /* Compensate for missing digits at the end. */
+ while (ndigits++ < 6)
+ result *= 10;
+ }
+ }
+
+ close (fd);
+ }
+
+ return result;
+}
+
+
+int
+clock_getcpuclockid (pid_t pid, clockid_t *clock_id)
+{
+ /* We don't allow any process ID but our own. */
+ if (pid != 0 && pid != getpid ())
+ return EPERM;
+
+#ifdef CLOCK_PROCESS_CPUTIME_ID
+ /* Store the number. */
+ *clock_id = CLOCK_PROCESS_CPUTIME_ID;
+
+ return 0;
+#else
+ /* We don't have a timer for that. */
+ return ENOENT;
+#endif
+}
+
+
+#ifdef i386
+#define HP_TIMING_NOW(Var) __asm__ __volatile__ ("rdtsc" : "=A" (Var))
+#elif defined __x86_64__
+# define HP_TIMING_NOW(Var) \
+ ({ unsigned int _hi, _lo; \
+ asm volatile ("rdtsc" : "=a" (_lo), "=d" (_hi)); \
+ (Var) = ((unsigned long long int) _hi << 32) | _lo; })
+#elif defined __ia64__
+#define HP_TIMING_NOW(Var) __asm__ __volatile__ ("mov %0=ar.itc" : "=r" (Var) : : "memory")
+#else
+#error "HP_TIMING_NOW missing"
+#endif
+
+/* Get current value of CLOCK and store it in TP. */
+int
+clock_gettime (clockid_t clock_id, struct timespec *tp)
+{
+ int retval = -1;
+
+ switch (clock_id)
+ {
+ case CLOCK_PROCESS_CPUTIME_ID:
+ {
+
+ static hp_timing_t freq;
+ hp_timing_t tsc;
+
+ /* Get the current counter. */
+ HP_TIMING_NOW (tsc);
+
+ if (freq == 0)
+ {
+ freq = get_clockfreq ();
+ if (freq == 0)
+ return EINVAL;
+ }
+
+ /* 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) * UINT64_C (1000000000)) / freq;
+
+ retval = 0;
+ }
+ break;
+
+ default:
+ errno = EINVAL;
+ break;
+ }
+
+ return retval;
+}
--- /dev/null
+++ b/fbtl/pt-allocrtsig.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <signal.h>
+
+
+/* These are defined in libc. We want to have only one definition
+ so we "forward" the calls. */
+extern int __libc_current_sigrtmin_private (void);
+extern int __libc_current_sigrtmax_private (void);
+extern int __libc_allocate_rtsig_private (int high);
+
+
+/* We reserve __SIGRTMIN for use as the cancellation signal and
+ __SIGRTMIN+1 to handle setuid et.al. These signals are used
+ internally. */
+int
+__libc_current_sigrtmin (void)
+{
+ return __libc_current_sigrtmin_private ();
+}
+
+
+int
+__libc_current_sigrtmax (void)
+{
+ return __libc_current_sigrtmax_private ();
+}
+
+
+int
+__libc_allocate_rtsig (int high)
+{
+ return __libc_allocate_rtsig_private (high);
+}
--- /dev/null
+++ b/fbtl/pt-cleanup.c
@@ -0,0 +1,62 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <setjmp.h>
+#include <stdlib.h>
+#include "pthreadP.h"
+#include <jmpbuf-unwind.h>
+
+void
+__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)
--- /dev/null
+++ b/fbtl/pt-crti.S
@@ -0,0 +1,43 @@
+/* Special .init and .fini section support for libpthread.
+ Copyright (C) 2012-2013 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.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Arrange for __pthread_initialize_minimal_internal to be called at
+ libpthread startup, instead of conditionally calling
+ __gmon_start__. */
+
+#define PREINIT_FUNCTION __pthread_initialize_minimal_internal
+#define PREINIT_FUNCTION_WEAK 0
+
+#include <crti.S>
--- /dev/null
+++ b/fbtl/pt-raise.c
@@ -0,0 +1,29 @@
+/* ISO C raise function for libpthread.
+ Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <signal.h>
+
+
+int
+raise (int sig)
+{
+ /* This is what POSIX says must happen. */
+ return pthread_kill (pthread_self (), sig);
+}
--- /dev/null
+++ b/fbtl/pt-system.c
@@ -0,0 +1,32 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <sysdep.h>
+#include "pthreadP.h"
+
+
+int
+system (const char *line)
+{
+ return __libc_system (line);
+}
+
+/* __libc_system in libc.so handles cancellation. */
+LIBC_CANCEL_HANDLED ();
--- /dev/null
+++ b/fbtl/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
--- /dev/null
+++ b/fbtl/pthreadP.h
@@ -0,0 +1,661 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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 <stackinfo.h>
+#include <internaltypes.h>
+#include <pthread-functions.h>
+#include <atomic.h>
+#include <kernel-features.h>
+#include <errno.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 pthread attributes. */
+extern struct pthread_attr __default_pthread_attr attribute_hidden;
+extern int __default_pthread_attr_lock 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 <= KTID_TERMINATED, 0)
+# define INVALID_NOT_TERMINATED_TD_P(pd) __builtin_expect ((pd)->tid < KTID_TERMINATED, 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 && !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 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 IS_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 " __SYMBOL_PREFIX "__libc_enable_asynccancel"); \
+ __asm (".globl " __SYMBOL_PREFIX "__libc_disable_asynccancel")
+#elif IS_IN (libpthread)
+# define LIBC_CANCEL_ASYNC() CANCEL_ASYNC ()
+# define LIBC_CANCEL_RESET(val) CANCEL_RESET (val)
+# define LIBC_CANCEL_HANDLED() \
+ __asm (".globl " __SYMBOL_PREFIX "__pthread_enable_asynccancel"); \
+ __asm (".globl " __SYMBOL_PREFIX "__pthread_disable_asynccancel")
+#elif 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 " __SYMBOL_PREFIX "__librt_enable_asynccancel"); \
+ __asm (".globl " __SYMBOL_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
+
+#ifndef PTHREAD_SIGBASE
+# define PTHREAD_SIGBASE __SIGRTMIN
+#endif
+
+/* The signal used for asynchronous cancelation. */
+#define SIGCANCEL PTHREAD_SIGBASE
+
+
+/* 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 (PTHREAD_SIGBASE + 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 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)
+ internal_function;
+#else
+extern int *__libc_pthread_init (unsigned long int *ptr,
+ void (*reclaim) (void),
+ const struct pthread_functions *functions)
+ internal_function;
+
+/* Variable set to a nonzero value either if more than one thread runs or ran,
+ or if a single-threaded process is trying to cancel itself. See
+ nptl/descr.h for more context on the single-threaded process case. */
+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;
+
+extern size_t __pthread_get_minstack (const pthread_attr_t *attr);
+
+/* 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_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_cond_lock (pthread_mutex_t *__mutex)
+ attribute_hidden internal_function;
+extern void __pthread_mutex_cond_lock_adjust (pthread_mutex_t *__mutex)
+ attribute_hidden internal_function;
+extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex);
+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_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);
+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 void *__pthread_getspecific (pthread_key_t key);
+extern int __pthread_setspecific (pthread_key_t key, const void *value);
+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));
+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) __attribute__ ((__noreturn__));
+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;
+
+#if IS_IN (libpthread)
+hidden_proto (__pthread_mutex_init)
+hidden_proto (__pthread_mutex_destroy)
+hidden_proto (__pthread_mutex_lock)
+hidden_proto (__pthread_mutex_unlock)
+hidden_proto (__pthread_rwlock_rdlock)
+hidden_proto (__pthread_rwlock_wrlock)
+hidden_proto (__pthread_rwlock_unlock)
+hidden_proto (__pthread_key_create)
+hidden_proto (__pthread_getspecific)
+hidden_proto (__pthread_setspecific)
+hidden_proto (__pthread_once)
+hidden_proto (__pthread_setcancelstate)
+#endif
+
+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;
+
+#if 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;
+#ifndef SHARED
+extern void __nptl_set_robust (struct pthread *self);
+#endif
+
+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
+
+/* Test if the mutex is suitable for the FUTEX_WAIT_REQUEUE_PI operation. */
+#if (defined lll_futex_wait_requeue_pi \
+ && defined __ASSUME_REQUEUE_PI)
+# define USE_REQUEUE_PI(mut) \
+ ((mut) && (mut) != (void *) ~0l \
+ && (((mut)->__data.__kind \
+ & (PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_NORMAL_NP)) \
+ == PTHREAD_MUTEX_PRIO_INHERIT_NP))
+#else
+# define USE_REQUEUE_PI(mut) 0
+#endif
+
+/* Returns 0 if POL is a valid scheduling policy. */
+static inline int
+check_sched_policy_attr (int pol)
+{
+ if (pol == SCHED_OTHER || pol == SCHED_FIFO || pol == SCHED_RR)
+ return 0;
+
+ return EINVAL;
+}
+
+/* Returns 0 if PR is within the accepted range of priority values for
+ the scheduling policy POL or EINVAL otherwise. */
+static inline int
+check_sched_priority_attr (int pr, int pol)
+{
+ int min = __sched_get_priority_min (pol);
+ int max = __sched_get_priority_max (pol);
+
+ if (min >= 0 && max >= 0 && pr >= min && pr <= max)
+ return 0;
+
+ return EINVAL;
+}
+
+/* Returns 0 if ST is a valid stack size for a thread stack and EINVAL
+ otherwise. */
+static inline int
+check_stacksize_attr (size_t st)
+{
+ if (st >= PTHREAD_STACK_MIN)
+ return 0;
+
+ return EINVAL;
+}
+
+/* Defined in pthread_setaffinity.c. */
+extern size_t __kernel_cpumask_size attribute_hidden;
+extern int __determine_cpumask_size (pid_t tid);
+
+/* Returns 0 if CS and SZ are valid values for the cpuset and cpuset size
+ respectively. Otherwise it returns an error number. */
+static inline int
+check_cpuset_attr (const cpu_set_t *cs, const size_t sz)
+{
+ if (__kernel_cpumask_size == 0)
+ {
+ int res = __determine_cpumask_size (THREAD_SELF->tid);
+ if (res)
+ 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 < sz; ++cnt)
+ if (((char *) cs)[cnt] != '\0')
+ /* Found a nonzero byte. This means the user request cannot be
+ fulfilled. */
+ return EINVAL;
+
+ return 0;
+}
+
+#endif /* pthreadP.h */
--- /dev/null
+++ b/fbtl/pthread_atfork.c
@@ -0,0 +1,61 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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
+#ifndef __pthread_atfork
+/* Don't mark the compatibility function as hidden. */
+attribute_hidden
+#endif
+__pthread_atfork (void (*prepare) (void), void (*parent) (void),
+ void (*child) (void))
+{
+ return __register_atfork (prepare, parent, child,
+ &__dso_handle == NULL ? NULL : __dso_handle);
+}
+#ifndef __pthread_atfork
+extern int pthread_atfork (void (*prepare) (void), void (*parent) (void),
+ void (*child) (void)) attribute_hidden;
+strong_alias (__pthread_atfork, pthread_atfork)
+#endif
--- /dev/null
+++ b/fbtl/pthread_attr_destroy.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include "pthreadP.h"
+#include <shlib-compat.h>
+
+int
+__pthread_attr_destroy (pthread_attr_t *attr)
+{
+ struct pthread_attr *iattr;
+
+ assert (sizeof (*attr) >= sizeof (struct pthread_attr));
+ iattr = (struct pthread_attr *) attr;
+
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
+ /* In old struct pthread_attr, neither next nor cpuset are
+ present. */
+ if (__builtin_expect ((iattr->flags & ATTR_FLAG_OLDATTR), 0) == 0)
+#endif
+ /* The affinity CPU set might be allocated dynamically. */
+ free (iattr->cpuset);
+
+ return 0;
+}
+strong_alias (__pthread_attr_destroy, pthread_attr_destroy)
--- /dev/null
+++ b/fbtl/pthread_attr_getdetachstate.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include "pthreadP.h"
+
+
+int
+__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)
--- /dev/null
+++ b/fbtl/pthread_attr_getguardsize.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl/pthread_attr_getinheritsched.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include "pthreadP.h"
+
+
+int
+__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)
--- /dev/null
+++ b/fbtl/pthread_attr_getschedparam.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <string.h>
+#include "pthreadP.h"
+
+
+int
+__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)
--- /dev/null
+++ b/fbtl/pthread_attr_getschedpolicy.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include "pthreadP.h"
+
+
+int
+__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)
--- /dev/null
+++ b/fbtl/pthread_attr_getscope.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include "pthreadP.h"
+
+
+int
+__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)
--- /dev/null
+++ b/fbtl/pthread_attr_getstack.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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)
--- /dev/null
+++ b/fbtl/pthread_attr_getstackaddr.c
@@ -0,0 +1,42 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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'")
--- /dev/null
+++ b/fbtl/pthread_attr_getstacksize.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+
+ size_t size = iattr->stacksize;
+
+ /* If the user has not set a stack size we return what the system
+ will use as the default. */
+ if (size == 0)
+ {
+ lll_lock (__default_pthread_attr_lock, LLL_PRIVATE);
+ size = __default_pthread_attr.stacksize;
+ lll_unlock (__default_pthread_attr_lock, LLL_PRIVATE);
+ }
+ *stacksize = size;
+
+ return 0;
+}
+strong_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize)
--- /dev/null
+++ b/fbtl/pthread_attr_init.c
@@ -0,0 +1,85 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include "pthreadP.h"
+
+#include <shlib-compat.h>
+
+
+struct pthread_attr *__attr_list;
+int __attr_list_lock = LLL_LOCK_INITIALIZER;
+
+
+int
+__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;
+}
+versioned_symbol (libpthread, __pthread_attr_init_2_1, pthread_attr_init,
+ GLIBC_2_1);
+
+
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
+int
+__pthread_attr_init_2_0 (pthread_attr_t *attr)
+{
+ /* This code is specific to the old LinuxThread code which has a too
+ small pthread_attr_t definition. The struct looked like
+ this: */
+ struct old_attr
+ {
+ int detachstate;
+ int schedpolicy;
+ struct sched_param schedparam;
+ int inheritsched;
+ int scope;
+ };
+ 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 (struct old_attr));
+
+ iattr = (struct pthread_attr *) attr;
+ iattr->flags |= ATTR_FLAG_OLDATTR;
+
+ /* We cannot enqueue the attribute because that member is not in the
+ old attribute structure. */
+ return 0;
+}
+compat_symbol (libpthread, __pthread_attr_init_2_0, pthread_attr_init,
+ GLIBC_2_0);
+#endif
--- /dev/null
+++ b/fbtl/pthread_attr_setdetachstate.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <errno.h>
+#include "pthreadP.h"
+
+
+int
+__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)
--- /dev/null
+++ b/fbtl/pthread_attr_setguardsize.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl/pthread_attr_setinheritsched.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <errno.h>
+#include "pthreadP.h"
+
+
+int
+__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)
--- /dev/null
+++ b/fbtl/pthread_attr_setschedparam.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include "pthreadP.h"
+
+
+int
+__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 ret = check_sched_priority_attr (param->sched_priority,
+ iattr->schedpolicy);
+ if (ret)
+ return ret;
+
+ /* 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)
--- /dev/null
+++ b/fbtl/pthread_attr_setschedpolicy.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <errno.h>
+#include "pthreadP.h"
+
+
+int
+__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. */
+ int ret = check_sched_policy_attr (policy);
+ if (ret)
+ return ret;
+
+ /* 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)
--- /dev/null
+++ b/fbtl/pthread_attr_setscope.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <errno.h>
+#include "pthreadP.h"
+
+
+int
+__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)
--- /dev/null
+++ b/fbtl/pthread_attr_setstack.c
@@ -0,0 +1,92 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include "pthreadP.h"
+
+
+#ifndef NEW_VERNUM
+# define NEW_VERNUM GLIBC_2_3_3
+#endif
+
+
+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. */
+ int ret = check_stacksize_attr (stacksize);
+ if (ret)
+ return ret;
+
+#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
+# include <shlib-compat.h>
+versioned_symbol (libpthread, __pthread_attr_setstack, pthread_attr_setstack,
+ NEW_VERNUM);
+
+# if SHLIB_COMPAT(libpthread, GLIBC_2_2, NEW_VERNUM)
+
+int
+__old_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 < 16384)
+ 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;
+}
+
+compat_symbol (libpthread, __old_pthread_attr_setstack, pthread_attr_setstack,
+ GLIBC_2_2);
+# endif
+
+#endif
--- /dev/null
+++ b/fbtl/pthread_attr_setstackaddr.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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'")
--- /dev/null
+++ b/fbtl/pthread_attr_setstacksize.c
@@ -0,0 +1,81 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include "pthreadP.h"
+
+#ifndef NEW_VERNUM
+# define NEW_VERNUM GLIBC_2_3_3
+#endif
+
+
+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. */
+ int ret = check_stacksize_attr (stacksize);
+ if (ret)
+ return ret;
+
+ iattr->stacksize = stacksize;
+
+ return 0;
+}
+
+#if PTHREAD_STACK_MIN == 16384
+strong_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize)
+#else
+# include <shlib-compat.h>
+versioned_symbol (libpthread, __pthread_attr_setstacksize,
+ pthread_attr_setstacksize, NEW_VERNUM);
+
+# if SHLIB_COMPAT(libpthread, GLIBC_2_1, NEW_VERNUM)
+
+int
+__old_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 < 16384)
+ return EINVAL;
+
+# ifdef STACKSIZE_ADJUST
+ STACKSIZE_ADJUST;
+# endif
+
+ iattr->stacksize = stacksize;
+
+ return 0;
+}
+
+compat_symbol (libpthread, __old_pthread_attr_setstacksize,
+ pthread_attr_setstacksize, GLIBC_2_1);
+# endif
+
+#endif
--- /dev/null
+++ b/fbtl/pthread_barrier_destroy.c
@@ -0,0 +1,42 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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 (__glibc_likely (ibarrier->left == ibarrier->init_count))
+ /* 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;
+}
--- /dev/null
+++ b/fbtl/pthread_barrier_init.c
@@ -0,0 +1,69 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include "pthreadP.h"
+#include <lowlevellock.h>
+#include <kernel-features.h>
+
+
+static const struct pthread_barrierattr default_barrierattr =
+ {
+ .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 (__glibc_unlikely (count == 0))
+ return EINVAL;
+
+ const struct pthread_barrierattr *iattr
+ = (attr != NULL
+ ? iattr = (struct pthread_barrierattr *) attr
+ : &default_barrierattr);
+
+ 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;
+}
--- /dev/null
+++ b/fbtl/pthread_barrier_wait.c
@@ -0,0 +1,77 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl/pthread_barrierattr_destroy.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP.h"
+
+
+int
+pthread_barrierattr_destroy (pthread_barrierattr_t *attr)
+{
+ /* Nothing to do. */
+
+ return 0;
+}
--- /dev/null
+++ b/fbtl/pthread_barrierattr_getpshared.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP.h"
+
+
+int
+pthread_barrierattr_getpshared (const pthread_barrierattr_t *attr,
+ int *pshared)
+{
+ *pshared = ((const struct pthread_barrierattr *) attr)->pshared;
+
+ return 0;
+}
--- /dev/null
+++ b/fbtl/pthread_barrierattr_init.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP.h"
+
+
+int
+pthread_barrierattr_init (pthread_barrierattr_t *attr)
+{
+ ((struct pthread_barrierattr *) attr)->pshared = PTHREAD_PROCESS_PRIVATE;
+
+ return 0;
+}
--- /dev/null
+++ b/fbtl/pthread_barrierattr_setpshared.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl/pthread_cancel.c
@@ -0,0 +1,101 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <signal.h>
+#include "pthreadP.h"
+#include "atomic.h"
+#include <sysdep.h>
+#include <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. */
+#warning TODO recheck
+#if 1
+ result = INLINE_SYSCALL(thr_kill, 2, pd->tid, SIGCANCEL);
+
+#else
+ pid_t pid = getpid ();
+
+ INTERNAL_SYSCALL_DECL (err);
+ int val = INTERNAL_SYSCALL_CALL (tgkill, err, pid, pd->tid,
+ SIGCANCEL);
+
+ if (INTERNAL_SYSCALL_ERROR_P (val, err))
+ result = INTERNAL_SYSCALL_ERRNO (val, err);
+#endif
+ break;
+ }
+
+ /* A single-threaded process should be able to kill itself, since there is
+ nothing in the POSIX specification that says that it cannot. So we set
+ multiple_threads to true so that cancellation points get executed. */
+ THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1);
+#ifndef TLS_MULTIPLE_THREADS_IN_TCB
+ __pthread_multiple_threads = *__libc_multiple_threads_ptr = 1;
+#endif
+ }
+ /* 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)
--- /dev/null
+++ b/fbtl/pthread_clock_gettime.c
@@ -0,0 +1,68 @@
+/* Copyright (C) 2001-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#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
--- /dev/null
+++ b/fbtl/pthread_clock_settime.c
@@ -0,0 +1,55 @@
+/* Copyright (C) 2001-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#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
--- /dev/null
+++ b/fbtl/pthread_cond_broadcast.c
@@ -0,0 +1,97 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <endian.h>
+#include <errno.h>
+#include <sysdep.h>
+#include <lowlevellock.h>
+#include <pthread.h>
+#include <pthreadP.h>
+#include <stap-probe.h>
+
+#include <shlib-compat.h>
+#include <kernel-features.h>
+
+
+int
+__pthread_cond_broadcast (pthread_cond_t *cond)
+{
+ LIBC_PROBE (cond_broadcast, 1, 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);
+
+ /* Wake everybody. */
+ pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex;
+
+ /* Do not use requeue for pshared condvars. */
+ if (mut == (void *) ~0l
+ || PTHREAD_MUTEX_PSHARED (mut) & PTHREAD_MUTEX_PSHARED_BIT)
+ goto wake_all;
+# warning wake all every time
+#if 0
+#if (defined lll_futex_cmp_requeue_pi \
+ && defined __ASSUME_REQUEUE_PI)
+ int pi_flag = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_NP;
+ pi_flag &= mut->__data.__kind;
+
+ if (pi_flag == PTHREAD_MUTEX_PRIO_INHERIT_NP)
+ {
+ if (lll_futex_cmp_requeue_pi (&cond->__data.__futex, 1, INT_MAX,
+ &mut->__data.__lock, futex_val,
+ LLL_PRIVATE) == 0)
+ return 0;
+ }
+ else
+#endif
+ /* 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))
+ return 0;
+#endif
+wake_all:
+ lll_futex_wake (&cond->__data.__futex, INT_MAX, pshared);
+ return 0;
+ }
+
+ /* We are done. */
+ lll_unlock (cond->__data.__lock, pshared);
+
+ return 0;
+}
+
+versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast,
+ GLIBC_2_3_2);
--- /dev/null
+++ b/fbtl/pthread_cond_destroy.c
@@ -0,0 +1,86 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <shlib-compat.h>
+#include "pthreadP.h"
+#include <stap-probe.h>
+
+
+int
+__pthread_cond_destroy (pthread_cond_t *cond)
+{
+ int pshared = (cond->__data.__mutex == (void *) ~0l)
+ ? LLL_SHARED : LLL_PRIVATE;
+
+ LIBC_PROBE (cond_destroy, 1, cond);
+
+ /* 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;
+}
+versioned_symbol (libpthread, __pthread_cond_destroy,
+ pthread_cond_destroy, GLIBC_2_3_2);
--- /dev/null
+++ b/fbtl/pthread_cond_init.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <shlib-compat.h>
+#include "pthreadP.h"
+#include <stap-probe.h>
+
+
+int
+__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;
+
+ LIBC_PROBE (cond_init, 2, cond, cond_attr);
+
+ return 0;
+}
+versioned_symbol (libpthread, __pthread_cond_init,
+ pthread_cond_init, GLIBC_2_3_2);
--- /dev/null
+++ b/fbtl/pthread_cond_signal.c
@@ -0,0 +1,90 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <endian.h>
+#include <errno.h>
+#include <sysdep.h>
+#include <lowlevellock.h>
+#include <pthread.h>
+#include <pthreadP.h>
+
+#include <shlib-compat.h>
+#include <kernel-features.h>
+#include <stap-probe.h>
+
+
+int
+__pthread_cond_signal (pthread_cond_t *cond)
+{
+ int pshared = (cond->__data.__mutex == (void *) ~0l)
+ ? LLL_SHARED : LLL_PRIVATE;
+
+ LIBC_PROBE (cond_signal, 1, cond);
+
+ /* 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;
+
+#warning TODO/rework
+#if 0
+#if (defined lll_futex_cmp_requeue_pi \
+ && defined __ASSUME_REQUEUE_PI)
+ int pi_flag = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_NP;
+ pthread_mutex_t *mut = cond->__data.__mutex;
+
+ /* Do not use requeue for pshared condvars. */
+ if (mut != (void *) ~0l)
+ pi_flag &= mut->__data.__kind;
+
+ if (__builtin_expect (pi_flag == PTHREAD_MUTEX_PRIO_INHERIT_NP, 0)
+ /* This can only really fail with a ENOSYS, since nobody can modify
+ futex while we have the cond_lock. */
+ && lll_futex_cmp_requeue_pi (&cond->__data.__futex, 1, 0,
+ &mut->__data.__lock,
+ cond->__data.__futex, pshared) == 0)
+ {
+ lll_unlock (cond->__data.__lock, pshared);
+ return 0;
+ }
+ else
+#endif
+ /* Wake one. */
+ if (! __builtin_expect (lll_futex_wake_unlock (&cond->__data.__futex,
+ 1, 1,
+ &cond->__data.__lock,
+ pshared), 0))
+ return 0;
+#endif
+ /* Fallback if neither of them work. */
+ lll_futex_wake (&cond->__data.__futex, 1, pshared);
+ }
+
+ /* We are done. */
+ lll_unlock (cond->__data.__lock, pshared);
+
+ return 0;
+}
+
+versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal,
+ GLIBC_2_3_2);
--- /dev/null
+++ b/fbtl/pthread_cond_timedwait.c
@@ -0,0 +1,267 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <endian.h>
+#include <errno.h>
+#include <sysdep.h>
+#include <lowlevellock.h>
+#include <pthread.h>
+#include <pthreadP.h>
+#include <kernel-features.h>
+
+#include <shlib-compat.h>
+
+#ifndef HAVE_CLOCK_GETTIME_VSYSCALL
+# undef INTERNAL_VSYSCALL
+# define INTERNAL_VSYSCALL INTERNAL_SYSCALL
+# undef INLINE_VSYSCALL
+# define INLINE_VSYSCALL INLINE_SYSCALL
+#else
+# include <bits/libc-vdso.h>
+#endif
+
+/* Cleanup handler, defined in pthread_cond_wait.c. */
+extern void __condvar_cleanup (void *arg)
+ __attribute__ ((visibility ("hidden")));
+
+struct _condvar_cleanup_buffer
+{
+ int oldtype;
+ pthread_cond_t *cond;
+ pthread_mutex_t *mutex;
+ unsigned int bc_seq;
+};
+
+int
+__pthread_cond_timedwait (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;
+
+#if (defined lll_futex_timed_wait_requeue_pi \
+ && defined __ASSUME_REQUEUE_PI)
+ int pi_flag = 0;
+#endif
+
+ /* Make sure we are alone. */
+ 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;
+
+ /* Work around the fact that the kernel rejects negative timeout values
+ despite them being valid. */
+ if (__glibc_unlikely (abstime->tv_sec < 0))
+ goto timeout;
+
+ /* 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)
+ {
+#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \
+ || !defined lll_futex_timed_wait_bitset)
+ struct timespec rt;
+ {
+# if 1 /* used to be ifdef __NR_clock_gettime */
+ INTERNAL_SYSCALL_DECL (err);
+ (void) INTERNAL_VSYSCALL (clock_gettime, err, 2,
+ (cond->__data.__nwaiters
+ & ((1 << COND_NWAITERS_SHIFT) - 1)),
+ &rt);
+ /* 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 (__glibc_unlikely (rt.tv_sec < 0))
+ {
+ if (cbuffer.bc_seq != cond->__data.__broadcast_seq)
+ goto bc_out;
+
+ goto timeout;
+ }
+#endif
+
+ 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 ();
+
+/* REQUEUE_PI was implemented after FUTEX_CLOCK_REALTIME, so it is sufficient
+ to check just the former. */
+#if (defined lll_futex_timed_wait_requeue_pi \
+ && defined __ASSUME_REQUEUE_PI)
+ /* If pi_flag remained 1 then it means that we had the lock and the mutex
+ but a spurious waker raced ahead of us. Give back the mutex before
+ going into wait again. */
+ if (pi_flag)
+ {
+ __pthread_mutex_cond_lock_adjust (mutex);
+ __pthread_mutex_unlock_usercnt (mutex, 0);
+ }
+ pi_flag = USE_REQUEUE_PI (mutex);
+
+ if (pi_flag)
+ {
+ unsigned int clockbit = (cond->__data.__nwaiters & 1
+ ? 0 : FUTEX_CLOCK_REALTIME);
+ err = lll_futex_timed_wait_requeue_pi (&cond->__data.__futex,
+ futex_val, abstime, clockbit,
+ &mutex->__data.__lock,
+ pshared);
+ pi_flag = (err == 0);
+ }
+ else
+#endif
+
+ {
+#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \
+ || !defined lll_futex_timed_wait_bitset)
+ /* Wait until woken by signal or broadcast. */
+ err = lll_futex_timed_wait (&cond->__data.__futex,
+ futex_val, &rt, pshared);
+#else
+ unsigned int clockbit = (cond->__data.__nwaiters & 1
+ ? 0 : FUTEX_CLOCK_REALTIME);
+ err = lll_futex_timed_wait_bitset (&cond->__data.__futex, futex_val,
+ abstime, clockbit, pshared);
+#endif
+ }
+
+ /* 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 (__glibc_unlikely (err == -ETIMEDOUT))
+ {
+ 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. */
+#if (defined lll_futex_timed_wait_requeue_pi \
+ && defined __ASSUME_REQUEUE_PI)
+ if (pi_flag)
+ {
+ __pthread_mutex_cond_lock_adjust (mutex);
+ err = 0;
+ }
+ else
+#endif
+ err = __pthread_mutex_cond_lock (mutex);
+
+ return err ?: result;
+}
+
+versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
+ GLIBC_2_3_2);
--- /dev/null
+++ b/fbtl/pthread_cond_wait.c
@@ -0,0 +1,236 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <endian.h>
+#include <errno.h>
+#include <sysdep.h>
+#include <lowlevellock.h>
+#include <pthread.h>
+#include <pthreadP.h>
+
+#include <shlib-compat.h>
+#include <stap-probe.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. We don't try to get the mutex if we already own it. */
+ if (!(USE_REQUEUE_PI (cbuffer->mutex))
+ || ((cbuffer->mutex->__data.__lock & FUTEX_TID_MASK)
+ != THREAD_GETMEM (THREAD_SELF, tid)))
+ {
+ __pthread_mutex_cond_lock (cbuffer->mutex);
+ }
+ else
+ __pthread_mutex_cond_lock_adjust (cbuffer->mutex);
+}
+
+
+int
+__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;
+
+#if (defined lll_futex_wait_requeue_pi \
+ && defined __ASSUME_REQUEUE_PI)
+ int pi_flag = 0;
+#endif
+
+ LIBC_PROBE (cond_wait, 2, cond, mutex);
+
+ /* Make sure we are alone. */
+ lll_lock (cond->__data.__lock, pshared);
+
+ /* Now we can release the mutex. */
+ err = __pthread_mutex_unlock_usercnt (mutex, 0);
+ if (__glibc_unlikely (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;
+
+ 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 ();
+
+#if (defined lll_futex_wait_requeue_pi \
+ && defined __ASSUME_REQUEUE_PI)
+ /* If pi_flag remained 1 then it means that we had the lock and the mutex
+ but a spurious waker raced ahead of us. Give back the mutex before
+ going into wait again. */
+ if (pi_flag)
+ {
+ __pthread_mutex_cond_lock_adjust (mutex);
+ __pthread_mutex_unlock_usercnt (mutex, 0);
+ }
+ pi_flag = USE_REQUEUE_PI (mutex);
+
+ if (pi_flag)
+ {
+ err = lll_futex_wait_requeue_pi (&cond->__data.__futex,
+ futex_val, &mutex->__data.__lock,
+ pshared);
+
+ pi_flag = (err == 0);
+ }
+ else
+#endif
+ /* 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. Not needed for PI. */
+#if (defined lll_futex_wait_requeue_pi \
+ && defined __ASSUME_REQUEUE_PI)
+ if (pi_flag)
+ {
+ __pthread_mutex_cond_lock_adjust (mutex);
+ return 0;
+ }
+ else
+#endif
+ return __pthread_mutex_cond_lock (mutex);
+}
+
+versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
+ GLIBC_2_3_2);
--- /dev/null
+++ b/fbtl/pthread_condattr_destroy.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP.h"
+
+
+int
+__pthread_condattr_destroy (pthread_condattr_t *attr)
+{
+ /* Nothing to be done. */
+ return 0;
+}
+strong_alias (__pthread_condattr_destroy, pthread_condattr_destroy)
--- /dev/null
+++ b/fbtl/pthread_condattr_getclock.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl/pthread_condattr_getpshared.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP.h"
+
+
+int
+pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared)
+{
+ *pshared = ((const struct pthread_condattr *) attr)->value & 1;
+
+ return 0;
+}
--- /dev/null
+++ b/fbtl/pthread_condattr_init.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+#include "pthreadP.h"
+
+
+int
+__pthread_condattr_init (pthread_condattr_t *attr)
+{
+ memset (attr, '\0', sizeof (*attr));
+
+ return 0;
+}
+strong_alias (__pthread_condattr_init, pthread_condattr_init)
--- /dev/null
+++ b/fbtl/pthread_condattr_setclock.c
@@ -0,0 +1,46 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sysdep.h>
+#include "pthreadP.h"
+#include <kernel-features.h>
+
+
+int
+pthread_condattr_setclock (pthread_condattr_t *attr, clockid_t clock_id)
+{
+ /* Only a few clocks are allowed. */
+ if (clock_id != CLOCK_MONOTONIC && 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;
+}
--- /dev/null
+++ b/fbtl/pthread_condattr_setpshared.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl/pthread_create.c
@@ -0,0 +1,669 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include "pthreadP.h"
+#include <hp-timing.h>
+#include <ldsodefs.h>
+#include <atomic.h>
+#include <libc-internal.h>
+#include <resolv.h>
+#include <kernel-features.h>
+#include <exit-thread.h>
+
+#include <shlib-compat.h>
+
+#include <stap-probe.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 __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 (__glibc_unlikely (pd->tpp != NULL))
+ {
+ 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
+
+#if 1
+ _FPU_SETCW(pd->fpu_control_init);
+#endif
+
+ /* Initialize resolver state pointer. */
+ __resp = &pd->res;
+
+ /* Initialize pointers to locale data. */
+ __ctype_init ();
+
+ /* Allow setxid from now onwards. */
+ if (__glibc_unlikely (atomic_exchange_acq (&pd->setxid_futex, 0) == -2))
+ lll_futex_wake (&pd->setxid_futex, 1, LLL_PRIVATE);
+
+#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 (__glibc_unlikely (pd->parent_cancelhandling & CANCELING_BITMASK))
+ {
+ sigset_t mask;
+ __sigemptyset (&mask);
+ __sigaddset (&mask, SIGCANCEL);
+ INLINE_SYSCALL (sigprocmask, 3, SIG_UNBLOCK, &mask, NULL);
+ }
+
+ /* 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 (__glibc_likely (! not_first_call))
+ {
+ /* Store the new cleanup handler info. */
+ THREAD_SETMEM (pd, cleanup_jmp_buf, &unwind_buf);
+
+ if (__glibc_unlikely (pd->stopped_start))
+ {
+ 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);
+ }
+
+ LIBC_PROBE (pthread_start, 3, (pthread_t) pd, pd->start_routine, pd->arg);
+
+ /* 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
+ }
+
+ /* Call destructors for the thread_local TLS variables. */
+#ifndef SHARED
+ if (&__call_tls_dtors != NULL)
+#endif
+ __call_tls_dtors ();
+
+ /* Run the destructor for the thread-local data. */
+ __nptl_deallocate_tsd ();
+
+ /* Clean up any state libc stored in thread-local variables. */
+ __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 (__glibc_unlikely (atomic_decrement_and_test (&__nptl_nthreads)))
+ /* This was the last thread. */
+ exit (0);
+
+ /* Report the death of the thread if this is wanted. */
+ if (__glibc_unlikely (pd->report_events))
+ {
+ /* 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);
+
+#warning robust misc
+#if 0
+#ifndef __ASSUME_SET_ROBUST_LIST
+ /* If this thread has any robust mutexes locked, handle them now. */
+# ifdef __PTHREAD_MUTEX_HAVE_PREV
+ 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
+#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 (__glibc_unlikely (pd->cancelhandling & SETXID_BITMASK))
+ {
+ /* 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_CHILD_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 ();
+
+ /* NOTREACHED */
+ return 0;
+}
+
+
+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;
+ struct pthread_attr default_attr;
+ bool free_cpuset = false;
+ if (iattr == NULL)
+ {
+ lll_lock (__default_pthread_attr_lock, LLL_PRIVATE);
+ default_attr = __default_pthread_attr;
+ size_t cpusetsize = default_attr.cpusetsize;
+ if (cpusetsize > 0)
+ {
+ cpu_set_t *cpuset;
+ if (__glibc_likely (__libc_use_alloca (cpusetsize)))
+ cpuset = __alloca (cpusetsize);
+ else
+ {
+ cpuset = malloc (cpusetsize);
+ if (cpuset == NULL)
+ {
+ lll_unlock (__default_pthread_attr_lock, LLL_PRIVATE);
+ return ENOMEM;
+ }
+ free_cpuset = true;
+ }
+ memcpy (cpuset, default_attr.cpuset, cpusetsize);
+ default_attr.cpuset = cpuset;
+ }
+ lll_unlock (__default_pthread_attr_lock, LLL_PRIVATE);
+ iattr = &default_attr;
+ }
+
+ struct pthread *pd = NULL;
+ int err = ALLOCATE_STACK (iattr, &pd);
+ int retval = 0;
+
+ if (__glibc_unlikely (err != 0))
+ /* Something went wrong. Maybe a parameter of the attributes is
+ invalid or we could not allocate memory. Note we have to
+ translate error codes. */
+ {
+ retval = err == ENOMEM ? EAGAIN : err;
+ goto out;
+ }
+
+
+ /* 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;
+
+#if 1
+ _FPU_GETCW(pd->fpu_control_init);
+#endif
+
+ /* 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
+
+#warning scheduling parameters
+#if 0
+ /* Determine scheduling parameters for the thread. */
+ if (__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)
+ {
+ /* Perhaps a thread wants to change the IDs and if waiting
+ for this stillborn thread. */
+ if (__builtin_expect (atomic_exchange_acq (&pd->setxid_futex, 0)
+ == -2, 0))
+ lll_futex_wake (&pd->setxid_futex, 1, LLL_PRIVATE);
+
+ __deallocate_stack (pd);
+
+ retval = EINVAL;
+ goto out;
+ }
+ }
+#endif
+
+ /* Pass the descriptor to the caller. */
+ *newthread = (pthread_t) pd;
+
+ LIBC_PROBE (pthread_create, 4, newthread, attr, start_routine, arg);
+
+ /* Start the thread. */
+ retval = create_thread (pd, iattr, STACK_VARIABLES_ARGS);
+
+ out:
+ if (__glibc_unlikely (free_cpuset))
+ free (default_attr.cpuset);
+
+ return retval;
+}
+versioned_symbol (libpthread, __pthread_create_2_1, pthread_create, GLIBC_2_1);
+
+
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
+int
+__pthread_create_2_0 (newthread, attr, start_routine, arg)
+ pthread_t *newthread;
+ const pthread_attr_t *attr;
+ void *(*start_routine) (void *);
+ void *arg;
+{
+ /* The ATTR attribute is not really of type `pthread_attr_t *'. It has
+ the old size and access to the new members might crash the program.
+ We convert the struct now. */
+ struct pthread_attr new_attr;
+
+ if (attr != NULL)
+ {
+ struct pthread_attr *iattr = (struct pthread_attr *) attr;
+ size_t ps = __getpagesize ();
+
+ /* Copy values from the user-provided attributes. */
+ new_attr.schedparam = iattr->schedparam;
+ new_attr.schedpolicy = iattr->schedpolicy;
+ new_attr.flags = iattr->flags;
+
+ /* Fill in default values for the fields not present in the old
+ implementation. */
+ new_attr.guardsize = ps;
+ new_attr.stackaddr = NULL;
+ new_attr.stacksize = 0;
+ new_attr.cpuset = NULL;
+
+ /* We will pass this value on to the real implementation. */
+ attr = (pthread_attr_t *) &new_attr;
+ }
+
+ return __pthread_create_2_1 (newthread, attr, start_routine, arg);
+}
+compat_symbol (libpthread, __pthread_create_2_0, pthread_create,
+ GLIBC_2_0);
+#endif
+
+/* Information for libthread_db. */
+
+#include "../fbtl_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)
--- /dev/null
+++ b/fbtl/pthread_detach.c
@@ -0,0 +1,55 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl/pthread_equal.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP.h"
+
+
+int
+__pthread_equal (pthread_t thread1, pthread_t thread2)
+{
+ return thread1 == thread2;
+}
+strong_alias (__pthread_equal, pthread_equal)
--- /dev/null
+++ b/fbtl/pthread_exit.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include "pthreadP.h"
+
+
+void
+__pthread_exit (void *value)
+{
+ THREAD_SETMEM (THREAD_SELF, result, value);
+
+ __do_cancel ();
+}
+strong_alias (__pthread_exit, pthread_exit)
+
+/* After a thread terminates, __libc_start_main decrements
+ __nptl_nthreads defined in pthread_create.c. */
+PTHREAD_STATIC_FN_REQUIRE (pthread_create)
--- /dev/null
+++ b/fbtl/pthread_getattr_default_np.c
@@ -0,0 +1,37 @@
+/* Get the default attributes used by pthread_create in the process.
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <pthreadP.h>
+#include <assert.h>
+
+int
+pthread_getattr_default_np (pthread_attr_t *out)
+{
+ struct pthread_attr *real_out;
+
+ assert (sizeof (*out) >= sizeof (struct pthread_attr));
+ real_out = (struct pthread_attr *) out;
+
+ lll_lock (__default_pthread_attr_lock, LLL_PRIVATE);
+ *real_out = __default_pthread_attr;
+ lll_unlock (__default_pthread_attr_lock, LLL_PRIVATE);
+
+ return 0;
+}
--- /dev/null
+++ b/fbtl/pthread_getattr_np.c
@@ -0,0 +1,198 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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 (__glibc_likely (thread->stackblock != NULL))
+ {
+ 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. */
+
+ /* 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", "rce");
+ 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 consider the main process stack to have ended with
+ the page containing __libc_stack_end. There is stuff below
+ it in the stack too, like the program arguments, environment
+ variables and auxv info, but we ignore those pages when
+ returning size so that the output is consistent when the
+ stack is marked executable due to a loaded DSO requiring
+ it. */
+ void *stack_end = (void *) ((uintptr_t) __libc_stack_end
+ & -(uintptr_t) GLRO(dl_pagesize));
+#if _STACK_GROWS_DOWN
+ stack_end += GLRO(dl_pagesize);
+#endif
+ /* 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->stackaddr = stack_end;
+ iattr->stacksize =
+ rl.rlim_cur - (size_t) (to - (uintptr_t) stack_end);
+
+ /* Cut it down to align it to page size since otherwise we
+ risk going beyond rlimit when the kernel rounds up the
+ stack extension request. */
+ iattr->stacksize = (iattr->stacksize
+ & -(intptr_t) GLRO(dl_pagesize));
+
+ /* 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;
+#if 1
+#warning not yet pthread_getaffinity_np
+ ret = ENOSYS;
+#else
+ ret = __pthread_getaffinity_np (thread_id, size, cpuset);
+#endif
+ }
+ /* 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;
+}
--- /dev/null
+++ b/fbtl/pthread_getconcurrency.c
@@ -0,0 +1,26 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP.h"
+
+
+int
+pthread_getconcurrency (void)
+{
+ return __concurrency_level;
+}
--- /dev/null
+++ b/fbtl/pthread_getcpuclockid.c
@@ -0,0 +1,54 @@
+/* Copyright (C) 2000-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#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
+}
--- /dev/null
+++ b/fbtl/pthread_getschedparam.c
@@ -0,0 +1,72 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <string.h>
+#include "pthreadP.h"
+#include <lowlevellock.h>
+
+
+int
+__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)
--- /dev/null
+++ b/fbtl/pthread_getspecific.c
@@ -0,0 +1,67 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include "pthreadP.h"
+
+
+void *
+__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 (__glibc_likely (key < PTHREAD_KEY_2NDLEVEL_SIZE))
+ 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 (__glibc_unlikely (seq != __pthread_keys[key].seq))
+ result = data->data = NULL;
+ }
+
+ return result;
+}
+strong_alias (__pthread_getspecific, pthread_getspecific)
+hidden_def (__pthread_getspecific)
--- /dev/null
+++ b/fbtl/pthread_join.c
@@ -0,0 +1,117 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include <atomic.h>
+#include "pthreadP.h"
+
+#include <stap-probe.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;
+
+ LIBC_PROBE (pthread_join, 1, threadid);
+
+ /* 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->ktid);
+
+
+ /* Restore cancellation mode. */
+ CANCEL_RESET (oldtype);
+
+ /* Remove the handler. */
+ pthread_cleanup_pop (0);
+
+
+ if (__glibc_likely (result == 0))
+ {
+ /* 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);
+ }
+
+ LIBC_PROBE (pthread_join_ret, 3, threadid, result, pd->result);
+
+ return result;
+}
--- /dev/null
+++ b/fbtl/pthread_key_create.c
@@ -0,0 +1,51 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include "pthreadP.h"
+#include <atomic.h>
+
+
+int
+__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)
+hidden_def (__pthread_key_create)
--- /dev/null
+++ b/fbtl/pthread_key_delete.c
@@ -0,0 +1,41 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include "pthreadP.h"
+#include <atomic.h>
+
+
+int
+pthread_key_delete (pthread_key_t key)
+{
+ int result = EINVAL;
+
+ if (__glibc_likely (key < PTHREAD_KEYS_MAX))
+ {
+ 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;
+}
--- /dev/null
+++ b/fbtl/pthread_kill_other_threads.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <shlib-compat.h>
+
+
+#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)
+{
+}
+compat_symbol (libpthread, __pthread_kill_other_threads_np,
+ pthread_kill_other_threads_np, GLIBC_2_0);
+#endif
--- /dev/null
+++ b/fbtl/pthread_mutex_consistent.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 2005-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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)
--- /dev/null
+++ b/fbtl/pthread_mutex_destroy.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include "pthreadP.h"
+
+#include <stap-probe.h>
+
+
+int
+__pthread_mutex_destroy (pthread_mutex_t *mutex)
+{
+ LIBC_PROBE (mutex_destroy, 1, 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)
+hidden_def (__pthread_mutex_destroy)
--- /dev/null
+++ b/fbtl/pthread_mutex_getprioceiling.c
@@ -0,0 +1,35 @@
+/* Get current priority ceiling of pthread_mutex_t.
+ Copyright (C) 2006-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthreadP.h>
+
+
+int
+pthread_mutex_getprioceiling (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;
+}
--- /dev/null
+++ b/fbtl/pthread_mutex_init.c
@@ -0,0 +1,149 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <kernel-features.h>
+#include "pthreadP.h"
+
+#include <stap-probe.h>
+
+static const struct pthread_mutexattr default_mutexattr =
+ {
+ /* Default is a normal mutex, not shared between processes. */
+ .mutexkind = PTHREAD_MUTEX_NORMAL
+ };
+
+
+#ifndef __ASSUME_FUTEX_LOCK_PI
+static int tpi_supported;
+#endif
+
+
+int
+__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_mutexattr);
+
+ /* 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;
+#if 0
+ case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
+#ifndef __ASSUME_FUTEX_LOCK_PI
+ if (__glibc_unlikely (tpi_supported == 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 (__glibc_unlikely (tpi_supported < 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;
+#else
+ default:
+ return ENOTSUP;
+#endif
+ }
+
+ /* 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;
+
+#warning not supported protocols
+#if 0
+ 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;
+ }
+#endif
+ /* 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
+
+ LIBC_PROBE (mutex_init, 1, mutex);
+
+ return 0;
+}
+strong_alias (__pthread_mutex_init, pthread_mutex_init)
+hidden_def (__pthread_mutex_init)
--- /dev/null
+++ b/fbtl/pthread_mutex_lock.c
@@ -0,0 +1,504 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <not-cancel.h>
+#include "pthreadP.h"
+#include <lowlevellock.h>
+#include <stap-probe.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
+__pthread_mutex_lock (pthread_mutex_t *mutex)
+{
+ assert (sizeof (mutex->__size) >= sizeof (mutex->__data));
+
+ unsigned int type = PTHREAD_MUTEX_TYPE (mutex);
+
+ LIBC_PROBE (mutex_entry, 1, 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 (__glibc_unlikely (mutex->__data.__count + 1 == 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 (__glibc_unlikely (mutex->__data.__owner == id))
+ return EDEADLK;
+ goto simple;
+ }
+
+ /* Record the ownership. */
+ mutex->__data.__owner = id;
+#ifndef NO_INCR
+ ++mutex->__data.__nusers;
+#endif
+
+ LIBC_PROBE (mutex_acquired, 1, mutex);
+
+ return 0;
+}
+
+static int
+__pthread_mutex_lock_full (pthread_mutex_t *mutex)
+{
+#if 1
+ return EINVAL;
+#else
+ 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 (__glibc_unlikely ((oldval & FUTEX_TID_MASK) == id))
+ {
+ 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 (__glibc_unlikely (mutex->__data.__count + 1 == 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 (__glibc_unlikely ((oldval & FUTEX_TID_MASK) == id))
+ {
+ 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 (__glibc_unlikely (mutex->__data.__count + 1 == 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 (__glibc_unlikely (oldval & FUTEX_OWNER_DIED))
+ {
+ 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 (__glibc_unlikely (mutex->__data.__count + 1 == 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
+
+ LIBC_PROBE (mutex_acquired, 1, mutex);
+
+ return 0;
+#endif
+}
+#ifndef __pthread_mutex_lock
+strong_alias (__pthread_mutex_lock, pthread_mutex_lock)
+hidden_def (__pthread_mutex_lock)
+#endif
+
+
+#ifdef NO_INCR
+void
+internal_function
+__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
--- /dev/null
+++ b/fbtl/pthread_mutex_setprioceiling.c
@@ -0,0 +1,116 @@
+/* Set current priority ceiling of pthread_mutex_t.
+ Copyright (C) 2006-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdbool.h>
+#include <errno.h>
+#include <pthreadP.h>
+
+
+int
+pthread_mutex_setprioceiling (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;
+}
--- /dev/null
+++ b/fbtl/pthread_mutex_timedlock.c
@@ -0,0 +1,495 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <errno.h>
+#include <time.h>
+#include "pthreadP.h"
+#include <lowlevellock.h>
+#include <not-cancel.h>
+
+#include <stap-probe.h>
+
+
+int
+pthread_mutex_timedlock (pthread_mutex_t *mutex,
+ const struct timespec *abstime)
+{
+ int oldval;
+ pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
+ int result = 0;
+
+ LIBC_PROBE (mutex_timedlock_entry, 2, mutex, abstime);
+
+ /* 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 (__glibc_unlikely (mutex->__data.__count + 1 == 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 (__glibc_unlikely (mutex->__data.__owner == id))
+ 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;
+
+#if 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 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 (__glibc_unlikely ((oldval & FUTEX_TID_MASK) == id))
+ {
+ 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 (__glibc_unlikely (mutex->__data.__count + 1 == 0))
+ /* Overflow of the counter. */
+ return EAGAIN;
+
+ ++mutex->__data.__count;
+
+ LIBC_PROBE (mutex_timedlock_acquired, 1, mutex);
+
+ 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 (__glibc_unlikely ((oldval & FUTEX_TID_MASK) == id))
+ {
+ 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 (__glibc_unlikely (mutex->__data.__count + 1 == 0))
+ /* Overflow of the counter. */
+ return EAGAIN;
+
+ ++mutex->__data.__count;
+
+ LIBC_PROBE (mutex_timedlock_acquired, 1, mutex);
+
+ 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 (__glibc_unlikely (oldval & FUTEX_OWNER_DIED))
+ {
+ 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 (__glibc_unlikely (mutex->__data.__count + 1 == 0))
+ /* Overflow of the counter. */
+ return EAGAIN;
+
+ ++mutex->__data.__count;
+
+ LIBC_PROBE (mutex_timedlock_acquired, 1, mutex);
+
+ 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;
+#endif
+ default:
+ /* Correct code cannot set any other type. */
+ return EINVAL;
+ }
+
+ if (result == 0)
+ {
+ /* Record the ownership. */
+ mutex->__data.__owner = id;
+ ++mutex->__data.__nusers;
+
+ LIBC_PROBE (mutex_timedlock_acquired, 1, mutex);
+ }
+
+ out:
+ return result;
+}
--- /dev/null
+++ b/fbtl/pthread_mutex_trylock.c
@@ -0,0 +1,380 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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 (__glibc_unlikely (mutex->__data.__count + 1 == 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;
+#if 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 (__glibc_unlikely ((oldval & FUTEX_TID_MASK) == id))
+ {
+ 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 (__glibc_unlikely (mutex->__data.__count + 1 == 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 (__glibc_unlikely ((oldval & FUTEX_TID_MASK) == id))
+ {
+ 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 (__glibc_unlikely (mutex->__data.__count + 1 == 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 (__glibc_unlikely (oldval & FUTEX_OWNER_DIED))
+ {
+ 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 (__glibc_unlikely (mutex->__data.__count + 1 == 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;
+#endif
+ default:
+ /* Correct code cannot set any other type. */
+ return EINVAL;
+ }
+
+ return EBUSY;
+}
+strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock)
--- /dev/null
+++ b/fbtl/pthread_mutex_unlock.c
@@ -0,0 +1,312 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include "pthreadP.h"
+#include <lowlevellock.h>
+#include <stap-probe.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));
+
+ LIBC_PROBE (mutex_release, 1, 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)
+{
+#if 1
+ return EINVAL;
+#else
+ 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. Load all necessary mutex data before releasing the mutex
+ to not violate the mutex destruction requirements (see
+ lll_unlock). */
+ int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
+ int private = (robust
+ ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex)
+ : PTHREAD_MUTEX_PSHARED (mutex));
+ /* Unlock the mutex using a CAS unless there are futex waiters or our
+ TID is not the value of __lock anymore, in which case we let the
+ kernel take care of the situation. Use release MO in the CAS to
+ synchronize with acquire MO in lock acquisitions. */
+ int l = atomic_load_relaxed (&mutex->__data.__lock);
+ do
+ {
+ if (((l & FUTEX_WAITERS) != 0)
+ || (l != THREAD_GETMEM (THREAD_SELF, tid)))
+ {
+ INTERNAL_SYSCALL_DECL (__err);
+ INTERNAL_SYSCALL (futex, __err, 2, &mutex->__data.__lock,
+ __lll_private_flag (FUTEX_UNLOCK_PI, private));
+ break;
+ }
+ }
+ while (!atomic_compare_exchange_weak_release (&mutex->__data.__lock,
+ &l, 0));
+
+ 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;
+
+ LIBC_PROBE (mutex_release, 1, mutex);
+
+ return __pthread_tpp_change_priority (oldprio, -1);
+
+ default:
+ /* Correct code cannot set any other type. */
+ return EINVAL;
+ }
+
+ LIBC_PROBE (mutex_release, 1, mutex);
+ return 0;
+#endif
+}
+
+
+int
+__pthread_mutex_unlock (pthread_mutex_t *mutex)
+{
+ return __pthread_mutex_unlock_usercnt (mutex, 1);
+}
+strong_alias (__pthread_mutex_unlock, pthread_mutex_unlock)
+hidden_def (__pthread_mutex_unlock)
--- /dev/null
+++ b/fbtl/pthread_mutexattr_destroy.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthreadP.h>
+
+
+int
+__pthread_mutexattr_destroy (pthread_mutexattr_t *attr)
+{
+ return 0;
+}
+strong_alias (__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
--- /dev/null
+++ b/fbtl/pthread_mutexattr_getprioceiling.c
@@ -0,0 +1,46 @@
+/* Get priority ceiling setting from pthread_mutexattr_t.
+ Copyright (C) 2006-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl/pthread_mutexattr_getprotocol.c
@@ -0,0 +1,34 @@
+/* Get priority protocol setting from pthread_mutexattr_t.
+ Copyright (C) 2006-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl/pthread_mutexattr_getpshared.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl/pthread_mutexattr_getrobust.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 2005-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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)
--- /dev/null
+++ b/fbtl/pthread_mutexattr_gettype.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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)
--- /dev/null
+++ b/fbtl/pthread_mutexattr_init.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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)
--- /dev/null
+++ b/fbtl/pthread_mutexattr_setprioceiling.c
@@ -0,0 +1,44 @@
+/* Change priority ceiling setting in pthread_mutexattr_t.
+ Copyright (C) 2006-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl/pthread_mutexattr_setprotocol.c
@@ -0,0 +1,38 @@
+/* Change priority protocol setting in pthread_mutexattr_t.
+ Copyright (C) 2006-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl/pthread_mutexattr_setpshared.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl/pthread_mutexattr_setrobust.c
@@ -0,0 +1,41 @@
+/* Copyright (C) 2005-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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)
--- /dev/null
+++ b/fbtl/pthread_mutexattr_settype.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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)
--- /dev/null
+++ b/fbtl/pthread_once.c
@@ -0,0 +1,54 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP.h"
+#include <lowlevellock.h>
+
+
+
+static int once_lock = LLL_LOCK_INITIALIZER;
+
+
+int
+__pthread_once (once_control, init_routine)
+ pthread_once_t *once_control;
+ void (*init_routine) (void);
+{
+ /* XXX Depending on whether the LOCK_IN_ONCE_T is defined use a
+ global lock variable or one which is part of the pthread_once_t
+ object. */
+ if (*once_control == PTHREAD_ONCE_INIT)
+ {
+ lll_lock (once_lock, 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)
+hidden_def (__pthread_once)
--- /dev/null
+++ b/fbtl/pthread_rwlock_destroy.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP.h"
+#include <stap-probe.h>
+
+
+int
+__pthread_rwlock_destroy (pthread_rwlock_t *rwlock)
+{
+ LIBC_PROBE (rwlock_destroy, 1, rwlock);
+
+ /* Nothing to be done. For now. */
+ return 0;
+}
+strong_alias (__pthread_rwlock_destroy, pthread_rwlock_destroy)
--- /dev/null
+++ b/fbtl/pthread_rwlock_init.c
@@ -0,0 +1,72 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP.h"
+#include <string.h>
+#include <kernel-features.h>
+
+
+static const struct pthread_rwlockattr default_rwlockattr =
+ {
+ .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_rwlockattr;
+
+ 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)
--- /dev/null
+++ b/fbtl/pthread_rwlock_rdlock.c
@@ -0,0 +1,99 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <sysdep.h>
+#include <lowlevellock.h>
+#include <pthread.h>
+#include <pthreadP.h>
+#include <stap-probe.h>
+
+
+/* Acquire read lock for RWLOCK. */
+int
+__pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
+{
+ int result = 0;
+
+ LIBC_PROBE (rdlock_entry, 1, rwlock);
+
+ /* Make sure we are alone. */
+ 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 (__glibc_unlikely (++rwlock->__data.__nr_readers == 0))
+ {
+ /* Overflow on number of readers. */
+ --rwlock->__data.__nr_readers;
+ result = EAGAIN;
+ }
+ else
+ LIBC_PROBE (rdlock_acquire_read, 1, rwlock);
+
+ 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 (__glibc_unlikely (++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. */
+ 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)
+hidden_def (__pthread_rwlock_rdlock)
--- /dev/null
+++ b/fbtl/pthread_rwlock_timedrdlock.c
@@ -0,0 +1,154 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <sysdep.h>
+#include <lowlevellock.h>
+#include <pthread.h>
+#include <pthreadP.h>
+#include <sys/time.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 alone. */
+ 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;
+ }
+
+ /* Work around the fact that the kernel rejects negative timeout values
+ despite them being valid. */
+ if (__glibc_unlikely (abstime->tv_sec < 0))
+ {
+ result = ETIMEDOUT;
+ break;
+ }
+
+#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \
+ || !defined lll_futex_timed_wait_bitset)
+ /* 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;
+ }
+#endif
+
+ /* 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. */
+#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \
+ || !defined lll_futex_timed_wait_bitset)
+ err = lll_futex_timed_wait (&rwlock->__data.__readers_wakeup,
+ waitval, &rt, rwlock->__data.__shared);
+#else
+ err = lll_futex_timed_wait_bitset (&rwlock->__data.__readers_wakeup,
+ waitval, abstime,
+ FUTEX_CLOCK_REALTIME,
+ rwlock->__data.__shared);
+#endif
+
+ /* 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;
+}
--- /dev/null
+++ b/fbtl/pthread_rwlock_timedwrlock.c
@@ -0,0 +1,145 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <sysdep.h>
+#include <lowlevellock.h>
+#include <pthread.h>
+#include <pthreadP.h>
+#include <sys/time.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 alone. */
+ 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;
+ }
+
+ /* Work around the fact that the kernel rejects negative timeout values
+ despite them being valid. */
+ if (__glibc_unlikely (abstime->tv_sec < 0))
+ {
+ result = ETIMEDOUT;
+ break;
+ }
+
+#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \
+ || !defined lll_futex_timed_wait_bitset)
+ /* 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;
+ }
+#endif
+
+ /* 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. */
+#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \
+ || !defined lll_futex_timed_wait_bitset)
+ err = lll_futex_timed_wait (&rwlock->__data.__writer_wakeup,
+ waitval, &rt, rwlock->__data.__shared);
+#else
+ err = lll_futex_timed_wait_bitset (&rwlock->__data.__writer_wakeup,
+ waitval, abstime,
+ FUTEX_CLOCK_REALTIME,
+ rwlock->__data.__shared);
+#endif
+
+ /* 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;
+}
--- /dev/null
+++ b/fbtl/pthread_rwlock_tryrdlock.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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 (__glibc_unlikely (++rwlock->__data.__nr_readers == 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)
--- /dev/null
+++ b/fbtl/pthread_rwlock_trywrlock.c
@@ -0,0 +1,41 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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)
--- /dev/null
+++ b/fbtl/pthread_rwlock_unlock.c
@@ -0,0 +1,61 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <sysdep.h>
+#include <lowlevellock.h>
+#include <pthread.h>
+#include <pthreadP.h>
+#include <stap-probe.h>
+
+/* Unlock RWLOCK. */
+int
+__pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
+{
+ LIBC_PROBE (rwlock_unlock, 1, 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)
+hidden_def (__pthread_rwlock_unlock)
--- /dev/null
+++ b/fbtl/pthread_rwlock_wrlock.c
@@ -0,0 +1,91 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <sysdep.h>
+#include <lowlevellock.h>
+#include <pthread.h>
+#include <pthreadP.h>
+#include <stap-probe.h>
+
+
+/* Acquire write lock for RWLOCK. */
+int
+__pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
+{
+ int result = 0;
+
+ LIBC_PROBE (wrlock_entry, 1, rwlock);
+
+ /* Make sure we are alone. */
+ 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);
+
+ LIBC_PROBE (wrlock_acquire_write, 1, rwlock);
+ 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)
+hidden_def (__pthread_rwlock_wrlock)
--- /dev/null
+++ b/fbtl/pthread_rwlockattr_destroy.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP.h"
+
+
+int
+pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr)
+{
+ /* Nothing to do. For now. */
+
+ return 0;
+}
--- /dev/null
+++ b/fbtl/pthread_rwlockattr_getkind_np.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP.h"
+
+
+int
+pthread_rwlockattr_getkind_np (const pthread_rwlockattr_t *attr, int *pref)
+{
+ *pref = ((const struct pthread_rwlockattr *) attr)->lockkind;
+
+ return 0;
+}
--- /dev/null
+++ b/fbtl/pthread_rwlockattr_getpshared.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP.h"
+
+
+int
+pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr, int *pshared)
+{
+ *pshared = ((const struct pthread_rwlockattr *) attr)->pshared;
+
+ return 0;
+}
--- /dev/null
+++ b/fbtl/pthread_rwlockattr_init.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl/pthread_rwlockattr_setkind_np.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl/pthread_rwlockattr_setpshared.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl/pthread_self.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP.h"
+#include <tls.h>
+
+
+pthread_t
+__pthread_self (void)
+{
+ return (pthread_t) THREAD_SELF;
+}
+strong_alias (__pthread_self, pthread_self)
--- /dev/null
+++ b/fbtl/pthread_setattr_default_np.c
@@ -0,0 +1,116 @@
+/* Set the default attributes to be used by pthread_create in the process.
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <pthreadP.h>
+#include <assert.h>
+#include <string.h>
+
+int
+pthread_setattr_default_np (const pthread_attr_t *in)
+{
+ const struct pthread_attr *real_in;
+ struct pthread_attr attrs;
+ int ret;
+
+ assert (sizeof (*in) >= sizeof (struct pthread_attr));
+ real_in = (struct pthread_attr *) in;
+
+#if 1
+#warning scheduling attributes not yet supported
+#else
+
+ /* Catch invalid values. */
+ int policy = real_in->schedpolicy;
+ ret = check_sched_policy_attr (policy);
+ if (ret)
+ return ret;
+
+ const struct sched_param *param = &real_in->schedparam;
+ if (param->sched_priority > 0)
+ {
+ ret = check_sched_priority_attr (param->sched_priority, policy);
+ if (ret)
+ return ret;
+ }
+
+ ret = check_cpuset_attr (real_in->cpuset, real_in->cpusetsize);
+ if (ret)
+ return ret;
+#endif
+
+ /* stacksize == 0 is fine. It means that we don't change the current
+ value. */
+ if (real_in->stacksize != 0)
+ {
+ ret = check_stacksize_attr (real_in->stacksize);
+ if (ret)
+ return ret;
+ }
+
+ /* Having a default stack address is wrong. */
+ if (real_in->flags & ATTR_FLAG_STACKADDR)
+ return EINVAL;
+
+ attrs = *real_in;
+
+ /* Now take the lock because we start writing into
+ __default_pthread_attr. */
+ lll_lock (__default_pthread_attr_lock, LLL_PRIVATE);
+
+ /* Free the cpuset if the input is 0. Otherwise copy in the cpuset
+ contents. */
+ size_t cpusetsize = attrs.cpusetsize;
+ if (cpusetsize == 0)
+ {
+ free (__default_pthread_attr.cpuset);
+ __default_pthread_attr.cpuset = NULL;
+ }
+ else if (cpusetsize == __default_pthread_attr.cpusetsize)
+ {
+ attrs.cpuset = __default_pthread_attr.cpuset;
+ memcpy (attrs.cpuset, real_in->cpuset, cpusetsize);
+ }
+ else
+ {
+ /* This may look wrong at first sight, but it isn't. We're freeing
+ __default_pthread_attr.cpuset and allocating to attrs.cpuset because
+ we'll copy over all of attr to __default_pthread_attr later. */
+ cpu_set_t *newp = realloc (__default_pthread_attr.cpuset,
+ cpusetsize);
+
+ if (newp == NULL)
+ {
+ ret = ENOMEM;
+ goto out;
+ }
+
+ attrs.cpuset = newp;
+ memcpy (attrs.cpuset, real_in->cpuset, cpusetsize);
+ }
+
+ /* We don't want to accidentally set the default stacksize to zero. */
+ if (attrs.stacksize == 0)
+ attrs.stacksize = __default_pthread_attr.stacksize;
+ __default_pthread_attr = attrs;
+
+ out:
+ lll_unlock (__default_pthread_attr_lock, LLL_PRIVATE);
+ return ret;
+}
--- /dev/null
+++ b/fbtl/pthread_setcancelstate.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include "pthreadP.h"
+#include <atomic.h>
+
+
+int
+__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 (__glibc_likely (curval == oldval))
+ {
+ 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)
+hidden_def (__pthread_setcancelstate)
--- /dev/null
+++ b/fbtl/pthread_setcanceltype.c
@@ -0,0 +1,73 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include "pthreadP.h"
+#include <atomic.h>
+
+
+int
+__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 (__glibc_likely (curval == oldval))
+ {
+ 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)
--- /dev/null
+++ b/fbtl/pthread_setconcurrency.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl/pthread_setegid.c
@@ -0,0 +1,3 @@
+#define SINGLE_THREAD
+#define setegid pthread_setegid_np
+#include <setegid.c>
--- /dev/null
+++ b/fbtl/pthread_seteuid.c
@@ -0,0 +1,3 @@
+#define SINGLE_THREAD
+#define seteuid pthread_seteuid_np
+#include <seteuid.c>
--- /dev/null
+++ b/fbtl/pthread_setgid.c
@@ -0,0 +1,3 @@
+#define SINGLE_THREAD
+#define __setgid pthread_setgid_np
+#include <setgid.c>
--- /dev/null
+++ b/fbtl/pthread_setregid.c
@@ -0,0 +1,3 @@
+#define SINGLE_THREAD
+#define __setregid pthread_setregid_np
+#include <setregid.c>
--- /dev/null
+++ b/fbtl/pthread_setresgid.c
@@ -0,0 +1,3 @@
+#define SINGLE_THREAD
+#define __setresgid pthread_setresgid_np
+#include <setresgid.c>
--- /dev/null
+++ b/fbtl/pthread_setresuid.c
@@ -0,0 +1,3 @@
+#define SINGLE_THREAD
+#define __setresuid pthread_setresuid_np
+#include <setresuid.c>
--- /dev/null
+++ b/fbtl/pthread_setreuid.c
@@ -0,0 +1,3 @@
+#define SINGLE_THREAD
+#define __setreuid pthread_setreuid_np
+#include <setreuid.c>
--- /dev/null
+++ b/fbtl/pthread_setschedparam.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <sched.h>
+#include <string.h>
+#include "pthreadP.h"
+#include <lowlevellock.h>
+
+
+int
+__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)
--- /dev/null
+++ b/fbtl/pthread_setschedprio.c
@@ -0,0 +1,63 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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 (__glibc_unlikely (sched_setparam (pd->tid, ¶m) == -1))
+ 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;
+}
--- /dev/null
+++ b/fbtl/pthread_setspecific.c
@@ -0,0 +1,93 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdlib.h>
+#include "pthreadP.h"
+
+
+int
+__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 (__glibc_likely (key < PTHREAD_KEY_2NDLEVEL_SIZE))
+ {
+ /* 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)
+hidden_def (__pthread_setspecific)
--- /dev/null
+++ b/fbtl/pthread_setuid.c
@@ -0,0 +1,3 @@
+#define SINGLE_THREAD
+#define __setuid pthread_setuid_np
+#include <setuid.c>
--- /dev/null
+++ b/fbtl/pthread_spin_destroy.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP.h"
+
+
+int
+pthread_spin_destroy (pthread_spinlock_t *lock)
+{
+ /* Nothing to do. */
+ return 0;
+}
--- /dev/null
+++ b/fbtl/pthread_spin_init.c
@@ -0,0 +1,27 @@
+/* pthread_spin_init -- initialize a spin lock. Generic version.
+ Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP.h"
+
+int
+pthread_spin_init (pthread_spinlock_t *lock, int pshared)
+{
+ *lock = 0;
+ return 0;
+}
--- /dev/null
+++ b/fbtl/pthread_spin_lock.c
@@ -0,0 +1,69 @@
+/* pthread_spin_lock -- lock a spin lock. Generic version.
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <atomic.h>
+#include "pthreadP.h"
+
+/* A machine-specific version can define SPIN_LOCK_READS_BETWEEN_CMPXCHG
+ to the number of plain reads that it's optimal to spin on between uses
+ of atomic_compare_and_exchange_val_acq. If spinning forever is optimal
+ then use -1. If no plain reads here would ever be optimal, use 0. */
+#ifndef SPIN_LOCK_READS_BETWEEN_CMPXCHG
+# warning machine-dependent file should define SPIN_LOCK_READS_BETWEEN_CMPXCHG
+# define SPIN_LOCK_READS_BETWEEN_CMPXCHG 1000
+#endif
+
+int
+pthread_spin_lock (pthread_spinlock_t *lock)
+{
+ /* atomic_exchange usually takes less instructions than
+ atomic_compare_and_exchange. On the other hand,
+ atomic_compare_and_exchange potentially generates less bus traffic
+ when the lock is locked.
+ We assume that the first try mostly will be successful, and we use
+ atomic_exchange. For the subsequent tries we use
+ atomic_compare_and_exchange. */
+ if (atomic_exchange_acq (lock, 1) == 0)
+ return 0;
+
+ do
+ {
+ /* The lock is contended and we need to wait. Going straight back
+ to cmpxchg is not a good idea on many targets as that will force
+ expensive memory synchronizations among processors and penalize other
+ running threads.
+ On the other hand, we do want to update memory state on the local core
+ once in a while to avoid spinning indefinitely until some event that
+ will happen to update local memory as a side-effect. */
+ if (SPIN_LOCK_READS_BETWEEN_CMPXCHG >= 0)
+ {
+ int wait = SPIN_LOCK_READS_BETWEEN_CMPXCHG;
+
+ while (*lock != 0 && wait > 0)
+ --wait;
+ }
+ else
+ {
+ while (*lock != 0)
+ ;
+ }
+ }
+ while (atomic_compare_and_exchange_val_acq (lock, 1, 0) != 0);
+
+ return 0;
+}
--- /dev/null
+++ b/fbtl/pthread_spin_trylock.c
@@ -0,0 +1,27 @@
+/* pthread_spin_trylock -- trylock a spin lock. Generic version.
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <atomic.h>
+#include "pthreadP.h"
+
+int
+pthread_spin_trylock (pthread_spinlock_t *lock)
+{
+ return atomic_exchange_acq (lock, 1) ? EBUSY : 0;
+}
--- /dev/null
+++ b/fbtl/pthread_spin_unlock.c
@@ -0,0 +1,29 @@
+/* pthread_spin_unlock -- unlock a spin lock. Generic version.
+ Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP.h"
+#include <atomic.h>
+
+int
+pthread_spin_unlock (pthread_spinlock_t *lock)
+{
+ atomic_full_barrier ();
+ *lock = 0;
+ return 0;
+}
--- /dev/null
+++ b/fbtl/pthread_testcancel.c
@@ -0,0 +1,27 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include "pthreadP.h"
+
+
+void
+pthread_testcancel (void)
+{
+ CANCELLATION_P (THREAD_SELF);
+}
--- /dev/null
+++ b/fbtl/pthread_timedjoin.c
@@ -0,0 +1,104 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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->ktid, 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;
+}
--- /dev/null
+++ b/fbtl/pthread_tryjoin.c
@@ -0,0 +1,72 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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 != KTID_TERMINATED)
+ 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;
+}
--- /dev/null
+++ b/fbtl/res.c
@@ -0,0 +1,26 @@
+/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <features.h>
+#include <resolv.h>
+#include <tls.h>
+
+struct __res_state *
+__res_state (void)
+{
+ return __resp;
+}
--- /dev/null
+++ b/fbtl/sem_close.c
@@ -0,0 +1,79 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl/sem_destroy.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <semaphore.h>
+#include <shlib-compat.h>
+#include "semaphoreP.h"
+
+
+int
+__new_sem_destroy (sem_t *sem)
+{
+ /* XXX Check for valid parameter. */
+
+ /* Nothing to do. */
+ return 0;
+}
+versioned_symbol (libpthread, __new_sem_destroy, sem_destroy, GLIBC_2_1);
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
+strong_alias (__new_sem_destroy, __old_sem_destroy)
+compat_symbol (libpthread, __old_sem_destroy, sem_destroy, GLIBC_2_0);
+#endif
--- /dev/null
+++ b/fbtl/sem_getvalue.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <semaphore.h>
+#include <shlib-compat.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;
+}
+versioned_symbol (libpthread, __new_sem_getvalue, sem_getvalue, GLIBC_2_1);
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
+strong_alias (__new_sem_getvalue, __old_sem_getvalue)
+compat_symbol (libpthread, __old_sem_getvalue, sem_getvalue, GLIBC_2_0);
+#endif
--- /dev/null
+++ b/fbtl/sem_init.c
@@ -0,0 +1,81 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <semaphore.h>
+#include <lowlevellock.h>
+#include <shlib-compat.h>
+#include "semaphoreP.h"
+#include <kernel-features.h>
+
+
+int
+__new_sem_init (sem_t *sem, int pshared, unsigned int value)
+{
+ /* Parameter sanity check. */
+ if (__glibc_unlikely (value > SEM_VALUE_MAX))
+ {
+ __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;
+}
+versioned_symbol (libpthread, __new_sem_init, sem_init, GLIBC_2_1);
+
+
+
+#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
+int
+attribute_compat_text_section
+__old_sem_init (sem_t *sem, int pshared, unsigned int value)
+{
+ /* Parameter sanity check. */
+ if (__glibc_unlikely (value > SEM_VALUE_MAX))
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ /* Map to the internal type. */
+ struct old_sem *isem = (struct old_sem *) sem;
+
+ /* Use the value the user provided. */
+ isem->value = value;
+
+ /* We cannot store the PSHARED attribute. So we always use the
+ operations needed for shared semaphores. */
+
+ return 0;
+}
+compat_symbol (libpthread, __old_sem_init, sem_init, GLIBC_2_0);
+#endif
--- /dev/null
+++ b/fbtl/sem_open.c
@@ -0,0 +1,300 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <fcntl.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 "semaphoreP.h"
+#include <shm-directory.h>
+
+
+/* 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. */
+ struct stat64 st;
+ if (__fxstat64 (_STAT_VER, fd, &st) == 0)
+ {
+ /* 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. */
+ int saved_errno = errno;
+ munmap(existing, sizeof (sem_t));
+ errno = saved_errno;
+ }
+
+ return result;
+}
+
+
+sem_t *
+sem_open (const char *name, int oflag, ...)
+{
+ int fd;
+ sem_t *result;
+
+ /* Create the name of the final file in local variable SHM_NAME. */
+ SHM_GET_NAME (EINVAL, SEM_FAILED, SEM_SHM_PREFIX);
+
+ /* If the semaphore object has to exist simply open it. */
+ if ((oflag & O_CREAT) == 0 || (oflag & O_EXCL) == 0)
+ {
+ try_again:
+ fd = __libc_open (shm_name,
+ (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);
+
+#if 0
+ mode = va_arg (ap, mode_t);
+#else
+ mode = va_arg (ap, int);
+#endif
+ 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 (shm_dirlen + sizeof SEM_SHM_PREFIX + 6);
+ char *xxxxxx = __mempcpy (tmpfname, shm_dir, shm_dirlen);
+
+ int retries = 0;
+#define NRETRIES 50
+ while (1)
+ {
+ /* Add the suffix for mktemp. */
+ strcpy (xxxxxx, "XXXXXX");
+
+ /* We really want to use mktemp here. We cannot use mkstemp
+ since the file must be opened with a specific mode. The
+ mode cannot later be set since then we cannot apply the
+ file create mask. */
+ if (__mktemp (tmpfname) == NULL)
+ return SEM_FAILED;
+
+ /* Open the file. Make sure we do not overwrite anything. */
+ fd = __libc_open (tmpfname, O_RDWR | O_CREAT | O_EXCL, mode);
+ if (fd == -1)
+ {
+ if (errno == EEXIST)
+ {
+ if (++retries < NRETRIES)
+ continue;
+
+ __set_errno (EAGAIN);
+ }
+
+ return SEM_FAILED;
+ }
+
+ /* We got a file. */
+ break;
+ }
+
+ 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, shm_name) != 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. */
+ int save = errno;
+ __libc_close (fd);
+ errno = save;
+ }
+
+ return result;
+}
--- /dev/null
+++ b/fbtl/sem_unlink.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <semaphore.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "semaphoreP.h"
+#include <shm-directory.h>
+
+int
+sem_unlink (const char *name)
+{
+ /* Construct the filename. */
+ SHM_GET_NAME (ENOENT, -1, SEM_SHM_PREFIX);
+
+ /* Now try removing it. */
+ int ret = unlink (shm_name);
+ if (ret < 0 && errno == EPERM)
+ __set_errno (EACCES);
+ return ret;
+}
--- /dev/null
+++ b/fbtl/semaphore.h
@@ -0,0 +1,78 @@
+/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#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) __THROWNL;
+
+/* Post SEM. */
+extern int sem_post (sem_t *__sem) __THROWNL;
+
+/* 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 */
--- /dev/null
+++ b/fbtl/semaphoreP.h
@@ -0,0 +1,54 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <semaphore.h>
+#include "pthreadP.h"
+
+#define SEM_SHM_PREFIX "sem."
+
+/* Keeping track of currently used mappings. */
+struct inuse_sem
+{
+ dev_t dev;
+ ino_t ino;
+ int refcnt;
+ sem_t *sem;
+ char name[0];
+};
+
+
+/* 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;
+
+
+/* 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);
--- /dev/null
+++ b/fbtl/shlib-versions
@@ -0,0 +1 @@
+libpthread=0 GLIBC_2.3
--- /dev/null
+++ b/fbtl/sigaction.c
@@ -0,0 +1,43 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+
+/* This is no complete implementation. The file is meant to be
+ included in the real implementation to provide the wrapper around
+ __libc_sigaction. */
+
+#include <fbtl/pthreadP.h>
+
+/* We use the libc implementation but we tell it to not allow
+ SIGCANCEL or SIGTIMER to be handled. */
+#define LIBC_SIGACTION 1
+
+
+int
+__sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
+{
+ if (__glibc_unlikely (sig == SIGCANCEL || sig == SIGSETXID))
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ return __libc_sigaction (sig, act, oact);
+}
+libc_hidden_weak (__sigaction)
+weak_alias (__sigaction, sigaction)
--- /dev/null
+++ b/fbtl/sockperf.c
@@ -0,0 +1,594 @@
+#define _GNU_SOURCE
+#include <argp.h>
+#include <complex.h>
+#include <errno.h>
+#include <error.h>
+#include <fcntl.h>
+#include <gd.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+
+#define size_x 320
+#define size_y 240
+
+
+#define PATH "/tmp/s.sockperf"
+
+
+struct thread_param
+{
+ unsigned int from;
+ unsigned int to;
+ unsigned int nserv;
+};
+
+struct coord
+{
+ unsigned int x;
+ unsigned int y;
+ complex double z;
+};
+
+
+/* We use 64bit values for the times. */
+typedef unsigned long long int hp_timing_t;
+
+
+static unsigned int nclients = 2;
+static unsigned int nservers = 2;
+
+static bool timing;
+static int points;
+
+
+static complex double top_left = -0.7 + 0.2i;
+static complex double bottom_right = -0.5 - 0.0i;
+
+
+static int colors[256];
+static gdImagePtr image;
+static pthread_mutex_t image_lock;
+
+static int sock;
+
+
+static void *
+client (void *arg)
+{
+ struct thread_param *param = arg;
+ unsigned int cnt;
+ unsigned int nserv = param->nserv;
+ int clisock[nserv];
+ struct pollfd servpoll[nserv];
+ struct sockaddr_un servaddr;
+ socklen_t servlen;
+ struct coord c;
+
+ bool new_coord (void)
+ {
+ if (cnt >= param->to)
+ return false;
+
+ unsigned int row = cnt / size_x;
+ unsigned int col = cnt % size_x;
+
+ c.x = col;
+ c.y = row;
+ c.z = (top_left
+ + ((col
+ * (creal (bottom_right) - creal (top_left))) / size_x)
+ + (_Complex_I * (row * (cimag (bottom_right) - cimag (top_left)))
+ / size_y));
+
+ ++cnt;
+
+ return true;
+ }
+
+
+ for (cnt = 0; cnt < nserv; ++cnt)
+ {
+ servpoll[cnt].fd = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (clisock < 0)
+ {
+ puts ("cannot create socket in client");
+ return NULL;
+ }
+
+ memset (&servaddr, '\0', sizeof (servaddr));
+ servaddr.sun_family = AF_UNIX;
+ strncpy (servaddr.sun_path, PATH, sizeof (servaddr.sun_path));
+ servlen = offsetof (struct sockaddr_un, sun_path) + strlen (PATH) + 1;
+
+
+ int err;
+ while (1)
+ {
+ err = TEMP_FAILURE_RETRY (connect (servpoll[cnt].fd, &servaddr,
+ servlen));
+ if (err != -1 || errno != ECONNREFUSED)
+ break;
+
+ pthread_yield ();
+ }
+
+ if (err == -1)
+ {
+ printf ("cannot connect: %m (%d)\n", errno);
+ exit (1);
+ }
+
+ servpoll[cnt].events = POLLOUT;
+ servpoll[cnt].revents = 0;
+ }
+
+ cnt = param->from;
+
+ new_coord ();
+ bool z_valid = true;
+
+ while (1)
+ {
+ int i;
+ int n = poll (servpoll, nserv, -1);
+ if (n == -1)
+ {
+ puts ("poll returned error");
+ break;
+ }
+
+ bool cont = false;
+ for (i = 0; i < nserv && n > 0; ++i)
+ if (servpoll[i].revents != 0)
+ {
+ if (servpoll[i].revents == POLLIN)
+ {
+ unsigned int vals[3];
+ if (TEMP_FAILURE_RETRY (read (servpoll[i].fd, &vals,
+ sizeof (vals)))
+ != sizeof (vals))
+ {
+ puts ("read error in client");
+ return NULL;
+ }
+
+ pthread_mutex_lock (&image_lock);
+
+ gdImageSetPixel (image, vals[0], vals[1], vals[2]);
+ ++points;
+
+ pthread_mutex_unlock (&image_lock);
+
+ servpoll[i].events = POLLOUT;
+ }
+ else
+ {
+ if (servpoll[i].revents != POLLOUT)
+ printf ("revents: %hd != POLLOUT ???\n",
+ servpoll[i].revents);
+
+ if (z_valid)
+ {
+ if (TEMP_FAILURE_RETRY (write (servpoll[i].fd, &c,
+ sizeof (c))) != sizeof (c))
+ {
+ puts ("write error in client");
+ return NULL;
+ }
+ cont = true;
+ servpoll[i].events = POLLIN;
+
+ z_valid = new_coord ();
+ if (! z_valid)
+ /* No more to do. Clear the event fields. */
+ for (i = 0; i < nserv; ++i)
+ if (servpoll[i].events == POLLOUT)
+ servpoll[i].events = servpoll[i].revents = 0;
+ }
+ else
+ servpoll[i].events = servpoll[i].revents = 0;
+ }
+
+ --n;
+ }
+ else if (servpoll[i].events != 0)
+ cont = true;
+
+ if (! cont && ! z_valid)
+ break;
+ }
+
+ c.x = 0xffffffff;
+ c.y = 0xffffffff;
+ for (cnt = 0; cnt < nserv; ++cnt)
+ {
+ TEMP_FAILURE_RETRY (write (servpoll[cnt].fd, &c, sizeof (c)));
+ close (servpoll[cnt].fd);
+ }
+
+ return NULL;
+}
+
+
+static void *
+server (void *arg)
+{
+ struct sockaddr_un cliaddr;
+ socklen_t clilen;
+ int clisock = TEMP_FAILURE_RETRY (accept (sock, &cliaddr, &clilen));
+
+ if (clisock == -1)
+ {
+ puts ("accept failed");
+ return NULL;
+ }
+
+ while (1)
+ {
+ struct coord c;
+
+ if (TEMP_FAILURE_RETRY (read (clisock, &c, sizeof (c))) != sizeof (c))
+ {
+ printf ("server read failed: %m (%d)\n", errno);
+ break;
+ }
+
+ if (c.x == 0xffffffff && c.y == 0xffffffff)
+ break;
+
+ unsigned int rnds = 0;
+ complex double z = c.z;
+ while (cabs (z) < 4.0)
+ {
+ z = z * z - 1;
+ if (++rnds == 255)
+ break;
+ }
+
+ unsigned int vals[3] = { c.x, c.y, rnds };
+ if (TEMP_FAILURE_RETRY (write (clisock, vals, sizeof (vals)))
+ != sizeof (vals))
+ {
+ puts ("server write error");
+ return NULL;
+ }
+ }
+
+ close (clisock);
+
+ return NULL;
+}
+
+
+static const char *outfilename = "test.png";
+
+
+static const struct argp_option options[] =
+ {
+ { "clients", 'c', "NUMBER", 0, "Number of client threads" },
+ { "servers", 's', "NUMBER", 0, "Number of server threads per client" },
+ { "timing", 'T', NULL, 0,
+ "Measure time from startup to the last thread finishing" },
+ { NULL, 0, NULL, 0, NULL }
+ };
+
+/* Prototype for option handler. */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+/* Data structure to communicate with argp functions. */
+static struct argp argp =
+{
+ options, parse_opt
+};
+
+
+int
+main (int argc, char *argv[])
+{
+ int cnt;
+ FILE *outfile;
+ struct sockaddr_un servaddr;
+ socklen_t servlen;
+ int remaining;
+
+ /* Parse and process arguments. */
+ argp_parse (&argp, argc, argv, 0, &remaining, NULL);
+
+
+ pthread_t servth[nservers * nclients];
+ pthread_t clntth[nclients];
+ struct thread_param clntparam[nclients];
+
+
+ image = gdImageCreate (size_x, size_y);
+ if (image == NULL)
+ {
+ puts ("gdImageCreate failed");
+ return 1;
+ }
+
+ for (cnt = 0; cnt < 255; ++cnt)
+ colors[cnt] = gdImageColorAllocate (image, 256 - cnt, 256 - cnt,
+ 256 - cnt);
+ /* Black. */
+ colors[cnt] = gdImageColorAllocate (image, 0, 0, 0);
+
+
+ sock = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (sock < 0)
+ error (EXIT_FAILURE, errno, "cannot create socket");
+
+ memset (&servaddr, '\0', sizeof (servaddr));
+ servaddr.sun_family = AF_UNIX;
+ strncpy (servaddr.sun_path, PATH, sizeof (servaddr.sun_path));
+ servlen = offsetof (struct sockaddr_un, sun_path) + strlen (PATH) + 1;
+
+ if (bind (sock, &servaddr, servlen) == -1)
+ error (EXIT_FAILURE, errno, "bind failed");
+
+ listen (sock, SOMAXCONN);
+
+ pthread_mutex_init (&image_lock, NULL);
+
+
+ struct sigaction sa;
+ sa.sa_handler = SIG_IGN;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+
+ clockid_t cl;
+ struct timespec start_time;
+ if (timing)
+ {
+ if (clock_getcpuclockid (0, &cl) != 0
+ || clock_gettime (cl, &start_time) != 0)
+ timing = false;
+ }
+
+ /* Start the servers. */
+ for (cnt = 0; cnt < nservers * nclients; ++cnt)
+ {
+ if (pthread_create (&servth[cnt], NULL, server, NULL) != 0)
+ {
+ puts ("pthread_create for server failed");
+ exit (1);
+ }
+ }
+
+ for (cnt = 0; cnt < nclients; ++cnt)
+ {
+ clntparam[cnt].from = cnt * (size_x * size_y) / nclients;
+ clntparam[cnt].to = MIN ((cnt + 1) * (size_x * size_y) / nclients,
+ size_x * size_y);
+ clntparam[cnt].nserv = nservers;
+
+ if (pthread_create (&clntth[cnt], NULL, client, &clntparam[cnt]) != 0)
+ {
+ puts ("pthread_create for client failed");
+ exit (1);
+ }
+ }
+
+
+ /* Wait for the clients. */
+ for (cnt = 0; cnt < nclients; ++cnt)
+ if (pthread_join (clntth[cnt], NULL) != 0)
+ {
+ puts ("client pthread_join failed");
+ exit (1);
+ }
+
+ /* Wait for the servers. */
+ for (cnt = 0; cnt < nclients * nservers; ++cnt)
+ if (pthread_join (servth[cnt], NULL) != 0)
+ {
+ puts ("server pthread_join failed");
+ exit (1);
+ }
+
+
+ if (timing)
+ {
+ struct timespec end_time;
+
+ if (clock_gettime (cl, &end_time) == 0)
+ {
+ end_time.tv_sec -= start_time.tv_sec;
+ end_time.tv_nsec -= start_time.tv_nsec;
+ if (end_time.tv_nsec < 0)
+ {
+ end_time.tv_nsec += 1000000000;
+ --end_time.tv_sec;
+ }
+
+ printf ("\nRuntime: %lu.%09lu seconds\n%d points computed\n",
+ (unsigned long int) end_time.tv_sec,
+ (unsigned long int) end_time.tv_nsec,
+ points);
+ }
+ }
+
+
+ outfile = fopen (outfilename, "w");
+ if (outfile == NULL)
+ error (EXIT_FAILURE, errno, "cannot open output file '%s'", outfilename);
+
+ gdImagePng (image, outfile);
+
+ fclose (outfile);
+
+ unlink (PATH);
+
+ return 0;
+}
+
+
+/* Handle program arguments. */
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+ switch (key)
+ {
+ case 'c':
+ nclients = strtoul (arg, NULL, 0);
+ break;
+
+ case 's':
+ nservers = strtoul (arg, NULL, 0);
+ break;
+
+ case 'T':
+ timing = true;
+ break;
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+
+ return 0;
+}
+
+
+static hp_timing_t
+get_clockfreq (void)
+{
+ /* We read the information from the /proc filesystem. It contains at
+ least one line like
+ cpu MHz : 497.840237
+ or also
+ cpu MHz : 497.841
+ We search for this line and convert the number in an integer. */
+ static hp_timing_t result;
+ int fd;
+
+ /* If this function was called before, we know the result. */
+ if (result != 0)
+ return result;
+
+ fd = open ("/proc/cpuinfo", O_RDONLY);
+ if (__glibc_likely (fd != -1))
+ {
+ /* XXX AFAIK the /proc filesystem can generate "files" only up
+ to a size of 4096 bytes. */
+ char buf[4096];
+ ssize_t n;
+
+ n = read (fd, buf, sizeof buf);
+ if (__builtin_expect (n, 1) > 0)
+ {
+ char *mhz = memmem (buf, n, "cpu MHz", 7);
+
+ if (__glibc_likely (mhz != NULL))
+ {
+ char *endp = buf + n;
+ int seen_decpoint = 0;
+ int ndigits = 0;
+
+ /* Search for the beginning of the string. */
+ while (mhz < endp && (*mhz < '0' || *mhz > '9') && *mhz != '\n')
+ ++mhz;
+
+ while (mhz < endp && *mhz != '\n')
+ {
+ if (*mhz >= '0' && *mhz <= '9')
+ {
+ result *= 10;
+ result += *mhz - '0';
+ if (seen_decpoint)
+ ++ndigits;
+ }
+ else if (*mhz == '.')
+ seen_decpoint = 1;
+
+ ++mhz;
+ }
+
+ /* Compensate for missing digits at the end. */
+ while (ndigits++ < 6)
+ result *= 10;
+ }
+ }
+
+ close (fd);
+ }
+
+ return result;
+}
+
+
+int
+clock_getcpuclockid (pid_t pid, clockid_t *clock_id)
+{
+ /* We don't allow any process ID but our own. */
+ if (pid != 0 && pid != getpid ())
+ return EPERM;
+
+#ifdef CLOCK_PROCESS_CPUTIME_ID
+ /* Store the number. */
+ *clock_id = CLOCK_PROCESS_CPUTIME_ID;
+
+ return 0;
+#else
+ /* We don't have a timer for that. */
+ return ENOENT;
+#endif
+}
+
+
+#define HP_TIMING_NOW(Var) __asm__ __volatile__ ("rdtsc" : "=A" (Var))
+
+/* Get current value of CLOCK and store it in TP. */
+int
+clock_gettime (clockid_t clock_id, struct timespec *tp)
+{
+ int retval = -1;
+
+ switch (clock_id)
+ {
+ case CLOCK_PROCESS_CPUTIME_ID:
+ {
+
+ static hp_timing_t freq;
+ hp_timing_t tsc;
+
+ /* Get the current counter. */
+ HP_TIMING_NOW (tsc);
+
+ if (freq == 0)
+ {
+ freq = get_clockfreq ();
+ if (freq == 0)
+ return EINVAL;
+ }
+
+ /* 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) * UINT64_C (1000000000)) / freq;
+
+ retval = 0;
+ }
+ break;
+
+ default:
+ errno = EINVAL;
+ break;
+ }
+
+ return retval;
+}
--- /dev/null
+++ b/fbtl/sysdeps/i386/Makefile
@@ -0,0 +1,26 @@
+# Copyright (C) 2002-2013 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+ifeq ($(subdir),csu)
+gen-as-const-headers += tcb-offsets.sym
+endif
+
+ifeq ($(subdir),fbtl)
+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
--- /dev/null
+++ b/fbtl/sysdeps/i386/i486/pthread_spin_trylock.S
@@ -0,0 +1,46 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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
--- /dev/null
+++ b/fbtl/sysdeps/i386/i586/pthread_spin_trylock.S
@@ -0,0 +1,19 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "../i486/pthread_spin_trylock.S"
--- /dev/null
+++ b/fbtl/sysdeps/i386/i686/Makefile
@@ -0,0 +1,31 @@
+# Copyright (C) 2003-2013 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, see
+# <http://www.gnu.org/licenses/>.
+
+ifeq ($(subdir),fbtl)
+# 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
--- /dev/null
+++ b/fbtl/sysdeps/i386/i686/pthread_spin_trylock.S
@@ -0,0 +1,20 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#define HAVE_CMOV 1
+#include "../i486/pthread_spin_trylock.S"
--- /dev/null
+++ b/fbtl/sysdeps/i386/i686/tls.h
@@ -0,0 +1,35 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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 */
--- /dev/null
+++ b/fbtl/sysdeps/i386/pthread_spin_init.c
@@ -0,0 +1,19 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Not needed. pthread_spin_init is an alias for pthread_spin_unlock. */
--- /dev/null
+++ b/fbtl/sysdeps/i386/pthread_spin_lock.S
@@ -0,0 +1,37 @@
+/* Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <lowlevellock.h>
+
+ .globl pthread_spin_lock
+ .type pthread_spin_lock,@function
+ .align 16
+pthread_spin_lock:
+ mov 4(%esp), %eax
+1: LOCK
+ decl 0(%eax)
+ jne 2f
+ xor %eax, %eax
+ ret
+
+ .align 16
+2: rep
+ nop
+ cmpl $0, 0(%eax)
+ jg 1b
+ jmp 2b
+ .size pthread_spin_lock,.-pthread_spin_lock
--- /dev/null
+++ b/fbtl/sysdeps/i386/pthread_spin_unlock.S
@@ -0,0 +1,31 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+ .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
--- /dev/null
+++ b/fbtl/sysdeps/i386/pthreaddef.h
@@ -0,0 +1,40 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* 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.
+
+ Some processors such as Intel Atom pay a big penalty on every
+ access using a segment override if that segment's base is not
+ aligned to the size of a cache line. (See Intel 64 and IA-32
+ Architectures Optimization Reference Manual, section 13.3.3.3,
+ "Segment Base".) On such machines, a cache line is 64 bytes. */
+#define TCB_ALIGNMENT 64
+
+
+/* Location of current stack frame. */
+#define CURRENT_STACK_FRAME __builtin_frame_address (0)
--- /dev/null
+++ b/fbtl/sysdeps/i386/tcb-offsets.sym
@@ -0,0 +1,16 @@
+#include <sysdep.h>
+#include <tls.h>
+
+RESULT offsetof (struct pthread, result)
+TID offsetof (struct pthread, tid)
+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
--- /dev/null
+++ b/fbtl/sysdeps/i386/tls.h
@@ -0,0 +1,459 @@
+/* Definition for thread-local data handling. nptl/i386 version.
+ Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _TLS_H
+#define _TLS_H 1
+
+#include <dl-sysdep.h>
+#ifndef __ASSEMBLER__
+# include <stdbool.h>
+# include <stddef.h>
+# include <stdint.h>
+# include <stdlib.h>
+# include <sysdep.h>
+# include <libc-internal.h>
+# include <kernel-features.h>
+# include <dl-dtv.h>
+
+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 __glibc_reserved1;
+#endif
+ /* Reservation of some values for the TM ABI. */
+ void *__private_tm[4];
+ /* GCC split stack support. */
+ void *__private_ss;
+} tcbhead_t;
+
+# define TLS_MULTIPLE_THREADS_IN_TCB 1
+
+#else /* __ASSEMBLER__ */
+# include <tcb-offsets.h>
+#endif
+
+
+/* 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];
+};
+
+
+/* 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
+# define TLS_DTV_AT_TP 0
+
+/* Get the thread descriptor definition. */
+# include <fbtl/descr.h>
+
+
+/* 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) \
+ ({ 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. */ \
+ _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" ((uint64_t) cast_to_integer (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" ((uint64_t) cast_to_integer (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 */
--- /dev/null
+++ b/fbtl/sysdeps/pthread/Makefile
@@ -0,0 +1,39 @@
+# Copyright (C) 2002-2013 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, see
+# <http://www.gnu.org/licenses/>.
+
+ifeq ($(subdir),fbtl)
+libpthread-sysdep_routines += errno-loc
+endif
+
+ifeq ($(subdir),rt)
+librt-sysdep_routines += timer_routines librt-cancellation
+CFLAGS-librt-cancellation.c += -fexceptions -fasynchronous-unwind-tables
+
+ifeq (yes,$(build-shared))
+$(objpfx)tst-timer: $(objpfx)librt.so $(shared-thread-library)
+else
+$(objpfx)tst-timer: $(objpfx)librt.a $(static-thread-library)
+endif
+
+tests += tst-mqueue8x
+CFLAGS-tst-mqueue8x.c += -fexceptions
+endif
+
+ifeq ($(subdir),posix)
+CFLAGS-confstr.c += -DLIBPTHREAD_VERSION='"FBTL $(version)"'
+endif
--- /dev/null
+++ b/fbtl/sysdeps/pthread/Subdirs
@@ -0,0 +1,2 @@
+fbtl
+fbtl_db
--- /dev/null
+++ b/fbtl/sysdeps/pthread/aio_misc.h
@@ -0,0 +1,74 @@
+/* Copyright (C) 2006-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* We define a special synchronization primitive for AIO. POSIX
+ conditional variables would be ideal but the pthread_cond_*wait
+ operations do not return on EINTR. This is a requirement for
+ correct aio_suspend and lio_listio implementations. */
+
+#include <assert.h>
+#include <pthreadP.h>
+#include <lowlevellock.h>
+
+#define DONT_NEED_AIO_MISC_COND 1
+
+#define AIO_MISC_NOTIFY(waitlist) \
+ do { \
+ if (*waitlist->counterp > 0 && --*waitlist->counterp == 0) \
+ lll_futex_wake (waitlist->counterp, 1, LLL_PRIVATE); \
+ } while (0)
+
+#define AIO_MISC_WAIT(result, futex, timeout, cancel) \
+ do { \
+ volatile int *futexaddr = &futex; \
+ int oldval = futex; \
+ \
+ if (oldval != 0) \
+ { \
+ pthread_mutex_unlock (&__aio_requests_mutex); \
+ \
+ int oldtype; \
+ if (cancel) \
+ oldtype = LIBC_CANCEL_ASYNC (); \
+ \
+ int status; \
+ do \
+ { \
+ status = lll_futex_timed_wait (futexaddr, oldval, timeout, \
+ LLL_PRIVATE); \
+ if (status != EWOULDBLOCK) \
+ break; \
+ \
+ oldval = *futexaddr; \
+ } \
+ while (oldval != 0); \
+ \
+ if (cancel) \
+ LIBC_CANCEL_RESET (oldtype); \
+ \
+ if (status == EINTR) \
+ result = EINTR; \
+ else if (status == ETIMEDOUT) \
+ result = EAGAIN; \
+ else \
+ assert (status == 0 || status == EWOULDBLOCK); \
+ \
+ pthread_mutex_lock (&__aio_requests_mutex); \
+ } \
+ } while (0)
+
+#include_next <aio_misc.h>
--- /dev/null
+++ b/fbtl/sysdeps/pthread/allocalim.h
@@ -0,0 +1,29 @@
+/* Determine whether block of given size can be allocated on the stack or not.
+ Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#include <alloca.h>
+#include <limits.h>
+
+
+extern __always_inline
+int
+__libc_use_alloca (size_t size)
+{
+ return (__builtin_expect (size <= PTHREAD_STACK_MIN / 4, 1)
+ || __builtin_expect (__libc_alloca_cutoff (size), 1));
+}
--- /dev/null
+++ b/fbtl/sysdeps/pthread/bits/sigthread.h
@@ -0,0 +1,43 @@
+/* Signal handling function for threaded programs.
+ Copyright (C) 1998-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#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 */
--- /dev/null
+++ b/fbtl/sysdeps/pthread/createthread.c
@@ -0,0 +1,298 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sched.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <atomic.h>
+#include <ldsodefs.h>
+#include <tls.h>
+#include <stdint.h>
+
+#include "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
+
+
+struct rtprio;
+struct thr_param {
+ int (*start_func)(void *); /* thread entry function. */
+ void *arg; /* argument for entry function. */
+ char *stack_base; /* stack base address. */
+ size_t stack_size; /* stack size. */
+ char *tls_base; /* tls base address. */
+ size_t tls_size; /* tls size. */
+ long *child_tid; /* address to store new TID. */
+ long *parent_tid; /* parent accesses the new TID here. */
+ int flags; /* thread flags. */
+ struct rtprio *rtp; /* Real-time scheduling priority */
+ void *spare[3]; /* TODO: cpu affinity mask etc. */
+};
+
+
+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
+
+ struct thr_param p;
+
+ if (__glibc_unlikely (stopped != 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 0
+ int rc = ARCH_CLONE (fct, STACK_VARIABLES_ARGS, clone_flags,
+ pd, &pd->tid, TLS_VALUE, &pd->tid);
+
+#else
+ memset(&p, 0, sizeof(p));
+ p.start_func = fct;
+ p.arg = pd;
+ p.stack_base = stackaddr; /* first in STACK_VARIABLES_ARGS */
+ p.stack_size = stacksize; /* second in STACK_VARIABLES_ARGS */
+ p.tls_base = (char*)pd;
+ p.child_tid = &(pd->ktid);
+
+ int rc = INLINE_SYSCALL(thr_new, 2, &p, sizeof(p));
+
+ if (rc)
+ {
+ errno = rc;
+ rc = -1;;
+ }
+#endif
+
+
+ if (__glibc_unlikely (rc == -1))
+ {
+ atomic_decrement (&__nptl_nthreads); /* Oops, we lied for a second. */
+ pd->ktid = 0;
+
+ /* Perhaps a thread wants to change the IDs and if waiting
+ for this stillborn thread. */
+ if (__builtin_expect (atomic_exchange_acq (&pd->setxid_futex, 0)
+ == -2, 0))
+ lll_futex_wake (&pd->setxid_futex, 1, LLL_PRIVATE);
+
+ /* Free the resources. */
+ __deallocate_stack (pd);
+
+ /* We have to translate error codes. */
+ return errno == ENOMEM ? EAGAIN : errno;
+ }
+#warning set scheduling parameters
+#if 0
+ /* Now we have the possibility to set scheduling parameters etc. */
+ if (__glibc_unlikely (stopped != 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 (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (res, err)))
+ {
+ /* The operation failed. We have to kill the thread. First
+ send it the cancellation signal. */
+ INTERNAL_SYSCALL_DECL (err2);
+ err_out:
+ (void) INTERNAL_SYSCALL (tgkill, err2, 3,
+ THREAD_GETMEM (THREAD_SELF, pid),
+ pd->tid, SIGCANCEL);
+
+ /* We do not free the stack here because the canceled thread
+ itself will do this. */
+
+ 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 (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (res, err)))
+ goto err_out;
+ }
+ }
+#endif
+
+ /* 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.
+
+ The termination signal is chosen to be zero which means no signal
+ is sent. */
+#if 1
+#define clone_flags 123456
+#warning clone
+#else
+ int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL
+ | CLONE_SETTLS | CLONE_PARENT_SETTID
+ | CLONE_CHILD_CLEARTID | CLONE_SYSVSEM
+ | 0);
+#endif
+
+ if (__glibc_unlikely (THREAD_GETMEM (THREAD_SELF, report_events)))
+ {
+ /* 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;
+}
--- /dev/null
+++ b/fbtl/sysdeps/pthread/flockfile.c
@@ -0,0 +1,32 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <libio.h>
+#include <stdio-lock.h>
+
+
+void
+__flockfile (stream)
+ FILE *stream;
+{
+ _IO_lock_lock (*stream->_lock);
+}
+strong_alias (__flockfile, _IO_flockfile)
+weak_alias (__flockfile, flockfile)
--- /dev/null
+++ b/fbtl/sysdeps/pthread/ftrylockfile.c
@@ -0,0 +1,32 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdio-lock.h>
+
+
+int
+__ftrylockfile (stream)
+ FILE *stream;
+{
+ return _IO_lock_trylock (*stream->_lock);
+}
+strong_alias (__ftrylockfile, _IO_ftrylockfile)
+weak_alias (__ftrylockfile, ftrylockfile)
--- /dev/null
+++ b/fbtl/sysdeps/pthread/funlockfile.c
@@ -0,0 +1,32 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <libio.h>
+#include <stdio-lock.h>
+
+
+void
+__funlockfile (stream)
+ FILE *stream;
+{
+ _IO_lock_unlock (*stream->_lock);
+}
+strong_alias (__funlockfile, _IO_funlockfile)
+weak_alias (__funlockfile, funlockfile)
--- /dev/null
+++ b/fbtl/sysdeps/pthread/gai_misc.h
@@ -0,0 +1,121 @@
+/* Copyright (C) 2006-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* We define a special synchronization primitive for AIO. POSIX
+ conditional variables would be ideal but the pthread_cond_*wait
+ operations do not return on EINTR. This is a requirement for
+ correct aio_suspend and lio_listio implementations. */
+
+#include <assert.h>
+#include <signal.h>
+#include <pthreadP.h>
+#include <lowlevellock.h>
+
+#define DONT_NEED_GAI_MISC_COND 1
+
+#define GAI_MISC_NOTIFY(waitlist) \
+ do { \
+ if (*waitlist->counterp > 0 && --*waitlist->counterp == 0) \
+ lll_futex_wake ((unsigned int *) waitlist->counterp, 1, LLL_PRIVATE); \
+ } while (0)
+
+#define GAI_MISC_WAIT(result, futex, timeout, cancel) \
+ do { \
+ volatile int *futexaddr = &futex; \
+ int oldval = futex; \
+ \
+ if (oldval != 0) \
+ { \
+ pthread_mutex_unlock (&__gai_requests_mutex); \
+ \
+ int oldtype; \
+ if (cancel) \
+ oldtype = LIBC_CANCEL_ASYNC (); \
+ \
+ int status; \
+ do \
+ { \
+ status = lll_futex_timed_wait ((unsigned int *) futexaddr, oldval,\
+ timeout, LLL_PRIVATE); \
+ if (status != EWOULDBLOCK) \
+ break; \
+ \
+ oldval = *futexaddr; \
+ } \
+ while (oldval != 0); \
+ \
+ if (cancel) \
+ LIBC_CANCEL_RESET (oldtype); \
+ \
+ if (status == EINTR) \
+ result = EINTR; \
+ else if (status == ETIMEDOUT) \
+ result = EAGAIN; \
+ else \
+ assert (status == 0 || status == EWOULDBLOCK); \
+ \
+ pthread_mutex_lock (&__gai_requests_mutex); \
+ } \
+ } while (0)
+
+
+#define gai_start_notify_thread __gai_start_notify_thread
+#define gai_create_helper_thread __gai_create_helper_thread
+
+extern inline void
+__gai_start_notify_thread (void)
+{
+ sigset_t ss;
+ sigemptyset (&ss);
+ INTERNAL_SYSCALL_DECL (err);
+ INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, NULL, _NSIG / 8);
+}
+
+extern inline int
+__gai_create_helper_thread (pthread_t *threadp, void *(*tf) (void *),
+ void *arg)
+{
+ pthread_attr_t attr;
+
+ /* Make sure the thread is created detached. */
+ pthread_attr_init (&attr);
+ pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+
+ /* The helper thread needs only very little resources. */
+ (void) pthread_attr_setstacksize (&attr,
+ __pthread_get_minstack (&attr)
+ + 4 * PTHREAD_STACK_MIN);
+
+ /* Block all signals in the helper thread. To do this thoroughly we
+ temporarily have to block all signals here. */
+ sigset_t ss;
+ sigset_t oss;
+ sigfillset (&ss);
+ INTERNAL_SYSCALL_DECL (err);
+ INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, &oss, _NSIG / 8);
+
+ int ret = pthread_create (threadp, &attr, tf, arg);
+
+ /* Restore the signal mask. */
+ INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &oss, NULL,
+ _NSIG / 8);
+
+ (void) pthread_attr_destroy (&attr);
+ return ret;
+}
+
+#include_next <gai_misc.h>
--- /dev/null
+++ b/fbtl/sysdeps/pthread/libc-lock.h
@@ -0,0 +1,187 @@
+/* libc-internal interface for mutex locks. NPTL version.
+ Copyright (C) 1996-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC_LOCK_H
+#define _LIBC_LOCK_H 1
+
+#include <pthread.h>
+#define __need_NULL
+#include <stddef.h>
+
+
+/* Mutex type. */
+#if defined _LIBC || defined _IO_MTSAFE_IO
+# if (!IS_IN (libc) && !IS_IN (libpthread)) || !defined _LIBC
+typedef struct { pthread_mutex_t mutex; } __libc_lock_recursive_t;
+# else
+typedef struct { int lock; int cnt; void *owner; } __libc_lock_recursive_t;
+# endif
+#else
+typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
+#endif
+
+/* 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_recursive(CLASS,NAME) \
+ CLASS __libc_lock_recursive_t NAME;
+
+/* Define an initialized recursive lock variable NAME with storage
+ class CLASS. */
+#if defined _LIBC && (IS_IN (libc) || IS_IN (libpthread))
+# define __libc_lock_define_initialized_recursive(CLASS, NAME) \
+ CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER;
+# 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
+
+/* Initialize a recursive mutex. */
+#if defined _LIBC && (IS_IN (libc) || IS_IN (libpthread))
+# define __libc_lock_init_recursive(NAME) \
+ ((void) ((NAME) = (__libc_lock_recursive_t) _LIBC_LOCK_RECURSIVE_INITIALIZER))
+#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
+
+/* Finalize recursive named lock. */
+#if defined _LIBC && (IS_IN (libc) || 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).mutex), 0)
+#endif
+
+/* Lock the recursive named lock variable. */
+#if defined _LIBC && (IS_IN (libc) || 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 recursive named lock variable. */
+#if defined _LIBC && (IS_IN (libc) || 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).mutex), 0)
+#endif
+
+/* Unlock the recursive named lock variable. */
+#if defined _LIBC && (IS_IN (libc) || 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).mutex), 0)
+#endif
+
+/* Note that for I/O cleanup handling we are using the old-style
+ cancel handling. It does not have to be integrated with C++ since
+ 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_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); \
+ }
+
+
+/* Hide the definitions which are only supposed to be used inside libc in
+ a separate file. This file is not present in the installation! */
+#ifdef _LIBC
+# include "libc-lockP.h"
+#endif
+
+#endif /* libc-lock.h */
--- /dev/null
+++ b/fbtl/sysdeps/pthread/libc-lockP.h
@@ -0,0 +1,438 @@
+/* Private libc-internal interface for mutex locks. NPTL version.
+ Copyright (C) 1996-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC_LOCKP_H
+#define _LIBC_LOCKP_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. */
+#include <lowlevellock.h>
+#include <tls.h>
+#include <pthread-functions.h>
+
+#if IS_IN (libpthread)
+/* This gets us the declarations of the __pthread_* internal names,
+ and hidden_proto for them. */
+# include <fbtl/pthreadP.h>
+#endif
+
+/* Mutex type. */
+#if !IS_IN (libc) && !IS_IN (libpthread)
+typedef pthread_mutex_t __libc_lock_t;
+#else
+typedef int __libc_lock_t;
+#endif
+typedef struct { pthread_mutex_t mutex; } __rtld_lock_recursive_t;
+typedef pthread_rwlock_t __libc_rwlock_t;
+
+/* Type for key to thread-specific data. */
+typedef pthread_key_t __libc_key_t;
+
+/* 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 __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.) */
+
+#define _LIBC_LOCK_INITIALIZER LLL_LOCK_INITIALIZER
+#if IS_IN (libc) || 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
+# define __libc_lock_define_initialized(CLASS,NAME) \
+ CLASS __libc_lock_t NAME;
+#endif
+
+#define __libc_rwlock_define_initialized(CLASS,NAME) \
+ CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER;
+
+#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 && IS_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)
+#elif IS_IN (libpthread)
+# define PTFAVAIL(NAME) 1
+# define __libc_ptf_call(FUNC, ARGS, ELSE) \
+ FUNC ARGS
+# define __libc_ptf_call_always(FUNC, ARGS) \
+ 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 IS_IN (libc) || IS_IN (libpthread)
+# define __libc_lock_init(NAME) \
+ ((void) ((NAME) = LLL_LOCK_INITIALIZER))
+#else
+# define __libc_lock_init(NAME) \
+ __libc_maybe_call (__pthread_mutex_init, (&(NAME), NULL), 0)
+#endif
+#if defined SHARED && IS_IN (libc)
+/* ((NAME) = (__libc_rwlock_t) PTHREAD_RWLOCK_INITIALIZER) is inefficient. */
+# define __libc_rwlock_init(NAME) \
+ ((void) __builtin_memset (&(NAME), '\0', sizeof (NAME)))
+#else
+# define __libc_rwlock_init(NAME) \
+ __libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0)
+#endif
+
+/* 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 IS_IN (libc) || 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 && IS_IN (libc)
+# define __libc_rwlock_fini(NAME) ((void) 0)
+#else
+# define __libc_rwlock_fini(NAME) \
+ __libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0)
+#endif
+
+/* Lock the named lock variable. */
+#if IS_IN (libc) || IS_IN (libpthread)
+# ifndef __libc_lock_lock
+# define __libc_lock_lock(NAME) \
+ ({ lll_lock (NAME, LLL_PRIVATE); 0; })
+# endif
+#else
+# undef __libc_lock_lock
+# 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)
+
+/* Try to lock the named lock variable. */
+#if IS_IN (libc) || IS_IN (libpthread)
+# ifndef __libc_lock_trylock
+# define __libc_lock_trylock(NAME) \
+ lll_trylock (NAME)
+# endif
+#else
+# undef __libc_lock_trylock
+# 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)
+
+#define __rtld_lock_trylock_recursive(NAME) \
+ __libc_maybe_call (__pthread_mutex_trylock, (&(NAME).mutex), 0)
+
+/* Unlock the named lock variable. */
+#if IS_IN (libc) || 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)
+
+#ifdef 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)
+
+/* Get once control variable. */
+#define __libc_once_get(ONCE_CONTROL) ((ONCE_CONTROL) != PTHREAD_ONCE_INIT)
+
+/* 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);
+
+/* 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);
+
+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);
+
+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));
+
+extern int __pthread_setcancelstate (int state, int *oldstate);
+
+
+/* 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)
+weak_extern (__pthread_setcancelstate)
+weak_extern (_pthread_cleanup_push_defer)
+weak_extern (_pthread_cleanup_pop_restore)
+# 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_setcancelstate
+# pragma weak _pthread_cleanup_push_defer
+# pragma weak _pthread_cleanup_pop_restore
+# endif
+#endif
+
+#endif /* libc-lockP.h */
--- /dev/null
+++ b/fbtl/sysdeps/pthread/librt-cancellation.c
@@ -0,0 +1,24 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP.h"
+
+
+#define __pthread_enable_asynccancel __librt_enable_asynccancel
+#define __pthread_disable_asynccancel __librt_disable_asynccancel
+#include <fbtl/cancellation.c>
--- /dev/null
+++ b/fbtl/sysdeps/pthread/list.h
@@ -0,0 +1,117 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _LIST_H
+
+#ifndef __need_list_t
+# define _LIST_H 1
+#endif
+
+/* 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. */
+
+
+#if defined __need_list_t || defined _LIST_H
+# ifndef __list_t_defined
+# define __list_t_defined
+/* Basic type for the double-link list. */
+typedef struct list_head
+{
+ struct list_head *next;
+ struct list_head *prev;
+} list_t;
+# endif
+# undef __need_list_t
+#endif
+
+#ifdef _LIST_H
+
+# include <atomic.h>
+
+/* 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;
+ atomic_write_barrier ();
+ 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 */
+
+#endif /* list.h */
--- /dev/null
+++ b/fbtl/sysdeps/pthread/malloc-machine.h
@@ -0,0 +1,28 @@
+/* Basic platform-independent macro definitions for mutexes,
+ thread-specific data and parameters for malloc.
+ Copyright (C) 2003-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _MALLOC_MACHINE_H
+#define _MALLOC_MACHINE_H
+
+#include <atomic.h>
+#include <libc-lock.h>
+
+#include <sysdeps/generic/malloc-machine.h>
+
+#endif /* !defined(_MALLOC_MACHINE_H) */
--- /dev/null
+++ b/fbtl/sysdeps/pthread/posix-timer.h
@@ -0,0 +1,196 @@
+/* Definitions for POSIX timer implementation on top of NPTL.
+ Copyright (C) 2000-2013 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, see <http://www.gnu.org/licenses/>. */
+
+#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);
--- /dev/null
+++ b/fbtl/sysdeps/pthread/pt-longjmp.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <setjmp.h>
+#include <stdlib.h>
+#include "pthreadP.h"
+
+void
+longjmp (jmp_buf env, int val)
+{
+ __libc_longjmp (env, val);
+}
+weak_alias (longjmp, siglongjmp)
--- /dev/null
+++ b/fbtl/sysdeps/pthread/pthread-functions.h
@@ -0,0 +1,117 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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 *) __attribute__ ((__noreturn__));
+ 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);
+ void (*ptr_set_robust) (struct pthread *);
+};
+
+/* Variable in libc.so. */
+extern struct pthread_functions __libc_pthread_functions attribute_hidden;
+extern int __libc_pthread_functions_init attribute_hidden;
+
+#ifdef PTR_DEMANGLE
+# 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 */
--- /dev/null
+++ b/fbtl/sysdeps/pthread/pthread.h
@@ -0,0 +1,1177 @@
+/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _PTHREAD_H
+#define _PTHREAD_H 1
+
+#include <features.h>
+#include <endian.h>
+#include <sched.h>
+#include <time.h>
+
+#include <bits/pthreadtypes.h>
+#include <bits/setjmp.h>
+#include <bits/wordsize.h>
+
+
+/* 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 _LIBC /* not yet supported, so do not expose outside libc */
+
+#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
+
+
+#if defined __USE_POSIX199506 || defined __USE_UNIX98
+/* Mutex protocols. */
+enum
+{
+ PTHREAD_PRIO_NONE,
+ PTHREAD_PRIO_INHERIT,
+ PTHREAD_PRIO_PROTECT
+};
+#endif
+
+#endif /* not yet supported, so do not expose outside libc */
+
+/* Mutex initializers. */
+#ifdef __PTHREAD_MUTEX_HAVE_PREV
+# 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
+};
+
+/* Define __PTHREAD_RWLOCK_INT_FLAGS_SHARED to 1 if pthread_rwlock_t
+ has the shared field. All 64-bit architectures have the shared field
+ in pthread_rwlock_t. */
+#ifndef __PTHREAD_RWLOCK_INT_FLAGS_SHARED
+# if __WORDSIZE == 64
+# define __PTHREAD_RWLOCK_INT_FLAGS_SHARED 1
+# endif
+#endif
+
+/* Read-write lock initializers. */
+# define PTHREAD_RWLOCK_INITIALIZER \
+ { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
+# ifdef __USE_GNU
+# ifdef __PTHREAD_RWLOCK_INT_FLAGS_SHARED
+# 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) __THROWNL __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 __attribute__ ((__const__));
+
+
+/* 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));
+
+#ifdef _LIBC /* not yet supported, so do not expose outside libc */
+
+/* Get the default attributes used by pthread_create in this process. */
+extern int pthread_getattr_default_np (pthread_attr_t *__attr)
+ __THROW __nonnull ((1));
+
+/* Set the default attributes to be used by pthread_create in this
+ process. */
+extern int pthread_setattr_default_np (const pthread_attr_t *__attr)
+ __THROW __nonnull ((1));
+
+#endif /* not yet supported, so do not expose outside libc */
+
+/* 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));
+
+
+#ifdef _LIBC /* not yet supported, so do not expose outside libc */
+
+/* Set the scheduling priority for TARGET_THREAD. */
+extern int pthread_setschedprio (pthread_t __target_thread, int __prio)
+ __THROW;
+#endif /* not yet supported, so do not expose outside libc */
+
+
+#ifdef __USE_GNU
+/* Get thread name visible in the kernel and its interfaces. */
+extern int pthread_getname_np (pthread_t __target_thread, char *__buf,
+ size_t __buflen)
+ __THROW __nonnull ((2));
+
+/* Set thread name visible in the kernel and its interfaces. */
+extern int pthread_setname_np (pthread_t __target_thread, const char *__name)
+ __THROW __nonnull ((2));
+#endif
+
+
+#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 (__glibc_unlikely (__not_first_call)) \
+ { \
+ __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 (__glibc_unlikely (__not_first_call)) \
+ { \
+ __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) __THROWNL;
+
+
+/* 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)
+ __THROWNL __nonnull ((1));
+
+/* Lock a mutex. */
+extern int pthread_mutex_lock (pthread_mutex_t *__mutex)
+ __THROWNL __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) __THROWNL __nonnull ((1, 2));
+#endif
+
+/* Unlock a mutex. */
+extern int pthread_mutex_unlock (pthread_mutex_t *__mutex)
+ __THROWNL __nonnull ((1));
+
+#ifdef _LIBC /* not yet supported, so do not expose outside libc */
+
+/* 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
+
+#endif /* not yet supported, so do not expose outside libc */
+
+/* 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
+
+#ifdef _LIBC /* not yet supported, so do not expose outside libc */
+
+/* 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
+
+#endif /* not yet supported, so do not expose outside libc */
+
+#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)
+ __THROWNL __nonnull ((1));
+
+/* Try to acquire read lock for RWLOCK. */
+extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock)
+ __THROWNL __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) __THROWNL __nonnull ((1, 2));
+# endif
+
+/* Acquire write lock for RWLOCK. */
+extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock)
+ __THROWNL __nonnull ((1));
+
+/* Try to acquire write lock for RWLOCK. */
+extern int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock)
+ __THROWNL __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) __THROWNL __nonnull ((1, 2));
+# endif
+
+/* Unlock RWLOCK. */
+extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock)
+ __THROWNL __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)
+ __THROWNL __nonnull ((1));
+
+/* Wake up all threads waiting for condition variables COND. */
+extern int pthread_cond_broadcast (pthread_cond_t *__cond)
+ __THROWNL __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)
+ __THROWNL __nonnull ((1));
+
+/* Try to lock spinlock LOCK. */
+extern int pthread_spin_trylock (pthread_spinlock_t *__lock)
+ __THROWNL __nonnull ((1));
+
+/* Release spinlock LOCK. */
+extern int pthread_spin_unlock (pthread_spinlock_t *__lock)
+ __THROWNL __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)
+ __THROWNL __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 */
--- /dev/null
+++ b/fbtl/sysdeps/pthread/pthread_sigmask.c
@@ -0,0 +1,57 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <signal.h>
+#include <pthreadP.h>
+#include <sysdep.h>
+
+
+int
+pthread_sigmask (how, newmask, oldmask)
+ 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
+}
--- /dev/null
+++ b/fbtl/sysdeps/pthread/setxid.h
@@ -0,0 +1,62 @@
+/* Copyright (C) 2004-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthreadP.h>
+#include <sysdep.h>
+
+#define __SETXID_1(cmd, arg1) \
+ cmd.id[0] = (long int) arg1
+#define __SETXID_2(cmd, arg1, arg2) \
+ __SETXID_1 (cmd, arg1); cmd.id[1] = (long int) arg2
+#define __SETXID_3(cmd, arg1, arg2, arg3) \
+ __SETXID_2 (cmd, arg1, arg2); cmd.id[2] = (long int) 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 (__glibc_unlikely (__nptl_setxid != NULL)) \
+ { \
+ 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
--- /dev/null
+++ b/fbtl/sysdeps/pthread/shm-directory.h
@@ -0,0 +1,31 @@
+/* Header for directory for shm/sem files. NPTL version.
+ Copyright (C) 2014-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _SHM_DIRECTORY_H
+
+#include <sysdeps/posix/shm-directory.h>
+
+/* For NPTL the __shm_directory function lives in libpthread.
+ We don't want PLT calls from there. But it's also used from
+ librt, so it cannot just be declared hidden. */
+
+#if IS_IN (libpthread)
+hidden_proto (__shm_directory)
+#endif
+
+#endif /* shm-directory.h */
--- /dev/null
+++ b/fbtl/sysdeps/pthread/sigfillset.c
@@ -0,0 +1,20 @@
+/* Copyright (C) 2003-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fbtl/pthreadP.h>
+
+#include <signal/sigfillset.c>
--- /dev/null
+++ b/fbtl/sysdeps/pthread/sigprocmask.c
@@ -0,0 +1,19 @@
+/* Copyright (C) 1997-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fbtl/pthreadP.h>
+#include <sysdeps/unix/bsd/sigprocmask.c>
--- /dev/null
+++ b/fbtl/sysdeps/pthread/stdio-lock.h
@@ -0,0 +1,110 @@
+/* Thread package specific definitions of stream lock type. NPTL version.
+ Copyright (C) 2000-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _STDIO_LOCK_H
+#define _STDIO_LOCK_H 1
+
+#include <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) \
+ ((void) ((_name) = (_IO_lock_t) _IO_lock_initializer))
+
+#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 && IS_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 /* stdio-lock.h */
--- /dev/null
+++ b/fbtl/sysdeps/pthread/tcb-offsets.h
@@ -0,0 +1 @@
+/* This is overridden by generated tcb-offsets.h on arches which need it. */
--- /dev/null
+++ b/fbtl/sysdeps/pthread/timer_create.c
@@ -0,0 +1,169 @@
+/* Copyright (C) 2000-2013 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, see <http://www.gnu.org/licenses/>. */
+
+#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 (clock_id, evp, timerid)
+ 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 (__glibc_unlikely (newtimer == NULL))
+ {
+ __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 (__glibc_unlikely (thread == NULL))
+ {
+ __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;
+}
--- /dev/null
+++ b/fbtl/sysdeps/pthread/timer_delete.c
@@ -0,0 +1,69 @@
+/* Copyright (C) 2000-2013 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, see <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <time.h>
+
+#include "posix-timer.h"
+
+
+/* Delete timer TIMERID. */
+int
+timer_delete (timerid)
+ 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;
+}
--- /dev/null
+++ b/fbtl/sysdeps/pthread/timer_getoverr.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 2000-2013 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, see <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl/sysdeps/pthread/timer_gettime.c
@@ -0,0 +1,76 @@
+/* Copyright (C) 2000-2013 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, see <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl/sysdeps/pthread/timer_routines.c
@@ -0,0 +1,577 @@
+/* Helper code for POSIX timer implementation on NPTL.
+ Copyright (C) 2000-2013 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, see <http://www.gnu.org/licenses/>. */
+
+#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);
+}
--- /dev/null
+++ b/fbtl/sysdeps/pthread/timer_settime.c
@@ -0,0 +1,136 @@
+/* Copyright (C) 2000-2013 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, see <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl/sysdeps/pthread/tst-mqueue8x.c
@@ -0,0 +1 @@
+#include <rt/tst-mqueue8.c>
--- /dev/null
+++ b/fbtl/sysdeps/pthread/tst-timer.c
@@ -0,0 +1,159 @@
+/* Tests for POSIX timer implementation.
+ Copyright (C) 2000-2013 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, see <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+
+static void
+notify_func1 (union sigval sigval)
+{
+ puts ("notify_func1");
+}
+
+
+static void
+notify_func2 (union sigval sigval)
+{
+ puts ("notify_func2");
+}
+
+
+static void
+signal_func (int sig)
+{
+ static const char text[] = "signal_func\n";
+ signal (sig, signal_func);
+ write (STDOUT_FILENO, text, sizeof text - 1);
+}
+
+static void
+intr_sleep (int sec)
+{
+ struct timespec ts;
+
+ ts.tv_sec = sec;
+ ts.tv_nsec = 0;
+
+ while (nanosleep (&ts, &ts) == -1 && errno == EINTR)
+ ;
+}
+
+#define ZSIGALRM 14
+
+
+int
+main (void)
+{
+ struct timespec ts;
+ timer_t timer_sig, timer_thr1, timer_thr2;
+ int retval;
+ struct sigevent sigev1 =
+ {
+ .sigev_notify = SIGEV_SIGNAL,
+ .sigev_signo = ZSIGALRM
+ };
+ struct sigevent sigev2;
+ struct itimerspec itimer1 = { { 0, 200000000 }, { 0, 200000000 } };
+ struct itimerspec itimer2 = { { 0, 100000000 }, { 0, 500000000 } };
+ struct itimerspec itimer3 = { { 0, 150000000 }, { 0, 300000000 } };
+ struct itimerspec old;
+
+ retval = clock_gettime (CLOCK_REALTIME, &ts);
+
+ sigev2.sigev_notify = SIGEV_THREAD;
+ sigev2.sigev_notify_function = notify_func1;
+ sigev2.sigev_notify_attributes = NULL;
+ /* It is unnecessary to do the following but to set a good example
+ we do it anyhow. */
+ sigev2.sigev_value.sival_ptr = NULL;
+
+ setvbuf (stdout, 0, _IOLBF, 0);
+
+ printf ("clock_gettime returned %d, timespec = { %ld, %ld }\n",
+ retval, ts.tv_sec, ts.tv_nsec);
+
+ retval = clock_getres (CLOCK_REALTIME, &ts);
+
+ printf ("clock_getres returned %d, timespec = { %ld, %ld }\n",
+ retval, ts.tv_sec, ts.tv_nsec);
+
+ if (timer_create (CLOCK_REALTIME, &sigev1, &timer_sig) != 0)
+ {
+ printf ("timer_create for timer_sig failed: %m\n");
+ exit (1);
+ }
+ if (timer_create (CLOCK_REALTIME, &sigev2, &timer_thr1) != 0)
+ {
+ printf ("timer_create for timer_thr1 failed: %m\n");
+ exit (1);
+ }
+ sigev2.sigev_notify_function = notify_func2;
+ if (timer_create (CLOCK_REALTIME, &sigev2, &timer_thr2) != 0)
+ {
+ printf ("timer_create for timer_thr2 failed: %m\n");
+ exit (1);
+ }
+
+ if (timer_settime (timer_thr1, 0, &itimer2, &old) != 0)
+ {
+ printf ("timer_settime for timer_thr1 failed: %m\n");
+ exit (1);
+ }
+ if (timer_settime (timer_thr2, 0, &itimer3, &old) != 0)
+ {
+ printf ("timer_settime for timer_thr2 failed: %m\n");
+ exit (1);
+ }
+
+ signal (ZSIGALRM, signal_func);
+
+ if (timer_settime (timer_sig, 0, &itimer1, &old) != 0)
+ {
+ printf ("timer_settime for timer_sig failed: %m\n");
+ exit (1);
+ }
+
+ intr_sleep (3);
+
+ if (timer_delete (timer_sig) != 0)
+ {
+ printf ("timer_delete for timer_sig failed: %m\n");
+ exit (1);
+ }
+ if (timer_delete (timer_thr1) != 0)
+ {
+ printf ("timer_delete for timer_thr1 failed: %m\n");
+ exit (1);
+ }
+
+ intr_sleep (3);
+
+ if (timer_delete (timer_thr2) != 0)
+ {
+ printf ("timer_delete for timer_thr2 failed: %m\n");
+ exit (1);
+ }
+
+ return 0;
+}
--- /dev/null
+++ b/fbtl/sysdeps/pthread/unwind-forcedunwind.c
@@ -0,0 +1,151 @@
+/* Copyright (C) 2003-2013 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, see <http://www.gnu.org/licenses/>. */
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unwind.h>
+#include <pthreadP.h>
+#include <sysdep.h>
+#include <gnu/lib-names.h>
+
+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 (__glibc_likely (libgcc_s_handle != NULL))
+ {
+ /* 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
+ )
+ __libc_fatal (LIBGCC_S_SO " must be installed for pthread_cancel to work\n");
+
+ 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 (__glibc_unlikely (libgcc_s_handle == NULL))
+ pthread_cancel_init ();
+ else
+ atomic_read_barrier ();
+
+ 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 (__glibc_unlikely (libgcc_s_handle == NULL))
+ pthread_cancel_init ();
+ else
+ atomic_read_barrier ();
+
+ _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 (__glibc_unlikely (libgcc_s_handle == NULL))
+ pthread_cancel_init ();
+ else
+ atomic_read_barrier ();
+
+ _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 (__glibc_unlikely (libgcc_s_handle == NULL))
+ pthread_cancel_init ();
+ else
+ atomic_read_barrier ();
+
+ _Unwind_Word (*getcfa) (struct _Unwind_Context *) = libgcc_s_getcfa;
+ PTR_DEMANGLE (getcfa);
+ return getcfa (context);
+}
--- /dev/null
+++ b/fbtl/sysdeps/x86_64/Makefile
@@ -0,0 +1,27 @@
+# Copyright (C) 2002-2013 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+ifeq ($(subdir),csu)
+gen-as-const-headers += tcb-offsets.sym
+endif
+
+ifeq ($(subdir),fbtl)
+# P4s have problems with 4M aliasing. We disturb the allocation of stacks
+# just enough so the subsequent allocations do not use stack address
+# (mod 4M) == 0.
+CFLAGS-pthread_create.c += -DMULTI_PAGE_ALIASING=65536
+endif
--- /dev/null
+++ b/fbtl/sysdeps/x86_64/pthread_spin_init.c
@@ -0,0 +1 @@
+#include "../i386/pthread_spin_init.c"
--- /dev/null
+++ b/fbtl/sysdeps/x86_64/pthread_spin_lock.S
@@ -0,0 +1,36 @@
+/* Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <lowlevellock.h>
+
+ .globl pthread_spin_lock
+ .type pthread_spin_lock,@function
+ .align 16
+pthread_spin_lock:
+1: LOCK
+ decl 0(%rdi)
+ jne 2f
+ xor %eax, %eax
+ ret
+
+ .align 16
+2: rep
+ nop
+ cmpl $0, 0(%rdi)
+ jg 1b
+ jmp 2b
+ .size pthread_spin_lock,.-pthread_spin_lock
--- /dev/null
+++ b/fbtl/sysdeps/x86_64/pthread_spin_trylock.S
@@ -0,0 +1,39 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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
--- /dev/null
+++ b/fbtl/sysdeps/x86_64/pthread_spin_unlock.S
@@ -0,0 +1,30 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+ .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
--- /dev/null
+++ b/fbtl/sysdeps/x86_64/pthreaddef.h
@@ -0,0 +1,44 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* 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.
+
+ We need to store post-AVX vector registers in the TCB and we want the
+ storage to be aligned to at least 32 bytes.
+
+ Some processors such as Intel Atom pay a big penalty on every
+ access using a segment override if that segment's base is not
+ aligned to the size of a cache line. (See Intel 64 and IA-32
+ Architectures Optimization Reference Manual, section 13.3.3.3,
+ "Segment Base".) On such machines, a cache line is 64 bytes. */
+#define TCB_ALIGNMENT 64
+
+
+/* Location of current stack frame. The frame pointer is not usable. */
+#define CURRENT_STACK_FRAME \
+ ({ register char *frame __asm__("rsp"); frame; })
--- /dev/null
+++ b/fbtl/sysdeps/x86_64/tcb-offsets.sym
@@ -0,0 +1,26 @@
+#include <sysdep.h>
+#include <tls.h>
+
+RESULT offsetof (struct pthread, result)
+TID offsetof (struct pthread, tid)
+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
+
+-- 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
--- /dev/null
+++ b/fbtl/sysdeps/x86_64/tls.h
@@ -0,0 +1,379 @@
+/* Definition for thread-local data handling. nptl/x86_64 version.
+ Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#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 <libc-internal.h>
+# include <kernel-features.h>
+# include <dl-dtv.h>
+
+/* Replacement type for __m128 since this file is included by ld.so,
+ which is compiled with -mno-sse. It must not change the alignment
+ of rtld_savespace_sse. */
+typedef struct
+{
+ int i[4];
+} __128bits;
+
+
+
+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 __glibc_reserved1;
+# endif
+ int __glibc_unused1;
+ /* Reservation of some values for the TM ABI. */
+ void *__private_tm[4];
+ /* GCC split stack support. */
+ void *__private_ss;
+ long int __glibc_reserved2;
+ /* Must be kept even if it is no longer used by glibc since programs,
+ like AddressSanitizer, depend on the size of tcbhead_t. */
+ __128bits __glibc_unused2[8][4] __attribute__ ((aligned (32)));
+
+ void *__padding[8];
+} tcbhead_t;
+
+#else /* __ASSEMBLER__ */
+# include <tcb-offsets.h>
+#endif
+
+
+/* Alignment requirement for the stack. */
+#define STACK_ALIGN 16
+
+
+#ifndef __ASSEMBLER__
+/* Get system call information. */
+# include <sysdep.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)
+
+/* 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
+# define TLS_DTV_AT_TP 0
+
+/* Get the thread descriptor definition. */
+# include <fbtl/descr.h>
+
+
+/* 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)
+
+
+/* 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) \
+ ({ 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 ("mov %%fs:%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_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 ((uint64_t) cast_to_integer (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 ((uint64_t) cast_to_integer (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) ()
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* tls.h */
--- /dev/null
+++ b/fbtl/tpp.c
@@ -0,0 +1,171 @@
+/* Thread Priority Protect helpers.
+ Copyright (C) 2006-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <atomic.h>
+#include <errno.h>
+#include <pthreadP.h>
+#include <sched.h>
+#include <stdlib.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;
+}
--- /dev/null
+++ b/fbtl/tst-_res1.c
@@ -0,0 +1,68 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Test whether _res in glibc 2.1.x and earlier (before __res_state()
+ was introduced) works. Portable programs should never do the
+ dirty things below. */
+
+#include <pthread.h>
+#include <resolv.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+void *tf (void *resp)
+{
+ if (resp == &_res || resp == __res_state ())
+ abort ();
+ _res.retry = 24;
+ return NULL;
+}
+
+void do_test (struct __res_state *resp)
+{
+ if (resp != &_res || resp != __res_state ())
+ abort ();
+ if (_res.retry != 12)
+ abort ();
+}
+
+int main (void)
+{
+#undef _res
+ extern struct __res_state _res;
+ pthread_t th;
+
+ _res.retry = 12;
+ if (pthread_create (&th, NULL, tf, &_res) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ do_test (&_res);
+
+ if (pthread_join (th, NULL) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ do_test (&_res);
+
+ exit (0);
+}
--- /dev/null
+++ b/fbtl/tst-_res1mod1.c
@@ -0,0 +1,22 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <resolv.h>
+#undef _res
+
+struct __res_state _res;
--- /dev/null
+++ b/fbtl/tst-_res1mod2.c
@@ -0,0 +1 @@
+/* Nothing. */
--- /dev/null
+++ b/fbtl/tst-abstime.c
@@ -0,0 +1,97 @@
+/* Copyright (C) 2010-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Schwab <schwab@redhat.com>, 2010.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+
+static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;
+static pthread_rwlock_t rw1 = PTHREAD_RWLOCK_INITIALIZER;
+static pthread_rwlock_t rw2 = PTHREAD_RWLOCK_INITIALIZER;
+static sem_t sem;
+
+static void *
+th (void *arg)
+{
+ long int res = 0;
+ int r;
+ struct timespec t = { -2, 0 };
+
+ r = pthread_mutex_timedlock (&m1, &t);
+ if (r != ETIMEDOUT)
+ {
+ puts ("pthread_mutex_timedlock did not return ETIMEDOUT");
+ res = 1;
+ }
+ r = pthread_rwlock_timedrdlock (&rw1, &t);
+ if (r != ETIMEDOUT)
+ {
+ puts ("pthread_rwlock_timedrdlock did not return ETIMEDOUT");
+ res = 1;
+ }
+ r = pthread_rwlock_timedwrlock (&rw2, &t);
+ if (r != ETIMEDOUT)
+ {
+ puts ("pthread_rwlock_timedwrlock did not return ETIMEDOUT");
+ res = 1;
+ }
+ return (void *) res;
+}
+
+static int
+do_test (void)
+{
+ int res = 0;
+ int r;
+ struct timespec t = { -2, 0 };
+ pthread_t pth;
+
+ sem_init (&sem, 0, 0);
+ r = sem_timedwait (&sem, &t);
+ if (r != -1 || errno != ETIMEDOUT)
+ {
+ puts ("sem_timedwait did not fail with ETIMEDOUT");
+ res = 1;
+ }
+
+ pthread_mutex_lock (&m1);
+ pthread_rwlock_wrlock (&rw1);
+ pthread_rwlock_rdlock (&rw2);
+ pthread_mutex_lock (&m2);
+ if (pthread_create (&pth, 0, th, 0) != 0)
+ {
+ puts ("cannot create thread");
+ return 1;
+ }
+ r = pthread_cond_timedwait (&c, &m2, &t);
+ if (r != ETIMEDOUT)
+ {
+ puts ("pthread_cond_timedwait did not return ETIMEDOUT");
+ res = 1;
+ }
+ void *thres;
+ pthread_join (pth, &thres);
+ return res | (thres != NULL);
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-align.c
@@ -0,0 +1,70 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <tst-stack-align.h>
+
+static void *
+tf (void *arg)
+{
+ bool ok = true;
+
+ puts ("in thread");
+
+ if (TEST_STACK_ALIGN ())
+ ok = false;
+
+ return ok ? NULL : (void *) -1l;
+}
+
+static int
+do_test (void)
+{
+ bool ok = true;
+
+ puts ("in main");
+
+ if (TEST_STACK_ALIGN ())
+ ok = false;
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ void *res;
+ if (pthread_join (th, &res) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ if (res != NULL)
+ ok = false;
+
+ return ok ? 0 : 1;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-align2.c
@@ -0,0 +1,95 @@
+/* Copyright (C) 2004-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sched.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <tst-stack-align.h>
+#include <stackinfo.h>
+
+static int
+f (void *arg)
+{
+ bool ok = true;
+
+ puts ("in f");
+
+ if (TEST_STACK_ALIGN ())
+ ok = false;
+
+ return ok ? 0 : 1;
+}
+
+static int
+do_test (void)
+{
+ bool ok = true;
+
+ puts ("in main");
+
+ if (TEST_STACK_ALIGN ())
+ ok = false;
+
+#ifdef __ia64__
+ extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base,
+ size_t __child_stack_size, int __flags,
+ void *__arg, ...);
+ char st[256 * 1024];
+ pid_t p = __clone2 (f, st, sizeof (st), 0, 0);
+#else
+ char st[128 * 1024] __attribute__ ((aligned));
+# if _STACK_GROWS_DOWN
+ pid_t p = clone (f, st + sizeof (st), 0, 0);
+# elif _STACK_GROWS_UP
+ pid_t p = clone (f, st, 0, 0);
+# else
+# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
+# endif
+#endif
+ if (p == -1)
+ {
+ printf("clone failed: %m\n");
+ return 1;
+ }
+
+ int e;
+ if (waitpid (p, &e, __WCLONE) != p)
+ {
+ puts ("waitpid failed");
+ kill (p, SIGKILL);
+ return 1;
+ }
+ if (!WIFEXITED (e))
+ {
+ if (WIFSIGNALED (e))
+ printf ("died from signal %s\n", strsignal (WTERMSIG (e)));
+ else
+ puts ("did not terminate correctly");
+ return 1;
+ }
+ if (WEXITSTATUS (e) != 0)
+ ok = false;
+
+ return ok ? 0 : 1;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-align3.c
@@ -0,0 +1,56 @@
+/* Copyright (C) 2005-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <tst-stack-align.h>
+
+static bool ok = true;
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+
+static void
+once_test (void)
+{
+ puts ("in once_test");
+
+ if (TEST_STACK_ALIGN ())
+ ok = false;
+}
+
+static int
+do_test (void)
+{
+ puts ("in main");
+
+ if (TEST_STACK_ALIGN ())
+ ok = false;
+
+ if (pthread_once (&once, once_test))
+ {
+ puts ("pthread once failed");
+ return 1;
+ }
+
+ return ok ? 0 : 1;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-atfork1.c
@@ -0,0 +1,120 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+
+static int val;
+
+
+static void
+prepare1 (void)
+{
+ val *= 2;
+}
+
+static void
+prepare2 (void)
+{
+ ++val;
+}
+
+static void
+parent1 (void)
+{
+ val += 4;
+}
+
+static void
+parent2 (void)
+{
+ val *= 4;
+}
+
+static void
+child1 (void)
+{
+ val += 8;
+}
+
+static void
+child2 (void)
+{
+ val *= 8;
+}
+
+
+static int
+do_test (void)
+{
+ pid_t pid;
+ int status = 0;
+
+ if (pthread_atfork (prepare1, parent1, child1) != 0)
+ {
+ puts ("1st atfork failed");
+ exit (1);
+ }
+ if (pthread_atfork (prepare2, parent2, child2) != 0)
+ {
+ puts ("2nd atfork failed");
+ exit (1);
+ }
+
+ pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+
+ if (pid != 0)
+ {
+ /* Parent. */
+ if (val != 24)
+ {
+ printf ("expected val=%d, got %d\n", 24, val);
+ exit (1);
+ }
+
+ if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+ {
+ puts ("waitpid failed");
+ exit (1);
+ }
+ }
+ else
+ {
+ /* Child. */
+ if (val != 80)
+ {
+ printf ("expected val=%d, got %d\n", 80, val);
+ exit (2);
+ }
+ }
+
+ return status;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-atfork2.c
@@ -0,0 +1,158 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <mcheck.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+
+/* Must be exported. */
+int val;
+
+static void
+prepare (void)
+{
+ val *= 2;
+}
+
+static void
+parent (void)
+{
+ val += 4;
+}
+
+static void
+child (void)
+{
+ val += 8;
+}
+
+
+static int
+do_test (void)
+{
+ mtrace ();
+
+ if (pthread_atfork (prepare, parent, child) != 0)
+ {
+ puts ("do_test: atfork failed");
+ exit (1);
+ }
+
+ void *h = dlopen ("tst-atfork2mod.so", RTLD_LAZY);
+ if (h == NULL)
+ {
+ printf ("dlopen failed: %s\n", dlerror ());
+ exit (1);
+ }
+
+ /* First trial of fork. */
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ puts ("1st fork failed");
+ exit (1);
+ }
+
+ if (pid == 0)
+ {
+ /* Child. */
+ if (val != 80)
+ {
+ printf ("1st: expected val=%d, got %d\n", 80, val);
+ exit (2);
+ }
+
+ exit (0);
+ }
+
+ /* Parent. */
+ if (val != 24)
+ {
+ printf ("1st: expected val=%d, got %d\n", 24, val);
+ exit (1);
+ }
+
+ int status;
+ if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+ {
+ puts ("1st waitpid failed");
+ exit (1);
+ }
+
+ if (status != 0)
+ exit (status);
+
+ puts ("unloading now");
+
+ /* Unload the module. */
+ if (dlclose (h) != 0)
+ {
+ puts ("dlclose failed");
+ exit (1);
+ }
+
+ puts ("2nd fork");
+
+ /* Second fork trial. */
+ val = 1;
+ pid = fork ();
+ if (pid == -1)
+ {
+ puts ("2nd fork failed");
+ exit (1);
+ }
+
+ if (pid == 0)
+ {
+ /* Child. */
+ if (val != 10)
+ {
+ printf ("2nd: expected val=%d, got %d\n", 10, val);
+ exit (3);
+ }
+
+ exit (0);
+ }
+
+ /* Parent. */
+ if (val != 6)
+ {
+ printf ("2nd: expected val=%d, got %d\n", 6, val);
+ exit (1);
+ }
+
+ if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+ {
+ puts ("2nd waitpid failed");
+ exit (1);
+ }
+
+ if (status != 0)
+ exit (status);
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-atfork2mod.c
@@ -0,0 +1,57 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+extern int val;
+
+
+static void
+prepare (void)
+{
+ ++val;
+}
+
+static void
+parent (void)
+{
+ val *= 4;
+}
+
+static void
+child (void)
+{
+ val *= 8;
+}
+
+static void
+__attribute__ ((constructor))
+init (void)
+{
+ extern void *__dso_handle;
+ printf ("dsohandle = %p\n", __dso_handle);
+
+ if (pthread_atfork (prepare, parent, child) != 0)
+ {
+ puts ("init: atfork failed");
+ exit (1);
+ }
+}
--- /dev/null
+++ b/fbtl/tst-attr1.c
@@ -0,0 +1,305 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+int
+do_test (void)
+{
+ int i;
+ pthread_attr_t a;
+
+ if (pthread_attr_init (&a) != 0)
+ {
+ puts ("attr_init failed");
+ exit (1);
+ }
+
+ pthread_mutexattr_t ma;
+
+ if (pthread_mutexattr_init (&ma) != 0)
+ {
+ puts ("mutexattr_init failed");
+ exit (1);
+ }
+
+ pthread_rwlockattr_t rwa;
+
+ if (pthread_rwlockattr_init (&rwa) != 0)
+ {
+ puts ("rwlockattr_init failed");
+ exit (1);
+ }
+
+ /* XXX Remove if default value is clear. */
+ pthread_attr_setinheritsched (&a, PTHREAD_INHERIT_SCHED);
+ pthread_attr_setschedpolicy (&a, SCHED_OTHER);
+ pthread_attr_setscope (&a, PTHREAD_SCOPE_SYSTEM);
+
+ for (i = 0; i < 10000; ++i)
+ {
+ long int r = random ();
+
+ if (r != PTHREAD_CREATE_DETACHED && r != PTHREAD_CREATE_JOINABLE)
+ {
+ int e = pthread_attr_setdetachstate (&a, r);
+
+ if (e == 0)
+ {
+ printf ("attr_setdetachstate with value %ld succeeded\n", r);
+ exit (1);
+ }
+ if (e != EINVAL)
+ {
+ puts ("attr_setdetachstate didn't return EINVAL");
+ exit (1);
+ }
+
+ int s;
+ if (pthread_attr_getdetachstate (&a, &s) != 0)
+ {
+ puts ("attr_getdetachstate failed");
+ exit (1);
+ }
+
+ if (s != PTHREAD_CREATE_JOINABLE)
+ {
+ printf ("\
+detach state changed to %d by invalid setdetachstate call\n", s);
+ exit (1);
+ }
+ }
+
+ if (r != PTHREAD_INHERIT_SCHED && r != PTHREAD_EXPLICIT_SCHED)
+ {
+ int e = pthread_attr_setinheritsched (&a, r);
+
+ if (e == 0)
+ {
+ printf ("attr_setinheritsched with value %ld succeeded\n", r);
+ exit (1);
+ }
+ if (e != EINVAL)
+ {
+ puts ("attr_setinheritsched didn't return EINVAL");
+ exit (1);
+ }
+
+ int s;
+ if (pthread_attr_getinheritsched (&a, &s) != 0)
+ {
+ puts ("attr_getinheritsched failed");
+ exit (1);
+ }
+
+ if (s != PTHREAD_INHERIT_SCHED)
+ {
+ printf ("\
+inheritsched changed to %d by invalid setinheritsched call\n", s);
+ exit (1);
+ }
+ }
+
+ if (r != SCHED_OTHER && r != SCHED_RR && r != SCHED_FIFO)
+ {
+ int e = pthread_attr_setschedpolicy (&a, r);
+
+ if (e == 0)
+ {
+ printf ("attr_setschedpolicy with value %ld succeeded\n", r);
+ exit (1);
+ }
+ if (e != EINVAL)
+ {
+ puts ("attr_setschedpolicy didn't return EINVAL");
+ exit (1);
+ }
+
+ int s;
+ if (pthread_attr_getschedpolicy (&a, &s) != 0)
+ {
+ puts ("attr_getschedpolicy failed");
+ exit (1);
+ }
+
+ if (s != SCHED_OTHER)
+ {
+ printf ("\
+schedpolicy changed to %d by invalid setschedpolicy call\n", s);
+ exit (1);
+ }
+ }
+
+ if (r != PTHREAD_SCOPE_SYSTEM && r != PTHREAD_SCOPE_PROCESS)
+ {
+ int e = pthread_attr_setscope (&a, r);
+
+ if (e == 0)
+ {
+ printf ("attr_setscope with value %ld succeeded\n", r);
+ exit (1);
+ }
+ if (e != EINVAL)
+ {
+ puts ("attr_setscope didn't return EINVAL");
+ exit (1);
+ }
+
+ int s;
+ if (pthread_attr_getscope (&a, &s) != 0)
+ {
+ puts ("attr_getscope failed");
+ exit (1);
+ }
+
+ if (s != PTHREAD_SCOPE_SYSTEM)
+ {
+ printf ("\
+contentionscope changed to %d by invalid setscope call\n", s);
+ exit (1);
+ }
+ }
+
+ if (r != PTHREAD_PROCESS_PRIVATE && r != PTHREAD_PROCESS_SHARED)
+ {
+ int e = pthread_mutexattr_setpshared (&ma, r);
+
+ if (e == 0)
+ {
+ printf ("mutexattr_setpshared with value %ld succeeded\n", r);
+ exit (1);
+ }
+ if (e != EINVAL)
+ {
+ puts ("mutexattr_setpshared didn't return EINVAL");
+ exit (1);
+ }
+
+ int s;
+ if (pthread_mutexattr_getpshared (&ma, &s) != 0)
+ {
+ puts ("mutexattr_getpshared failed");
+ exit (1);
+ }
+
+ if (s != PTHREAD_PROCESS_PRIVATE)
+ {
+ printf ("\
+pshared changed to %d by invalid mutexattr_setpshared call\n", s);
+ exit (1);
+ }
+
+ e = pthread_rwlockattr_setpshared (&rwa, r);
+
+ if (e == 0)
+ {
+ printf ("rwlockattr_setpshared with value %ld succeeded\n", r);
+ exit (1);
+ }
+ if (e != EINVAL)
+ {
+ puts ("rwlockattr_setpshared didn't return EINVAL");
+ exit (1);
+ }
+
+ if (pthread_rwlockattr_getpshared (&rwa, &s) != 0)
+ {
+ puts ("rwlockattr_getpshared failed");
+ exit (1);
+ }
+
+ if (s != PTHREAD_PROCESS_PRIVATE)
+ {
+ printf ("\
+pshared changed to %d by invalid rwlockattr_setpshared call\n", s);
+ exit (1);
+ }
+ }
+
+ if (r != PTHREAD_CANCEL_ENABLE && r != PTHREAD_CANCEL_DISABLE)
+ {
+ int e = pthread_setcancelstate (r, NULL);
+
+ if (e == 0)
+ {
+ printf ("setcancelstate with value %ld succeeded\n", r);
+ exit (1);
+ }
+
+ if (e != EINVAL)
+ {
+ puts ("setcancelstate didn't return EINVAL");
+ exit (1);
+ }
+
+ int s;
+ if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &s) != 0)
+ {
+ puts ("setcancelstate failed for PTHREAD_CANCEL_ENABLE");
+ exit (1);
+ }
+
+ if (s != PTHREAD_CANCEL_ENABLE)
+ {
+ puts ("invalid setcancelstate changed state");
+ exit (1);
+ }
+ }
+
+ if (r != PTHREAD_CANCEL_DEFERRED && r != PTHREAD_CANCEL_ASYNCHRONOUS)
+ {
+ int e = pthread_setcanceltype (r, NULL);
+
+ if (e == 0)
+ {
+ printf ("setcanceltype with value %ld succeeded\n", r);
+ exit (1);
+ }
+
+ if (e != EINVAL)
+ {
+ puts ("setcanceltype didn't return EINVAL");
+ exit (1);
+ }
+
+ int s;
+ if (pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &s) != 0)
+ {
+ puts ("setcanceltype failed for PTHREAD_CANCEL_DEFERRED");
+ exit (1);
+ }
+
+ if (s != PTHREAD_CANCEL_DEFERRED)
+ {
+ puts ("invalid setcanceltype changed state");
+ exit (1);
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-attr2.c
@@ -0,0 +1,316 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+int
+do_test (void)
+{
+ pthread_attr_t a;
+
+ if (pthread_attr_init (&a) != 0)
+ {
+ puts ("attr_init failed");
+ exit (1);
+ }
+
+ /* Check default value of detach state. */
+ int s;
+ if (pthread_attr_getdetachstate (&a, &s) != 0)
+ {
+ puts ("1st attr_getdestachstate failed");
+ exit (1);
+ }
+ if (s != PTHREAD_CREATE_JOINABLE)
+ {
+ printf ("\
+default detach state wrong: %d, expected %d (PTHREAD_CREATE_JOINABLE)\n",
+ s, PTHREAD_CREATE_JOINABLE);
+ exit (1);
+ }
+
+ int e = pthread_attr_setdetachstate (&a, PTHREAD_CREATE_DETACHED);
+ if (e != 0)
+ {
+ puts ("1st attr_setdetachstate failed");
+ exit (1);
+ }
+ if (pthread_attr_getdetachstate (&a, &s) != 0)
+ {
+ puts ("2nd attr_getdestachstate failed");
+ exit (1);
+ }
+ if (s != PTHREAD_CREATE_DETACHED)
+ {
+ puts ("PTHREAD_CREATE_DETACHED set, but not given back");
+ exit (1);
+ }
+
+ e = pthread_attr_setdetachstate (&a, PTHREAD_CREATE_JOINABLE);
+ if (e != 0)
+ {
+ puts ("2nd attr_setdetachstate failed");
+ exit (1);
+ }
+ if (pthread_attr_getdetachstate (&a, &s) != 0)
+ {
+ puts ("3rd attr_getdestachstate failed");
+ exit (1);
+ }
+ if (s != PTHREAD_CREATE_JOINABLE)
+ {
+ puts ("PTHREAD_CREATE_JOINABLE set, but not given back");
+ exit (1);
+ }
+
+
+ size_t g;
+ if (pthread_attr_getguardsize (&a, &g) != 0)
+ {
+ puts ("1st attr_getguardsize failed");
+ exit (1);
+ }
+ if (g != (size_t) sysconf (_SC_PAGESIZE))
+ {
+ printf ("default guardsize %zu, expected %ld (PAGESIZE)\n",
+ g, sysconf (_SC_PAGESIZE));
+ exit (1);
+ }
+
+ e = pthread_attr_setguardsize (&a, 0);
+ if (e != 0)
+ {
+ puts ("1st attr_setguardsize failed");
+ exit (1);
+ }
+ if (pthread_attr_getguardsize (&a, &g) != 0)
+ {
+ puts ("2nd attr_getguardsize failed");
+ exit (1);
+ }
+ if (g != 0)
+ {
+ printf ("guardsize set to zero but %zu returned\n", g);
+ exit (1);
+ }
+
+ e = pthread_attr_setguardsize (&a, 1);
+ if (e != 0)
+ {
+ puts ("2nd attr_setguardsize failed");
+ exit (1);
+ }
+ if (pthread_attr_getguardsize (&a, &g) != 0)
+ {
+ puts ("3rd attr_getguardsize failed");
+ exit (1);
+ }
+ if (g != 1)
+ {
+ printf ("guardsize set to 1 but %zu returned\n", g);
+ exit (1);
+ }
+
+
+ if (pthread_attr_getinheritsched (&a, &s) != 0)
+ {
+ puts ("1st attr_getinheritsched failed");
+ exit (1);
+ }
+ /* XXX What is the correct default value. */
+ if (s != PTHREAD_INHERIT_SCHED && s != PTHREAD_EXPLICIT_SCHED)
+ {
+ puts ("incorrect default value for inheritsched");
+ exit (1);
+ }
+
+ e = pthread_attr_setinheritsched (&a, PTHREAD_EXPLICIT_SCHED);
+ if (e != 0)
+ {
+ puts ("1st attr_setinheritsched failed");
+ exit (1);
+ }
+ if (pthread_attr_getinheritsched (&a, &s) != 0)
+ {
+ puts ("2nd attr_getinheritsched failed");
+ exit (1);
+ }
+ if (s != PTHREAD_EXPLICIT_SCHED)
+ {
+ printf ("inheritsched set to PTHREAD_EXPLICIT_SCHED, but got %d\n", s);
+ exit (1);
+ }
+
+ e = pthread_attr_setinheritsched (&a, PTHREAD_INHERIT_SCHED);
+ if (e != 0)
+ {
+ puts ("2nd attr_setinheritsched failed");
+ exit (1);
+ }
+ if (pthread_attr_getinheritsched (&a, &s) != 0)
+ {
+ puts ("3rd attr_getinheritsched failed");
+ exit (1);
+ }
+ if (s != PTHREAD_INHERIT_SCHED)
+ {
+ printf ("inheritsched set to PTHREAD_INHERIT_SCHED, but got %d\n", s);
+ exit (1);
+ }
+
+
+ if (pthread_attr_getschedpolicy (&a, &s) != 0)
+ {
+ puts ("1st attr_getschedpolicy failed");
+ exit (1);
+ }
+ /* XXX What is the correct default value. */
+ if (s != SCHED_OTHER && s != SCHED_FIFO && s != SCHED_RR)
+ {
+ puts ("incorrect default value for schedpolicy");
+ exit (1);
+ }
+
+ e = pthread_attr_setschedpolicy (&a, SCHED_RR);
+ if (e != 0)
+ {
+ puts ("1st attr_setschedpolicy failed");
+ exit (1);
+ }
+ if (pthread_attr_getschedpolicy (&a, &s) != 0)
+ {
+ puts ("2nd attr_getschedpolicy failed");
+ exit (1);
+ }
+ if (s != SCHED_RR)
+ {
+ printf ("schedpolicy set to SCHED_RR, but got %d\n", s);
+ exit (1);
+ }
+
+ e = pthread_attr_setschedpolicy (&a, SCHED_FIFO);
+ if (e != 0)
+ {
+ puts ("2nd attr_setschedpolicy failed");
+ exit (1);
+ }
+ if (pthread_attr_getschedpolicy (&a, &s) != 0)
+ {
+ puts ("3rd attr_getschedpolicy failed");
+ exit (1);
+ }
+ if (s != SCHED_FIFO)
+ {
+ printf ("schedpolicy set to SCHED_FIFO, but got %d\n", s);
+ exit (1);
+ }
+
+ e = pthread_attr_setschedpolicy (&a, SCHED_OTHER);
+ if (e != 0)
+ {
+ puts ("3rd attr_setschedpolicy failed");
+ exit (1);
+ }
+ if (pthread_attr_getschedpolicy (&a, &s) != 0)
+ {
+ puts ("4th attr_getschedpolicy failed");
+ exit (1);
+ }
+ if (s != SCHED_OTHER)
+ {
+ printf ("schedpolicy set to SCHED_OTHER, but got %d\n", s);
+ exit (1);
+ }
+
+
+ if (pthread_attr_getscope (&a, &s) != 0)
+ {
+ puts ("1st attr_getscope failed");
+ exit (1);
+ }
+ /* XXX What is the correct default value. */
+ if (s != PTHREAD_SCOPE_SYSTEM && s != PTHREAD_SCOPE_PROCESS)
+ {
+ puts ("incorrect default value for contentionscope");
+ exit (1);
+ }
+
+ e = pthread_attr_setscope (&a, PTHREAD_SCOPE_PROCESS);
+ if (e != ENOTSUP)
+ {
+ if (e != 0)
+ {
+ puts ("1st attr_setscope failed");
+ exit (1);
+ }
+ if (pthread_attr_getscope (&a, &s) != 0)
+ {
+ puts ("2nd attr_getscope failed");
+ exit (1);
+ }
+ if (s != PTHREAD_SCOPE_PROCESS)
+ {
+ printf ("\
+contentionscope set to PTHREAD_SCOPE_PROCESS, but got %d\n", s);
+ exit (1);
+ }
+ }
+
+ e = pthread_attr_setscope (&a, PTHREAD_SCOPE_SYSTEM);
+ if (e != 0)
+ {
+ puts ("2nd attr_setscope failed");
+ exit (1);
+ }
+ if (pthread_attr_getscope (&a, &s) != 0)
+ {
+ puts ("3rd attr_getscope failed");
+ exit (1);
+ }
+ if (s != PTHREAD_SCOPE_SYSTEM)
+ {
+ printf ("contentionscope set to PTHREAD_SCOPE_SYSTEM, but got %d\n", s);
+ exit (1);
+ }
+
+ char buf[1];
+ e = pthread_attr_setstack (&a, buf, 1);
+ if (e != EINVAL)
+ {
+ puts ("setstack with size 1 did not produce EINVAL");
+ exit (1);
+ }
+
+ e = pthread_attr_setstacksize (&a, 1);
+ if (e != EINVAL)
+ {
+ puts ("setstacksize with size 1 did not produce EINVAL");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-attr3.c
@@ -0,0 +1,421 @@
+/* pthread_getattr_np test.
+ Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <error.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <stackinfo.h>
+
+static void *
+tf (void *arg)
+{
+ pthread_attr_t a, *ap, a2;
+ int err;
+ void *result = NULL;
+
+ if (arg == NULL)
+ {
+ ap = &a2;
+ err = pthread_attr_init (ap);
+ if (err)
+ {
+ error (0, err, "pthread_attr_init failed");
+ return tf;
+ }
+ }
+ else
+ ap = (pthread_attr_t *) arg;
+
+ err = pthread_getattr_np (pthread_self (), &a);
+ if (err)
+ {
+ error (0, err, "pthread_getattr_np failed");
+ result = tf;
+ }
+
+ int detachstate1, detachstate2;
+ err = pthread_attr_getdetachstate (&a, &detachstate1);
+ if (err)
+ {
+ error (0, err, "pthread_attr_getdetachstate failed");
+ result = tf;
+ }
+ else
+ {
+ err = pthread_attr_getdetachstate (ap, &detachstate2);
+ if (err)
+ {
+ error (0, err, "pthread_attr_getdetachstate failed");
+ result = tf;
+ }
+ else if (detachstate1 != detachstate2)
+ {
+ error (0, 0, "detachstate differs %d != %d",
+ detachstate1, detachstate2);
+ result = tf;
+ }
+ }
+
+ void *stackaddr;
+ size_t stacksize;
+ err = pthread_attr_getstack (&a, &stackaddr, &stacksize);
+ if (err)
+ {
+ error (0, err, "pthread_attr_getstack failed");
+ result = tf;
+ }
+ else if ((void *) &a < stackaddr
+ || (void *) &a >= stackaddr + stacksize)
+ {
+ error (0, 0, "pthread_attr_getstack returned range does not cover thread's stack");
+ result = tf;
+ }
+ else
+ printf ("thread stack %p-%p (0x%zx)\n", stackaddr, stackaddr + stacksize,
+ stacksize);
+
+ size_t guardsize1, guardsize2;
+ err = pthread_attr_getguardsize (&a, &guardsize1);
+ if (err)
+ {
+ error (0, err, "pthread_attr_getguardsize failed");
+ result = tf;
+ }
+ else
+ {
+ err = pthread_attr_getguardsize (ap, &guardsize2);
+ if (err)
+ {
+ error (0, err, "pthread_attr_getguardsize failed");
+ result = tf;
+ }
+ else if (guardsize1 != guardsize2)
+ {
+ error (0, 0, "guardsize differs %zd != %zd",
+ guardsize1, guardsize2);
+ result = tf;
+ }
+ else
+ printf ("thread guardsize %zd\n", guardsize1);
+ }
+
+ int scope1, scope2;
+ err = pthread_attr_getscope (&a, &scope1);
+ if (err)
+ {
+ error (0, err, "pthread_attr_getscope failed");
+ result = tf;
+ }
+ else
+ {
+ err = pthread_attr_getscope (ap, &scope2);
+ if (err)
+ {
+ error (0, err, "pthread_attr_getscope failed");
+ result = tf;
+ }
+ else if (scope1 != scope2)
+ {
+ error (0, 0, "scope differs %d != %d",
+ scope1, scope2);
+ result = tf;
+ }
+ }
+
+ int inheritsched1, inheritsched2;
+ err = pthread_attr_getinheritsched (&a, &inheritsched1);
+ if (err)
+ {
+ error (0, err, "pthread_attr_getinheritsched failed");
+ result = tf;
+ }
+ else
+ {
+ err = pthread_attr_getinheritsched (ap, &inheritsched2);
+ if (err)
+ {
+ error (0, err, "pthread_attr_getinheritsched failed");
+ result = tf;
+ }
+ else if (inheritsched1 != inheritsched2)
+ {
+ error (0, 0, "inheritsched differs %d != %d",
+ inheritsched1, inheritsched2);
+ result = tf;
+ }
+ }
+
+ cpu_set_t c1, c2;
+ err = pthread_getaffinity_np (pthread_self (), sizeof (c1), &c1);
+ if (err == 0)
+ {
+ err = pthread_attr_getaffinity_np (&a, sizeof (c2), &c2);
+ if (err)
+ {
+ error (0, err, "pthread_attr_getaffinity_np failed");
+ result = tf;
+ }
+ else if (memcmp (&c1, &c2, sizeof (c1)))
+ {
+ error (0, 0, "pthread_attr_getaffinity_np returned different CPU mask than pthread_getattr_np");
+ result = tf;
+ }
+ }
+
+ err = pthread_attr_destroy (&a);
+ if (err)
+ {
+ error (0, err, "pthread_attr_destroy failed");
+ result = tf;
+ }
+
+ if (ap == &a2)
+ {
+ err = pthread_attr_destroy (ap);
+ if (err)
+ {
+ error (0, err, "pthread_attr_destroy failed");
+ result = tf;
+ }
+ }
+
+ return result;
+}
+
+
+static int
+do_test (void)
+{
+ int result = 0;
+ pthread_attr_t a;
+ cpu_set_t c1, c2;
+
+ int err = pthread_attr_init (&a);
+ if (err)
+ {
+ error (0, err, "pthread_attr_init failed");
+ result = 1;
+ }
+
+ err = pthread_attr_getaffinity_np (&a, sizeof (c1), &c1);
+ if (err && err != ENOSYS)
+ {
+ error (0, err, "pthread_attr_getaffinity_np failed");
+ result = 1;
+ }
+
+ err = pthread_attr_destroy (&a);
+ if (err)
+ {
+ error (0, err, "pthread_attr_destroy failed");
+ result = 1;
+ }
+
+ err = pthread_getattr_np (pthread_self (), &a);
+ if (err)
+ {
+ error (0, err, "pthread_getattr_np failed");
+ result = 1;
+ }
+
+ int detachstate;
+ err = pthread_attr_getdetachstate (&a, &detachstate);
+ if (err)
+ {
+ error (0, err, "pthread_attr_getdetachstate failed");
+ result = 1;
+ }
+ else if (detachstate != PTHREAD_CREATE_JOINABLE)
+ {
+ error (0, 0, "initial thread not joinable");
+ result = 1;
+ }
+
+ void *stackaddr;
+ size_t stacksize;
+ err = pthread_attr_getstack (&a, &stackaddr, &stacksize);
+ if (err)
+ {
+ error (0, err, "pthread_attr_getstack failed");
+ result = 1;
+ }
+ else if ((void *) &a < stackaddr
+ || (void *) &a >= stackaddr + stacksize)
+ {
+ error (0, 0, "pthread_attr_getstack returned range does not cover main's stack");
+ result = 1;
+ }
+ else
+ printf ("initial thread stack %p-%p (0x%zx)\n", stackaddr,
+ stackaddr + stacksize, stacksize);
+
+ size_t guardsize;
+ err = pthread_attr_getguardsize (&a, &guardsize);
+ if (err)
+ {
+ error (0, err, "pthread_attr_getguardsize failed");
+ result = 1;
+ }
+ else if (guardsize != 0)
+ {
+ error (0, 0, "pthread_attr_getguardsize returned %zd != 0",
+ guardsize);
+ result = 1;
+ }
+
+ int scope;
+ err = pthread_attr_getscope (&a, &scope);
+ if (err)
+ {
+ error (0, err, "pthread_attr_getscope failed");
+ result = 1;
+ }
+ else if (scope != PTHREAD_SCOPE_SYSTEM)
+ {
+ error (0, 0, "pthread_attr_getscope returned %d != PTHREAD_SCOPE_SYSTEM",
+ scope);
+ result = 1;
+ }
+
+ int inheritsched;
+ err = pthread_attr_getinheritsched (&a, &inheritsched);
+ if (err)
+ {
+ error (0, err, "pthread_attr_getinheritsched failed");
+ result = 1;
+ }
+ else if (inheritsched != PTHREAD_INHERIT_SCHED)
+ {
+ error (0, 0, "pthread_attr_getinheritsched returned %d != PTHREAD_INHERIT_SCHED",
+ inheritsched);
+ result = 1;
+ }
+
+ err = pthread_getaffinity_np (pthread_self (), sizeof (c1), &c1);
+ if (err == 0)
+ {
+ err = pthread_attr_getaffinity_np (&a, sizeof (c2), &c2);
+ if (err)
+ {
+ error (0, err, "pthread_attr_getaffinity_np failed");
+ result = 1;
+ }
+ else if (memcmp (&c1, &c2, sizeof (c1)))
+ {
+ error (0, 0, "pthread_attr_getaffinity_np returned different CPU mask than pthread_getattr_np");
+ result = 1;
+ }
+ }
+
+ err = pthread_attr_destroy (&a);
+ if (err)
+ {
+ error (0, err, "pthread_attr_destroy failed");
+ result = 1;
+ }
+
+ pthread_t th;
+ err = pthread_create (&th, NULL, tf, NULL);
+ if (err)
+ {
+ error (0, err, "pthread_create #1 failed");
+ result = 1;
+ }
+ else
+ {
+ void *ret;
+ err = pthread_join (th, &ret);
+ if (err)
+ {
+ error (0, err, "pthread_join #1 failed");
+ result = 1;
+ }
+ else if (ret != NULL)
+ result = 1;
+ }
+
+ err = pthread_attr_init (&a);
+ if (err)
+ {
+ error (0, err, "pthread_attr_init failed");
+ result = 1;
+ }
+
+ err = pthread_create (&th, &a, tf, &a);
+ if (err)
+ {
+ error (0, err, "pthread_create #2 failed");
+ result = 1;
+ }
+ else
+ {
+ void *ret;
+ err = pthread_join (th, &ret);
+ if (err)
+ {
+ error (0, err, "pthread_join #2 failed");
+ result = 1;
+ }
+ else if (ret != NULL)
+ result = 1;
+ }
+
+ err = pthread_attr_setguardsize (&a, 16 * sysconf (_SC_PAGESIZE));
+ if (err)
+ {
+ error (0, err, "pthread_attr_setguardsize failed");
+ result = 1;
+ }
+
+ err = pthread_create (&th, &a, tf, &a);
+ if (err)
+ {
+ error (0, err, "pthread_create #3 failed");
+ result = 1;
+ }
+ else
+ {
+ void *ret;
+ err = pthread_join (th, &ret);
+ if (err)
+ {
+ error (0, err, "pthread_join #3 failed");
+ result = 1;
+ }
+ else if (ret != NULL)
+ result = 1;
+ }
+
+ err = pthread_attr_destroy (&a);
+ if (err)
+ {
+ error (0, err, "pthread_attr_destroy failed");
+ result = 1;
+ }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-backtrace1.c
@@ -0,0 +1,85 @@
+/* Copyright (C) 2004-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <execinfo.h>
+#include <pthread.h>
+#include <stdio.h>
+
+#define BT_SIZE 64
+void *bt_array[BT_SIZE];
+int bt_cnt;
+
+int
+do_bt (void)
+{
+ bt_cnt = backtrace (bt_array, BT_SIZE);
+ return 56;
+}
+
+int
+call_do_bt (void)
+{
+ return do_bt () + 1;
+}
+
+void *
+tf (void *arg)
+{
+ if (call_do_bt () != 57)
+ return (void *) 1L;
+ return NULL;
+}
+
+int
+do_test (void)
+{
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL))
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ void *res;
+ if (pthread_join (th, &res))
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ if (res != NULL)
+ {
+ puts ("thread failed");
+ return 1;
+ }
+
+ char **text = backtrace_symbols (bt_array, bt_cnt);
+ if (text == NULL)
+ {
+ puts ("backtrace_symbols failed");
+ return 1;
+ }
+
+ for (int i = 0; i < bt_cnt; ++i)
+ puts (text[i]);
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-barrier1.c
@@ -0,0 +1,70 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+
+
+static int
+do_test (void)
+{
+ pthread_barrier_t b;
+ int e;
+ int cnt;
+
+ e = pthread_barrier_init (&b, NULL, 0);
+ if (e == 0)
+ {
+ puts ("barrier_init with count 0 succeeded");
+ return 1;
+ }
+ if (e != EINVAL)
+ {
+ puts ("barrier_init with count 0 didn't return EINVAL");
+ return 1;
+ }
+
+ if (pthread_barrier_init (&b, NULL, 1) != 0)
+ {
+ puts ("real barrier_init failed");
+ return 1;
+ }
+
+ for (cnt = 0; cnt < 10; ++cnt)
+ {
+ e = pthread_barrier_wait (&b);
+
+ if (e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait didn't return PTHREAD_BARRIER_SERIAL_THREAD");
+ return 1;
+ }
+ }
+
+ if (pthread_barrier_destroy (&b) != 0)
+ {
+ puts ("barrier_destroy failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-barrier2.c
@@ -0,0 +1,184 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+
+static int
+do_test (void)
+{
+ size_t ps = sysconf (_SC_PAGESIZE);
+ char tmpfname[] = "/tmp/tst-barrier2.XXXXXX";
+ char data[ps];
+ void *mem;
+ int fd;
+ pthread_barrier_t *b;
+ pthread_barrierattr_t a;
+ pid_t pid;
+ int serials = 0;
+ int cnt;
+ int status;
+ int p;
+
+ fd = mkstemp (tmpfname);
+ if (fd == -1)
+ {
+ printf ("cannot open temporary file: %m\n");
+ return 1;
+ }
+
+ /* Make sure it is always removed. */
+ unlink (tmpfname);
+
+ /* Create one page of data. */
+ memset (data, '\0', ps);
+
+ /* Write the data to the file. */
+ if (write (fd, data, ps) != (ssize_t) ps)
+ {
+ puts ("short write");
+ return 1;
+ }
+
+ mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (mem == MAP_FAILED)
+ {
+ printf ("mmap failed: %m\n");
+ return 1;
+ }
+
+ b = (pthread_barrier_t *) (((uintptr_t) mem + __alignof (pthread_barrier_t))
+ & ~(__alignof (pthread_barrier_t) - 1));
+
+ if (pthread_barrierattr_init (&a) != 0)
+ {
+ puts ("barrierattr_init failed");
+ return 1;
+ }
+
+ if (pthread_barrierattr_getpshared (&a, &p) != 0)
+ {
+ puts ("1st barrierattr_getpshared failed");
+ return 1;
+ }
+
+ if (p != PTHREAD_PROCESS_PRIVATE)
+ {
+ puts ("default pshared value wrong");
+ return 1;
+ }
+
+ if (pthread_barrierattr_setpshared (&a, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("barrierattr_setpshared failed");
+ return 1;
+ }
+
+ if (pthread_barrierattr_getpshared (&a, &p) != 0)
+ {
+ puts ("2nd barrierattr_getpshared failed");
+ return 1;
+ }
+
+ if (p != PTHREAD_PROCESS_SHARED)
+ {
+ puts ("pshared value after setpshared call wrong");
+ return 1;
+ }
+
+ if (pthread_barrier_init (b, &a, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ if (pthread_barrierattr_destroy (&a) != 0)
+ {
+ puts ("barrierattr_destroy failed");
+ return 1;
+ }
+
+ puts ("going to fork now");
+ pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ return 1;
+ }
+
+ /* Just to be sure we don't hang forever. */
+ alarm (4);
+
+#define N 30
+ for (cnt = 0; cnt < N; ++cnt)
+ {
+ int e;
+
+ e = pthread_barrier_wait (b);
+ if (e == PTHREAD_BARRIER_SERIAL_THREAD)
+ ++serials;
+ else if (e != 0)
+ {
+ printf ("%s: barrier_wait returned value %d != 0 and PTHREAD_BARRIER_SERIAL_THREAD\n",
+ pid == 0 ? "child" : "parent", e);
+ return 1;
+ }
+ }
+
+ alarm (0);
+
+ printf ("%s: was %d times the serial thread\n",
+ pid == 0 ? "child" : "parent", serials);
+
+ if (pid == 0)
+ /* The child. Pass the number of times we had the serializing
+ thread back to the parent. */
+ exit (serials);
+
+ if (waitpid (pid, &status, 0) != pid)
+ {
+ puts ("waitpid failed");
+ return 1;
+ }
+
+ if (!WIFEXITED (status))
+ {
+ puts ("child exited abnormally");
+ return 1;
+ }
+
+ if (WEXITSTATUS (status) + serials != N)
+ {
+ printf ("total number of serials is %d, expected %d\n",
+ WEXITSTATUS (status) + serials, N);
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-barrier3.c
@@ -0,0 +1,153 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Test of POSIX barriers. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define NTHREADS 20
+
+#define ROUNDS 20
+
+static pthread_barrier_t barriers[NTHREADS];
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+static int counters[NTHREADS];
+static int serial[NTHREADS];
+
+static void *
+worker (void *arg)
+{
+ void *result = NULL;
+ int nr = (long int) arg;
+ int i;
+
+ for (i = 0; i < ROUNDS; ++i)
+ {
+ int j;
+ int retval;
+
+ if (nr == 0)
+ {
+ memset (counters, '\0', sizeof (counters));
+ memset (serial, '\0', sizeof (serial));
+ }
+
+ retval = pthread_barrier_wait (&barriers[NTHREADS - 1]);
+ if (retval != 0 && retval != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("thread %d failed to wait for all the others\n", nr);
+ result = (void *) 1;
+ }
+
+ for (j = nr; j < NTHREADS; ++j)
+ {
+ /* Increment the counter for this round. */
+ pthread_mutex_lock (&lock);
+ ++counters[j];
+ pthread_mutex_unlock (&lock);
+
+ /* Wait for the rest. */
+ retval = pthread_barrier_wait (&barriers[j]);
+
+ /* Test the result. */
+ if (nr == 0 && counters[j] != j + 1)
+ {
+ printf ("barrier in round %d released but count is %d\n",
+ j, counters[j]);
+ result = (void *) 1;
+ }
+
+ if (retval != 0)
+ {
+ if (retval != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("thread %d in round %d has nonzero return value != PTHREAD_BARRIER_SERIAL_THREAD\n",
+ nr, j);
+ result = (void *) 1;
+ }
+ else
+ {
+ pthread_mutex_lock (&lock);
+ ++serial[j];
+ pthread_mutex_unlock (&lock);
+ }
+ }
+
+ /* Wait for the rest again. */
+ retval = pthread_barrier_wait (&barriers[j]);
+
+ /* Now we can check whether exactly one thread was serializing. */
+ if (nr == 0 && serial[j] != 1)
+ {
+ printf ("not exactly one serial thread in round %d\n", j);
+ result = (void *) 1;
+ }
+ }
+ }
+
+ return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 60
+static int
+do_test (void)
+{
+ pthread_t threads[NTHREADS];
+ int i;
+ void *res;
+ int result = 0;
+
+ /* Initialized the barrier variables. */
+ for (i = 0; i < NTHREADS; ++i)
+ if (pthread_barrier_init (&barriers[i], NULL, i + 1) != 0)
+ {
+ printf ("Failed to initialize barrier %d\n", i);
+ exit (1);
+ }
+
+ /* Start the threads. */
+ for (i = 0; i < NTHREADS; ++i)
+ if (pthread_create (&threads[i], NULL, worker, (void *) (long int) i) != 0)
+ {
+ printf ("Failed to start thread %d\n", i);
+ exit (1);
+ }
+
+ /* And wait for them. */
+ for (i = 0; i < NTHREADS; ++i)
+ if (pthread_join (threads[i], &res) != 0 || res != NULL)
+ {
+ printf ("thread %d returned a failure\n", i);
+ result = 1;
+ }
+ else
+ printf ("joined threads %d\n", i);
+
+ if (result == 0)
+ puts ("all OK");
+
+ return result;
+}
+
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-barrier4.c
@@ -0,0 +1,121 @@
+/* Copyright (C) 2004-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* This is a test for behavior not guaranteed by POSIX. */
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_barrier_t b1;
+static pthread_barrier_t b2;
+
+
+#define N 20
+
+static void *
+tf (void *arg)
+{
+ int round = 0;
+
+ while (round++ < 30)
+ {
+ if (pthread_barrier_wait (&b1) == PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ pthread_barrier_destroy (&b1);
+ if (pthread_barrier_init (&b1, NULL, N) != 0)
+ {
+ puts ("tf: 1st barrier_init failed");
+ exit (1);
+ }
+ }
+
+ if (pthread_barrier_wait (&b2) == PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ pthread_barrier_destroy (&b2);
+ if (pthread_barrier_init (&b2, NULL, N) != 0)
+ {
+ puts ("tf: 2nd barrier_init failed");
+ exit (1);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_attr_t at;
+ int cnt;
+
+ if (pthread_attr_init (&at) != 0)
+ {
+ puts ("attr_init failed");
+ return 1;
+ }
+
+ if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+ if (pthread_barrier_init (&b1, NULL, N) != 0)
+ {
+ puts ("1st barrier_init failed");
+ return 1;
+ }
+
+ if (pthread_barrier_init (&b2, NULL, N) != 0)
+ {
+ puts ("2nd barrier_init failed");
+ return 1;
+ }
+
+ pthread_t th[N - 1];
+ for (cnt = 0; cnt < N - 1; ++cnt)
+ if (pthread_create (&th[cnt], &at, tf, NULL) != 0)
+ {
+ puts ("pthread_create failed");
+ return 1;
+ }
+
+ if (pthread_attr_destroy (&at) != 0)
+ {
+ puts ("attr_destroy failed");
+ return 1;
+ }
+
+ tf (NULL);
+
+ for (cnt = 0; cnt < N - 1; ++cnt)
+ if (pthread_join (th[cnt], NULL) != 0)
+ {
+ puts ("pthread_join failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-basic1.c
@@ -0,0 +1,81 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+
+static pid_t pid;
+
+static void *
+tf (void *a)
+{
+ if (getpid () != pid)
+ {
+ write (2, "pid mismatch\n", 13);
+ _exit (1);
+ }
+
+ return a;
+}
+
+
+int
+do_test (void)
+{
+ pid = getpid ();
+
+#define N 2
+ pthread_t t[N];
+ int i;
+
+ for (i = 0; i < N; ++i)
+ if (pthread_create (&t[i], NULL, tf, (void *) (long int) (i + 1)) != 0)
+ {
+ write (2, "create failed\n", 14);
+ _exit (1);
+ }
+ else
+ printf ("created thread %d\n", i);
+
+ for (i = 0; i < N; ++i)
+ {
+ void *r;
+ int e;
+ if ((e = pthread_join (t[i], &r)) != 0)
+ {
+ printf ("join failed: %d\n", e);
+ _exit (1);
+ }
+ else if (r != (void *) (long int) (i + 1))
+ {
+ write (2, "result wrong\n", 13);
+ _exit (1);
+ }
+ else
+ printf ("joined thread %d\n", i);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-basic2.c
@@ -0,0 +1,120 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+#define N 20
+
+static pthread_t th[N];
+static pthread_mutex_t lock[N];
+
+
+static void *tf (void *a)
+{
+ uintptr_t idx = (uintptr_t) a;
+
+ pthread_mutex_lock (&lock[idx]);
+
+ return pthread_equal (pthread_self (), th[idx]) ? NULL : (void *) 1l;
+}
+
+
+int
+do_test (void)
+{
+ if (pthread_equal (pthread_self (), pthread_self ()) == 0)
+ {
+ puts ("pthread_equal (pthread_self (), pthread_self ()) failed");
+ exit (1);
+ }
+
+ pthread_attr_t at;
+
+ if (pthread_attr_init (&at) != 0)
+ {
+ puts ("attr_init failed");
+ return 1;
+ }
+
+ if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ if (pthread_mutex_init (&lock[i], NULL) != 0)
+ {
+ puts ("mutex_init failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_lock (&lock[i]) != 0)
+ {
+ puts ("mutex_lock failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th[i], &at, tf, (void *) (long int) i) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&lock[i]) != 0)
+ {
+ puts ("mutex_unlock failed");
+ exit (1);
+ }
+
+ printf ("created thread %d\n", i);
+ }
+
+ if (pthread_attr_destroy (&at) != 0)
+ {
+ puts ("attr_destroy failed");
+ return 1;
+ }
+
+ int result = 0;
+ for (i = 0; i < N; ++i)
+ {
+ void *r;
+ int e;
+ if ((e = pthread_join (th[i], &r)) != 0)
+ {
+ printf ("join failed: %d\n", e);
+ _exit (1);
+ }
+ else if (r != NULL)
+ result = 1;
+ }
+
+ return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-basic3.c
@@ -0,0 +1,86 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static int nrunning = 1;
+
+
+static void
+final_test (void)
+{
+ puts ("final_test has been called");
+
+#define THE_SIGNAL SIGUSR1
+ kill (getpid (), SIGUSR1);
+}
+
+
+static void *
+tf (void *a)
+{
+ if (pthread_join ((pthread_t) a, NULL) != 0)
+ {
+ printf ("join failed while %d are running\n", nrunning);
+ _exit (1);
+ }
+
+ printf ("%2d left\n", --nrunning);
+
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+#define N 20
+ pthread_t t[N];
+ pthread_t last = pthread_self ();
+ int i;
+
+ atexit (final_test);
+
+ printf ("starting %d + 1 threads\n", N);
+ for (i = 0; i < N; ++i)
+ {
+ if (pthread_create (&t[i], NULL, tf, (void *) last) != 0)
+ {
+ puts ("create failed");
+ _exit (1);
+ }
+
+ ++nrunning;
+
+ last = t[i];
+ }
+
+ printf ("%2d left\n", --nrunning);
+
+ pthread_exit (NULL);
+}
+
+
+#define EXPECTED_SIGNAL THE_SIGNAL
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-basic4.c
@@ -0,0 +1,100 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+
+static void
+final_test (void)
+{
+ puts ("final_test has been called");
+
+#define THE_SIGNAL SIGUSR1
+ kill (getpid (), SIGUSR1);
+}
+
+
+static void *
+tf (void *a)
+{
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+
+ if (pid == 0)
+ {
+ atexit (final_test);
+
+ pthread_exit (NULL);
+ }
+
+ int r;
+ int e = TEMP_FAILURE_RETRY (waitpid (pid, &r, 0));
+ if (e != pid)
+ {
+ puts ("waitpid failed");
+ exit (1);
+ }
+
+ if (! WIFSIGNALED (r))
+ {
+ puts ("child not signled");
+ exit (1);
+ }
+
+ if (WTERMSIG (r) != THE_SIGNAL)
+ {
+ puts ("child's termination signal wrong");
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ _exit (1);
+ }
+
+ if (pthread_join (th, NULL) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-basic5.c
@@ -0,0 +1,73 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+
+int
+do_test (void)
+{
+ int c = pthread_getconcurrency ();
+ if (c != 0)
+ {
+ puts ("initial concurrencylevel wrong");
+ exit (1);
+ }
+
+ if (pthread_setconcurrency (1) != 0)
+ {
+ puts ("setconcurrency failed");
+ exit (1);
+ }
+
+ c = pthread_getconcurrency ();
+ if (c != 1)
+ {
+ puts ("getconcurrency didn't return the value previous set");
+ exit (1);
+ }
+
+ int e = pthread_setconcurrency (-1);
+ if (e == 0)
+ {
+ puts ("setconcurrency of negative value didn't failed");
+ exit (1);
+ }
+ if (e != EINVAL)
+ {
+ puts ("setconcurrency didn't return EINVAL for negative value");
+ exit (1);
+ }
+
+ c = pthread_getconcurrency ();
+ if (c != 1)
+ {
+ puts ("invalid getconcurrency changed level");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-basic6.c
@@ -0,0 +1,131 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+static char *p;
+
+static pthread_barrier_t b;
+#define BT \
+ e = pthread_barrier_wait (&b); \
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) \
+ { \
+ puts ("barrier_wait failed"); \
+ exit (1); \
+ }
+
+
+static void *
+tf (void *a)
+{
+ int e;
+
+ BT;
+
+ char *p2 = getcwd (NULL, 0);
+ if (p2 == NULL)
+ {
+ puts ("2nd getcwd failed");
+ exit (1);
+ }
+
+ if (strcmp (p, p2) != 0)
+ {
+ printf ("initial cwd mismatch: \"%s\" vs \"%s\"\n", p, p2);
+ exit (1);
+ }
+
+ free (p);
+ free (p2);
+
+ if (chdir ("..") != 0)
+ {
+ puts ("chdir failed");
+ exit (1);
+ }
+
+ p = getcwd (NULL, 0);
+ if (p == NULL)
+ {
+ puts ("getcwd failed");
+ exit (1);
+ }
+
+ return a;
+}
+
+
+int
+do_test (void)
+{
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ p = getcwd (NULL, 0);
+ if (p == NULL)
+ {
+ puts ("getcwd failed");
+ exit (1);
+ }
+
+ int e;
+ BT;
+
+ if (pthread_join (th, NULL) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ char *p2 = getcwd (NULL, 0);
+ if (p2 == NULL)
+ {
+ puts ("2nd getcwd failed");
+ exit (1);
+ }
+
+ if (strcmp (p, p2) != 0)
+ {
+ printf ("cwd after chdir mismatch: \"%s\" vs \"%s\"\n", p, p2);
+ exit (1);
+ }
+
+ free (p);
+ free (p2);
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-basic7.c
@@ -0,0 +1,74 @@
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+
+static void use_stack (size_t needed);
+
+void (*use_stack_ptr) (size_t) = use_stack;
+
+static void
+use_stack (size_t needed)
+{
+ size_t sz = sysconf (_SC_PAGESIZE);
+ char *buf = alloca (sz);
+ memset (buf, '\0', sz);
+
+ if (needed > sz)
+ use_stack_ptr (needed - sz);
+}
+
+static void
+use_up_memory (void)
+{
+ struct rlimit rl;
+ getrlimit (RLIMIT_AS, &rl);
+ rl.rlim_cur = 10 * 1024 * 1024;
+ setrlimit (RLIMIT_AS, &rl);
+
+ char *c;
+ int PAGESIZE = getpagesize ();
+ while (1)
+ {
+ c = mmap (NULL, PAGESIZE, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
+ if (c == MAP_FAILED)
+ break;
+ }
+}
+
+static void *
+child (void *arg)
+{
+ sleep (1);
+ return arg;
+}
+
+static int
+do_test (void)
+{
+ int err;
+ pthread_t tid;
+
+ /* Allocate the memory needed for the stack. */
+ use_stack_ptr (PTHREAD_STACK_MIN);
+
+ use_up_memory ();
+
+ err = pthread_create (&tid, NULL, child, NULL);
+ if (err != 0)
+ {
+ printf ("pthread_create returns %d: %s\n", err,
+ err == EAGAIN ? "OK" : "FAIL");
+ return err != EAGAIN;
+ }
+
+ /* We did not fail to allocate memory despite the preparation. Oh well. */
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel-self-cancelstate.c
@@ -0,0 +1,65 @@
+/* Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "tst-cancel-self-cleanup.c"
+
+
+static int
+do_test (void)
+{
+ int ret = 0;
+ volatile int should_fail = 1;
+
+ pthread_cleanup_push (cleanup, &should_fail);
+
+ if ((ret = pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL)) != 0)
+ {
+ printf ("setcancelstate(disable) failed: %s\n", strerror (ret));
+ exit (1);
+ }
+
+ if ((ret = pthread_cancel (pthread_self ())) != 0)
+ {
+ printf ("cancel failed: %s\n", strerror (ret));
+ exit (1);
+ }
+
+ usleep (100);
+ should_fail = 0;
+
+ if ((ret = pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL)) != 0)
+ {
+ printf ("setcancelstate(enable) failed: %s\n", strerror (ret));
+ exit (1);
+ }
+
+ /* The write syscall within this printf should give us our cancellation
+ point. */
+ printf ("Could not cancel self.\n");
+ pthread_cleanup_pop (0);
+
+ return 1;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel-self-canceltype.c
@@ -0,0 +1,53 @@
+/* Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "tst-cancel-self-cleanup.c"
+
+
+static int
+do_test (void)
+{
+ int ret = 0, should_fail = 0;
+
+ pthread_cleanup_push (cleanup, &should_fail);
+
+ if ((ret = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) != 0)
+ {
+ printf ("setcanceltype failed: %s\n", strerror (ret));
+ exit (1);
+ }
+
+ if ((ret = pthread_cancel (pthread_self ())) != 0)
+ {
+ printf ("cancel failed: %s\n", strerror (ret));
+ exit (1);
+ }
+
+ /* Wait to be canceled. Don't give any cancellation points to play with. */
+ while (1);
+ pthread_cleanup_pop (0);
+
+ return 1;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel-self-cleanup.c
@@ -0,0 +1,23 @@
+/* Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+static void
+cleanup (void *cleanup_should_fail)
+{
+ printf ("Main thread got cancelled and is being cleaned up now\n");
+ exit (*(int *)cleanup_should_fail);
+}
--- /dev/null
+++ b/fbtl/tst-cancel-self-testcancel.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "tst-cancel-self-cleanup.c"
+
+
+static int
+do_test (void)
+{
+ int ret = 0, should_fail = 0;
+
+ pthread_cleanup_push (cleanup, &should_fail);
+ if ((ret = pthread_cancel (pthread_self ())) != 0)
+ {
+ printf ("cancel failed: %s\n", strerror (ret));
+ exit (1);
+ }
+
+ pthread_testcancel ();
+
+ printf ("Could not cancel self.\n");
+ pthread_cleanup_pop (0);
+
+ return 1;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel-self.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "tst-cancel-self-cleanup.c"
+
+
+static int
+do_test (void)
+{
+ int ret = 0, should_fail = 0;
+
+ pthread_cleanup_push (cleanup, &should_fail);
+ if ((ret = pthread_cancel (pthread_self ())) != 0)
+ {
+ printf ("cancel failed: %s\n", strerror (ret));
+ exit (1);
+ }
+
+ /* The write syscall within this printf should give us our cancellation
+ point. */
+ printf ("Could not cancel self.\n");
+ pthread_cleanup_pop (0);
+
+ return 1;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel-wrappers.sh
@@ -0,0 +1,92 @@
+#! /bin/sh
+# Test whether all cancelable functions are cancelable.
+# Copyright (C) 2002-2013 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, see
+# <http://www.gnu.org/licenses/>.
+
+NM="$1"; shift
+while [ $# -gt 0 ]; do
+ ( $NM -P $1; echo 'end[end]:' ) | gawk ' BEGIN {
+C["accept"]=1
+C["close"]=1
+C["connect"]=1
+C["creat"]=1
+C["fcntl"]=1
+C["fdatasync"]=1
+C["fsync"]=1
+C["msgrcv"]=1
+C["msgsnd"]=1
+C["msync"]=1
+C["nanosleep"]=1
+C["open"]=1
+C["open64"]=1
+C["pause"]=1
+C["poll"]=1
+C["pread"]=1
+C["pread64"]=1
+C["pselect"]=1
+C["pwrite"]=1
+C["pwrite64"]=1
+C["read"]=1
+C["readv"]=1
+C["recv"]=1
+C["recvfrom"]=1
+C["recvmsg"]=1
+C["select"]=1
+C["send"]=1
+C["sendmsg"]=1
+C["sendto"]=1
+C["sigpause"]=1
+C["sigsuspend"]=1
+C["sigwait"]=1
+C["sigwaitinfo"]=1
+C["tcdrain"]=1
+C["wait"]=1
+C["waitid"]=1
+C["waitpid"]=1
+C["write"]=1
+C["writev"]=1
+C["__xpg_sigpause"]=1
+}
+/:$/ {
+ if (seen)
+ {
+ if (!seen_enable || !seen_disable)
+ {
+ printf "in '$1'(%s) %s'\''s cancellation missing\n", object, seen
+ ret = 1
+ }
+ }
+ seen=""
+ seen_enable=""
+ seen_disable=""
+ object=gensub(/^.*\[(.*)\]:$/,"\\1","",$0)
+ next
+}
+{
+ if (C[$1] && $2 ~ /^[TW]$/)
+ seen=$1
+ else if ($1 ~ /^([.]|)__(libc|pthread)_enable_asynccancel$/ && $2 == "U")
+ seen_enable=1
+ else if ($1 ~ /^([.]|)__(libc|pthread)_disable_asynccancel$/ && $2 == "U")
+ seen_disable=1
+}
+END {
+ exit ret
+}' || exit
+ shift
+done
--- /dev/null
+++ b/fbtl/tst-cancel1.c
@@ -0,0 +1,162 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+static pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;
+
+static int cntr;
+
+
+static void
+cleanup (void *arg)
+{
+ if (arg != (void *) 42l)
+ cntr = 42;
+ else
+ cntr = 1;
+}
+
+
+static void *
+tf (void *arg)
+{
+ /* Ignore all signals. This must not have any effect on delivering
+ the cancellation signal. */
+ sigset_t ss;
+
+ sigfillset (&ss);
+
+ if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+ {
+ puts ("pthread_sigmask failed");
+ exit (1);
+ }
+
+ pthread_cleanup_push (cleanup, (void *) 42l);
+
+ int err = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+ if (err != 0)
+ {
+ printf ("setcanceltype failed: %s\n", strerror (err));
+ exit (1);
+ }
+ /* The following code is not standard compliant: the mutex functions
+ must not be called with asynchronous cancellation enabled. */
+
+ err = pthread_mutex_unlock (&m2);
+ if (err != 0)
+ {
+ printf ("child: mutex_unlock failed: %s\n", strerror (err));
+ exit (1);
+ }
+
+ err = pthread_mutex_lock (&m1);
+ if (err != 0)
+ {
+ printf ("child: 1st mutex_lock failed: %s\n", strerror (err));
+ exit (1);
+ }
+
+ /* We should never come here. */
+
+ pthread_cleanup_pop (0);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ int err;
+ pthread_t th;
+ int result = 0;
+ void *retval;
+
+ /* Get the mutexes. */
+ err = pthread_mutex_lock (&m1);
+ if (err != 0)
+ {
+ printf ("parent: 1st mutex_lock failed: %s\n", strerror (err));
+ return 1;
+ }
+ err = pthread_mutex_lock (&m2);
+ if (err != 0)
+ {
+ printf ("parent: 2nd mutex_lock failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ err = pthread_create (&th, NULL, tf, NULL);
+ if (err != 0)
+ {
+ printf ("create failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ err = pthread_mutex_lock (&m2);
+ if (err != 0)
+ {
+ printf ("parent: 3rd mutex_lock failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ err = pthread_cancel (th);
+ if (err != 0)
+ {
+ printf ("cancel failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ err = pthread_join (th, &retval);
+ if (err != 0)
+ {
+ printf ("join failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ if (retval != PTHREAD_CANCELED)
+ {
+ printf ("wrong return value: %p\n", retval);
+ result = 1;
+ }
+
+ if (cntr == 42)
+ {
+ puts ("cleanup handler called with wrong argument");
+ result = 1;
+ }
+ else if (cntr != 1)
+ {
+ puts ("cleanup handling not called");
+ result = 1;
+ }
+
+ return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel10.c
@@ -0,0 +1,125 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+static void
+cleanup (void *arg)
+{
+ /* Just for fun. */
+ if (pthread_cancel (pthread_self ()) != 0)
+ {
+ puts ("cleanup: cancel failed");
+ exit (1);
+ }
+
+ printf ("cleanup for %ld\n", (long int) arg);
+}
+
+
+static void *
+tf (void *arg)
+{
+ long int n = (long int) arg;
+
+ pthread_cleanup_push (cleanup, arg);
+
+ if (pthread_setcanceltype ((n & 1) == 0
+ ? PTHREAD_CANCEL_DEFERRED
+ : PTHREAD_CANCEL_ASYNCHRONOUS, NULL) != 0)
+ {
+ puts ("setcanceltype failed");
+ exit (1);
+ }
+
+ if (pthread_cancel (pthread_self ()) != 0)
+ {
+ puts ("cancel failed");
+ exit (1);
+ }
+
+ pthread_testcancel ();
+
+ /* We should never come here. */
+
+ pthread_cleanup_pop (0);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_attr_t at;
+
+ if (pthread_attr_init (&at) != 0)
+ {
+ puts ("attr_init failed");
+ return 1;
+ }
+
+ if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+#define N 20
+ int i;
+ pthread_t th[N];
+
+ for (i = 0; i < N; ++i)
+ if (pthread_create (&th[i], &at, tf, (void *) (long int) i) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ if (pthread_attr_destroy (&at) != 0)
+ {
+ puts ("attr_destroy failed");
+ return 1;
+ }
+
+ for (i = 0; i < N; ++i)
+ {
+ void *r;
+ if (pthread_join (th[i], &r) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("thread not canceled");
+ exit (1);
+ }
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel11.c
@@ -0,0 +1,122 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+static pthread_barrier_t bar;
+static int fd[2];
+
+
+static void
+cleanup (void *arg)
+{
+ static int ncall;
+
+ if (++ncall != 1)
+ {
+ puts ("second call to cleanup");
+ exit (1);
+ }
+
+ printf ("cleanup call #%d\n", ncall);
+}
+
+
+static void *
+tf (void *arg)
+{
+ pthread_cleanup_push (cleanup, NULL);
+
+ int e = pthread_barrier_wait (&bar);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("tf: 1st barrier_wait failed");
+ exit (1);
+ }
+
+ /* This call should block and be cancelable. */
+ char buf[20];
+ read (fd[0], buf, sizeof (buf));
+
+ pthread_cleanup_pop (0);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_barrier_init (&bar, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (pipe (fd) != 0)
+ {
+ puts ("pipe failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&bar);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("1st barrier_wait failed");
+ exit (1);
+ }
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("1st cancel failed");
+ exit (1);
+ }
+
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("thread not canceled");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel12.c
@@ -0,0 +1,126 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+static pthread_barrier_t bar;
+static sem_t sem;
+
+
+static void
+cleanup (void *arg)
+{
+ static int ncall;
+
+ if (++ncall != 1)
+ {
+ puts ("second call to cleanup");
+ exit (1);
+ }
+
+ printf ("cleanup call #%d\n", ncall);
+}
+
+
+static void *
+tf (void *arg)
+{
+ pthread_cleanup_push (cleanup, NULL);
+
+ int e = pthread_barrier_wait (&bar);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("tf: 1st barrier_wait failed");
+ exit (1);
+ }
+
+ /* This call should block and be cancelable. */
+ sem_wait (&sem);
+
+ pthread_cleanup_pop (0);
+
+ puts ("sem_wait returned");
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_barrier_init (&bar, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (sem_init (&sem, 0, 1) != 0)
+ {
+ puts ("sem_init failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ /* Check whether cancellation is honored even before sem_wait does
+ anything. */
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("1st cancel failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&bar);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("1st barrier_wait failed");
+ exit (1);
+ }
+
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("thread not canceled");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel13.c
@@ -0,0 +1,128 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+static pthread_barrier_t bar;
+static sem_t sem;
+
+
+static void
+cleanup (void *arg)
+{
+ static int ncall;
+
+ if (++ncall != 1)
+ {
+ puts ("second call to cleanup");
+ exit (1);
+ }
+
+ printf ("cleanup call #%d\n", ncall);
+}
+
+
+static void *
+tf (void *arg)
+{
+ pthread_cleanup_push (cleanup, NULL);
+
+ int e = pthread_barrier_wait (&bar);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("tf: 1st barrier_wait failed");
+ exit (1);
+ }
+
+ /* This call should block and be cancelable. */
+ sem_wait (&sem);
+
+ pthread_cleanup_pop (0);
+
+ puts ("sem_wait returned");
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_barrier_init (&bar, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (sem_init (&sem, 0, 0) != 0)
+ {
+ puts ("sem_init failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&bar);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("1st barrier_wait failed");
+ exit (1);
+ }
+
+ /* Give the child a chance to go to sleep in sem_wait. */
+ sleep (1);
+
+ /* Check whether cancellation is honored when waiting in sem_wait. */
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("1st cancel failed");
+ exit (1);
+ }
+
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("thread not canceled");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel14.c
@@ -0,0 +1,136 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+
+static pthread_barrier_t bar;
+static sem_t sem;
+
+
+static void
+cleanup (void *arg)
+{
+ static int ncall;
+
+ if (++ncall != 1)
+ {
+ puts ("second call to cleanup");
+ exit (1);
+ }
+
+ printf ("cleanup call #%d\n", ncall);
+}
+
+
+static void *
+tf (void *arg)
+{
+ pthread_cleanup_push (cleanup, NULL);
+
+ int e = pthread_barrier_wait (&bar);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("tf: 1st barrier_wait failed");
+ exit (1);
+ }
+
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+ /* Timeout in 5 seconds. */
+ ts.tv_sec += 5;
+
+ /* This call should block and be cancelable. */
+ sem_timedwait (&sem, &ts);
+
+ pthread_cleanup_pop (0);
+
+ puts ("sem_timedwait returned");
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_barrier_init (&bar, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (sem_init (&sem, 0, 1) != 0)
+ {
+ puts ("sem_init failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ /* Check whether cancellation is honored even before sem_timedwait does
+ anything. */
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("1st cancel failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&bar);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("1st barrier_wait failed");
+ exit (1);
+ }
+
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("thread not canceled");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel15.c
@@ -0,0 +1,141 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+
+static pthread_barrier_t bar;
+static sem_t sem;
+
+
+static void
+cleanup (void *arg)
+{
+ static int ncall;
+
+ if (++ncall != 1)
+ {
+ puts ("second call to cleanup");
+ exit (1);
+ }
+
+ printf ("cleanup call #%d\n", ncall);
+}
+
+
+static void *
+tf (void *arg)
+{
+ int e;
+
+ pthread_cleanup_push (cleanup, NULL);
+
+ e = pthread_barrier_wait (&bar);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("tf: 1st barrier_wait failed");
+ exit (1);
+ }
+
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+ /* Timeout in 5 seconds. */
+ ts.tv_sec += 5;
+
+ /* This call should block and be cancelable. */
+ errno = 0;
+ e = sem_timedwait (&sem, &ts);
+
+ pthread_cleanup_pop (0);
+
+ printf ("sem_timedwait returned, e = %d, errno = %d\n", e, errno);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_barrier_init (&bar, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (sem_init (&sem, 0, 0) != 0)
+ {
+ puts ("sem_init failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&bar);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("1st barrier_wait failed");
+ exit (1);
+ }
+
+ /* Give the child a chance to go to sleep in sem_wait. */
+ sleep (1);
+
+ /* Check whether cancellation is honored when waiting in sem_timedwait. */
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("1st cancel failed");
+ exit (1);
+ }
+
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("thread not canceled");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel16.c
@@ -0,0 +1,230 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+
+static pthread_barrier_t b2;
+static int fd;
+static int called;
+
+
+static void
+cl (void *arg)
+{
+ called = 1;
+}
+
+
+static void *
+tf (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child thread: barrier_wait failed");
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ /* This call should never return. */
+ (void) lockf (fd, F_LOCK, 0);
+
+ pthread_cleanup_pop (0);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ char fname[] = "/tmp/cancel16XXXXXX";
+ fd = mkstemp (fname);
+ if (fd == -1)
+ {
+ puts ("mkstemp failed");
+ return 1;
+ }
+ unlink (fname);
+
+ char mem[sizeof (pthread_barrier_t)];
+ memset (mem, '\0', sizeof (mem));
+ if (TEMP_FAILURE_RETRY (pwrite (fd, mem, sizeof (mem), 0)) != sizeof (mem))
+ {
+ puts ("pwrite failed");
+ return 1;
+ }
+
+ void *p = mmap (NULL, sizeof (mem), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ if (p == MAP_FAILED)
+ {
+ puts ("mmap failed");
+ return 1;
+ }
+ pthread_barrier_t *b = (pthread_barrier_t *) p;
+
+ pthread_barrierattr_t ba;
+ if (pthread_barrierattr_init (&ba) != 0)
+ {
+ puts ("barrierattr_init failed");
+ return 1;
+ }
+ if (pthread_barrierattr_setpshared (&ba, 1) != 0)
+ {
+ puts ("barrierattr_setshared failed");
+ return 1;
+ }
+
+ if (pthread_barrier_init (b, &ba, 2) != 0)
+ {
+ puts ("1st barrier_init failed");
+ return 1;
+ }
+ if (pthread_barrierattr_destroy (&ba) != 0)
+ {
+ puts ("barrier_destroy failed");
+ return 1;
+ }
+
+ pid_t pid = fork ();
+ if (pid == 0)
+ {
+ /* Child. Lock the file and wait. */
+ if (lockf (fd, F_LOCK, 0) != 0)
+ {
+ puts ("child process: lockf failed");
+ _exit (1);
+ }
+
+ int r = pthread_barrier_wait (b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child process: 1st barrier_wait failed");
+ _exit (1);
+ }
+
+ /* Make sure the process dies. */
+ alarm (5);
+
+ r = pthread_barrier_wait (b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child process: 2nd barrier_wait failed");
+ _exit (1);
+ }
+
+ _exit (0);
+ }
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ return 1;
+ }
+
+ int r = pthread_barrier_wait (b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("main: 1st barrier_wait failed");
+ _exit (1);
+ }
+
+ if (pthread_barrier_init (&b2, NULL, 2) != 0)
+ {
+ puts ("2nd barrier_init failed");
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("main: 2nd barrier_wait failed");
+ return 1;
+ }
+
+ /* Delay. */
+ sleep (1);
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cancel failed");
+ return 1;
+ }
+
+ void *result;
+ if (pthread_join (th, &result) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+ if (result != PTHREAD_CANCELED)
+ {
+ puts ("thread not canceled");
+ return 1;
+ }
+ if (called == 0)
+ {
+ puts ("cleanup handler not called");
+ return 1;
+ }
+
+ r = pthread_barrier_wait (b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("main: 3rd barrier_wait failed");
+ return 1;
+ }
+
+ int status;
+ if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+ {
+ puts ("waitpid failed");
+ return 1;
+ }
+ if (WEXITSTATUS (status) != 0)
+ {
+ printf ("child process exits with %d\n", WEXITSTATUS (status));
+ return 1;
+ }
+
+ if (lockf (fd, F_LOCK, 0) != 0)
+ {
+ puts ("main: lockf failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel17.c
@@ -0,0 +1,340 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <aio.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+static pthread_barrier_t b;
+
+
+/* Cleanup handling test. */
+static int cl_called;
+
+static void
+cl (void *arg)
+{
+ ++cl_called;
+}
+
+
+static void *
+tf (void *arg)
+{
+ int r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("tf: barrier_wait failed");
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ const struct aiocb *l[1] = { arg };
+
+ TEMP_FAILURE_RETRY (aio_suspend (l, 1, NULL));
+
+ pthread_cleanup_pop (0);
+
+ puts ("tf: aio_suspend returned");
+
+ exit (1);
+}
+
+
+static void *
+tf2 (void *arg)
+{
+ int r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("tf2: barrier_wait failed");
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ const struct aiocb *l[1] = { arg };
+ struct timespec ts = { .tv_sec = 1000, .tv_nsec = 0 };
+
+ TEMP_FAILURE_RETRY (aio_suspend (l, 1, &ts));
+
+ pthread_cleanup_pop (0);
+
+ puts ("tf2: aio_suspend returned");
+
+ exit (1);
+}
+
+
+static int
+do_test (void)
+{
+ int fds[2];
+ if (pipe (fds) != 0)
+ {
+ puts ("pipe failed");
+ return 1;
+ }
+
+ struct aiocb a, a2, *ap;
+ char mem[1];
+ memset (&a, '\0', sizeof (a));
+ a.aio_fildes = fds[0];
+ a.aio_buf = mem;
+ a.aio_nbytes = sizeof (mem);
+ if (aio_read (&a) != 0)
+ {
+ puts ("aio_read failed");
+ return 1;
+ }
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, &a) != 0)
+ {
+ puts ("1st create failed");
+ return 1;
+ }
+
+ int r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+ while (nanosleep (&ts, &ts) != 0)
+ continue;
+
+ puts ("going to cancel tf in-time");
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("1st cancel failed");
+ return 1;
+ }
+
+ void *status;
+ if (pthread_join (th, &status) != 0)
+ {
+ puts ("1st join failed");
+ return 1;
+ }
+ if (status != PTHREAD_CANCELED)
+ {
+ puts ("1st thread not canceled");
+ return 1;
+ }
+
+ if (cl_called == 0)
+ {
+ puts ("tf cleanup handler not called");
+ return 1;
+ }
+ if (cl_called > 1)
+ {
+ puts ("tf cleanup handler called more than once");
+ return 1;
+ }
+
+ cl_called = 0;
+
+ if (pthread_create (&th, NULL, tf2, &a) != 0)
+ {
+ puts ("2nd create failed");
+ return 1;
+ }
+
+ r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("2nd barrier_wait failed");
+ exit (1);
+ }
+
+ ts.tv_sec = 0;
+ ts.tv_nsec = 100000000;
+ while (nanosleep (&ts, &ts) != 0)
+ continue;
+
+ puts ("going to cancel tf2 in-time");
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("2nd cancel failed");
+ return 1;
+ }
+
+ if (pthread_join (th, &status) != 0)
+ {
+ puts ("2nd join failed");
+ return 1;
+ }
+ if (status != PTHREAD_CANCELED)
+ {
+ puts ("2nd thread not canceled");
+ return 1;
+ }
+
+ if (cl_called == 0)
+ {
+ puts ("tf2 cleanup handler not called");
+ return 1;
+ }
+ if (cl_called > 1)
+ {
+ puts ("tf2 cleanup handler called more than once");
+ return 1;
+ }
+
+ puts ("in-time cancellation succeeded");
+
+ ap = &a;
+ if (aio_cancel (fds[0], &a) != AIO_CANCELED)
+ {
+ puts ("aio_cancel failed");
+ /* If aio_cancel failed, we cannot reuse aiocb a. */
+ ap = &a2;
+ }
+
+
+ cl_called = 0;
+
+ size_t len2 = fpathconf (fds[1], _PC_PIPE_BUF);
+ size_t page_size = sysconf (_SC_PAGESIZE);
+ len2 = 20 * (len2 < page_size ? page_size : len2) + sizeof (mem) + 1;
+ char *mem2 = malloc (len2);
+ if (mem2 == NULL)
+ {
+ puts ("could not allocate memory for pipe write");
+ return 1;
+ }
+
+ memset (ap, '\0', sizeof (*ap));
+ ap->aio_fildes = fds[1];
+ ap->aio_buf = mem2;
+ ap->aio_nbytes = len2;
+ if (aio_write (ap) != 0)
+ {
+ puts ("aio_write failed");
+ return 1;
+ }
+
+ if (pthread_create (&th, NULL, tf, ap) != 0)
+ {
+ puts ("3rd create failed");
+ return 1;
+ }
+
+ puts ("going to cancel tf early");
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("3rd cancel failed");
+ return 1;
+ }
+
+ r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("3rd barrier_wait failed");
+ exit (1);
+ }
+
+ if (pthread_join (th, &status) != 0)
+ {
+ puts ("3rd join failed");
+ return 1;
+ }
+ if (status != PTHREAD_CANCELED)
+ {
+ puts ("3rd thread not canceled");
+ return 1;
+ }
+
+ if (cl_called == 0)
+ {
+ puts ("tf cleanup handler not called");
+ return 1;
+ }
+ if (cl_called > 1)
+ {
+ puts ("tf cleanup handler called more than once");
+ return 1;
+ }
+
+ cl_called = 0;
+
+ if (pthread_create (&th, NULL, tf2, ap) != 0)
+ {
+ puts ("4th create failed");
+ return 1;
+ }
+
+ puts ("going to cancel tf2 early");
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("4th cancel failed");
+ return 1;
+ }
+
+ r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("4th barrier_wait failed");
+ exit (1);
+ }
+
+ if (pthread_join (th, &status) != 0)
+ {
+ puts ("4th join failed");
+ return 1;
+ }
+ if (status != PTHREAD_CANCELED)
+ {
+ puts ("4th thread not canceled");
+ return 1;
+ }
+
+ if (cl_called == 0)
+ {
+ puts ("tf2 cleanup handler not called");
+ return 1;
+ }
+ if (cl_called > 1)
+ {
+ puts ("tf2 cleanup handler called more than once");
+ return 1;
+ }
+
+ puts ("early cancellation succeeded");
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel18.c
@@ -0,0 +1,173 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+
+static pthread_barrier_t b;
+
+
+/* Cleanup handling test. */
+static int cl_called;
+
+static void
+cl (void *arg)
+{
+ ++cl_called;
+}
+
+
+static void *
+tf (void *arg)
+{
+ int r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ struct timespec ts = { .tv_sec = arg == NULL ? 10000000 : 0, .tv_nsec = 0 };
+ TEMP_FAILURE_RETRY (clock_nanosleep (CLOCK_REALTIME, 0, &ts, &ts));
+
+ pthread_cleanup_pop (0);
+
+ puts ("clock_nanosleep returned");
+
+ exit (1);
+}
+
+
+static int
+do_test (void)
+{
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("1st create failed");
+ return 1;
+ }
+
+ int r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+ while (nanosleep (&ts, &ts) != 0)
+ continue;
+
+ puts ("going to cancel in-time");
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("1st cancel failed");
+ return 1;
+ }
+
+ void *status;
+ if (pthread_join (th, &status) != 0)
+ {
+ puts ("1st join failed");
+ return 1;
+ }
+ if (status != PTHREAD_CANCELED)
+ {
+ puts ("1st thread not canceled");
+ return 1;
+ }
+
+ if (cl_called == 0)
+ {
+ puts ("cleanup handler not called");
+ return 1;
+ }
+ if (cl_called > 1)
+ {
+ puts ("cleanup handler called more than once");
+ return 1;
+ }
+
+ puts ("in-time cancellation succeeded");
+
+
+ cl_called = 0;
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("2nd create failed");
+ return 1;
+ }
+
+ puts ("going to cancel early");
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("2nd cancel failed");
+ return 1;
+ }
+
+ r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ if (pthread_join (th, &status) != 0)
+ {
+ puts ("2nd join failed");
+ return 1;
+ }
+ if (status != PTHREAD_CANCELED)
+ {
+ puts ("2nd thread not canceled");
+ return 1;
+ }
+
+ if (cl_called == 0)
+ {
+ printf ("cleanup handler not called\n");
+ return 1;
+ }
+ if (cl_called > 1)
+ {
+ printf ("cleanup handler called more than once\n");
+ return 1;
+ }
+
+ puts ("early cancellation succeeded");
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel19.c
@@ -0,0 +1,286 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <error.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+static void *
+tf (void *arg)
+{
+ return NULL;
+}
+
+static void
+handler (int sig)
+{
+}
+
+static void __attribute__ ((noinline))
+clobber_lots_of_regs (void)
+{
+#define X1(n) long r##n = 10##n; __asm __volatile ("" : "+r" (r##n));
+#define X2(n) X1(n##0) X1(n##1) X1(n##2) X1(n##3) X1(n##4)
+#define X3(n) X2(n##0) X2(n##1) X2(n##2) X2(n##3) X2(n##4)
+ X3(0) X3(1) X3(2) X3(3) X3(4)
+#undef X1
+#define X1(n) __asm __volatile ("" : : "r" (r##n));
+ X3(0) X3(1) X3(2) X3(3) X3(4)
+#undef X1
+#undef X2
+#undef X3
+}
+
+static int
+do_test (void)
+{
+ pthread_t th;
+ int old, rc;
+ int ret = 0;
+ int fd[2];
+
+ rc = pipe (fd);
+ if (rc < 0)
+ error (EXIT_FAILURE, errno, "couldn't create pipe");
+
+ rc = pthread_create (&th, NULL, tf, NULL);
+ if (rc)
+ error (EXIT_FAILURE, rc, "couldn't create thread");
+
+ rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+ if (rc)
+ {
+ error (0, rc, "1st pthread_setcanceltype failed");
+ ret = 1;
+ }
+ if (old != PTHREAD_CANCEL_DEFERRED && old != PTHREAD_CANCEL_ASYNCHRONOUS)
+ {
+ error (0, 0, "1st pthread_setcanceltype returned invalid value %d",
+ old);
+ ret = 1;
+ }
+
+ clobber_lots_of_regs ();
+ close (fd[0]);
+
+ rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
+ if (rc)
+ {
+ error (0, rc, "pthread_setcanceltype after close failed");
+ ret = 1;
+ }
+ if (old != PTHREAD_CANCEL_DEFERRED)
+ {
+ error (0, 0, "pthread_setcanceltype after close returned invalid value %d",
+ old);
+ ret = 1;
+ }
+
+ clobber_lots_of_regs ();
+ close (fd[1]);
+
+ rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+ if (rc)
+ {
+ error (0, rc, "pthread_setcanceltype after 2nd close failed");
+ ret = 1;
+ }
+ if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
+ {
+ error (0, 0, "pthread_setcanceltype after 2nd close returned invalid value %d",
+ old);
+ ret = 1;
+ }
+
+ struct sigaction sa = { .sa_handler = handler, .sa_flags = 0 };
+ sigemptyset (&sa.sa_mask);
+ sigaction (SIGALRM, &sa, NULL);
+
+ struct itimerval it;
+ it.it_value.tv_sec = 1;
+ it.it_value.tv_usec = 0;
+ it.it_interval = it.it_value;
+ setitimer (ITIMER_REAL, &it, NULL);
+
+ clobber_lots_of_regs ();
+ pause ();
+
+ memset (&it, 0, sizeof (it));
+ setitimer (ITIMER_REAL, &it, NULL);
+
+ rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
+ if (rc)
+ {
+ error (0, rc, "pthread_setcanceltype after pause failed");
+ ret = 1;
+ }
+ if (old != PTHREAD_CANCEL_DEFERRED)
+ {
+ error (0, 0, "pthread_setcanceltype after pause returned invalid value %d",
+ old);
+ ret = 1;
+ }
+
+ it.it_value.tv_sec = 1;
+ it.it_value.tv_usec = 0;
+ it.it_interval = it.it_value;
+ setitimer (ITIMER_REAL, &it, NULL);
+
+ clobber_lots_of_regs ();
+ pause ();
+
+ memset (&it, 0, sizeof (it));
+ setitimer (ITIMER_REAL, &it, NULL);
+
+ rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+ if (rc)
+ {
+ error (0, rc, "pthread_setcanceltype after 2nd pause failed");
+ ret = 1;
+ }
+ if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
+ {
+ error (0, 0, "pthread_setcanceltype after 2nd pause returned invalid value %d",
+ old);
+ ret = 1;
+ }
+
+ char fname[] = "/tmp/tst-cancel19-dir-XXXXXX\0foo/bar";
+ char *enddir = strchr (fname, '\0');
+ if (mkdtemp (fname) == NULL)
+ {
+ error (0, errno, "mkdtemp failed");
+ ret = 1;
+ }
+ *enddir = '/';
+
+ clobber_lots_of_regs ();
+ creat (fname, 0400);
+
+ rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
+ if (rc)
+ {
+ error (0, rc, "pthread_setcanceltype after creat failed");
+ ret = 1;
+ }
+ if (old != PTHREAD_CANCEL_DEFERRED)
+ {
+ error (0, 0, "pthread_setcanceltype after creat returned invalid value %d",
+ old);
+ ret = 1;
+ }
+
+ clobber_lots_of_regs ();
+ creat (fname, 0400);
+
+ rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+ if (rc)
+ {
+ error (0, rc, "pthread_setcanceltype after 2nd creat failed");
+ ret = 1;
+ }
+ if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
+ {
+ error (0, 0, "pthread_setcanceltype after 2nd creat returned invalid value %d",
+ old);
+ ret = 1;
+ }
+
+ clobber_lots_of_regs ();
+ open (fname, O_CREAT, 0400);
+
+ rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
+ if (rc)
+ {
+ error (0, rc, "pthread_setcanceltype after open failed");
+ ret = 1;
+ }
+ if (old != PTHREAD_CANCEL_DEFERRED)
+ {
+ error (0, 0, "pthread_setcanceltype after open returned invalid value %d",
+ old);
+ ret = 1;
+ }
+
+ clobber_lots_of_regs ();
+ open (fname, O_CREAT, 0400);
+
+ rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+ if (rc)
+ {
+ error (0, rc, "pthread_setcanceltype after 2nd open failed");
+ ret = 1;
+ }
+ if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
+ {
+ error (0, 0, "pthread_setcanceltype after 2nd open returned invalid value %d",
+ old);
+ ret = 1;
+ }
+
+ *enddir = '\0';
+ rmdir (fname);
+
+ clobber_lots_of_regs ();
+ select (-1, NULL, NULL, NULL, NULL);
+
+ rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
+ if (rc)
+ {
+ error (0, rc, "pthread_setcanceltype after select failed");
+ ret = 1;
+ }
+ if (old != PTHREAD_CANCEL_DEFERRED)
+ {
+ error (0, 0, "pthread_setcanceltype after select returned invalid value %d",
+ old);
+ ret = 1;
+ }
+
+ clobber_lots_of_regs ();
+ select (-1, NULL, NULL, NULL, NULL);
+
+ rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+ if (rc)
+ {
+ error (0, rc, "pthread_setcanceltype after 2nd select failed");
+ ret = 1;
+ }
+ if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
+ {
+ error (0, 0, "pthread_setcanceltype after 2nd select returned invalid value %d",
+ old);
+ ret = 1;
+ }
+
+ pthread_join (th, NULL);
+
+ return ret;
+}
+
+#define TIMEOUT 20
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel2.c
@@ -0,0 +1,95 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+static int fd[2];
+
+
+static void *
+tf (void *arg)
+{
+ /* The buffer size must be larger than the pipe size so that the
+ write blocks. */
+ char buf[100000];
+
+ while (write (fd[1], buf, sizeof (buf)) > 0);
+
+ return (void *) 42l;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+ void *r;
+ struct sigaction sa;
+
+ sa.sa_handler = SIG_IGN;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+
+ if (sigaction (SIGPIPE, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ if (pipe (fd) != 0)
+ {
+ puts ("pipe failed");
+ return 1;
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cancel failed");
+ return 1;
+ }
+
+ /* This will cause the write in the child to return. */
+ close (fd[0]);
+
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ if (r != PTHREAD_CANCELED)
+ {
+ printf ("result is wrong: expected %p, got %p\n", PTHREAD_CANCELED, r);
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel20.c
@@ -0,0 +1,263 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static int fd[4];
+static pthread_barrier_t b;
+volatile int in_sh_body;
+unsigned long cleanups;
+
+static void
+cl (void *arg)
+{
+ cleanups = (cleanups << 4) | (long) arg;
+}
+
+
+static void __attribute__((noinline))
+sh_body (void)
+{
+ char c;
+
+ pthread_cleanup_push (cl, (void *) 1L);
+
+ in_sh_body = 1;
+ if (read (fd[2], &c, 1) == 1)
+ {
+ puts ("read succeeded");
+ exit (1);
+ }
+
+ pthread_cleanup_pop (0);
+}
+
+
+static void
+sh (int sig)
+{
+ pthread_cleanup_push (cl, (void *) 2L);
+ sh_body ();
+ in_sh_body = 0;
+
+ pthread_cleanup_pop (0);
+}
+
+
+static void __attribute__((noinline))
+tf_body (void)
+{
+ char c;
+
+ pthread_cleanup_push (cl, (void *) 3L);
+
+ int r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child thread: barrier_wait failed");
+ exit (1);
+ }
+
+ if (read (fd[0], &c, 1) == 1)
+ {
+ puts ("read succeeded");
+ exit (1);
+ }
+
+ read (fd[0], &c, 1);
+
+ pthread_cleanup_pop (0);
+}
+
+
+static void *
+tf (void *arg)
+{
+ pthread_cleanup_push (cl, (void *) 4L);
+ tf_body ();
+ pthread_cleanup_pop (0);
+ return NULL;
+}
+
+
+static int
+do_one_test (void)
+{
+ in_sh_body = 0;
+ cleanups = 0;
+ if (pipe (fd) != 0 || pipe (fd + 2) != 0)
+ {
+ puts ("pipe failed");
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ int r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("parent thread: barrier_wait failed");
+ return 1;
+ }
+
+ sleep (1);
+
+ r = pthread_kill (th, SIGHUP);
+ if (r)
+ {
+ errno = r;
+ printf ("pthread_kill failed %m\n");
+ return 1;
+ }
+
+ while (in_sh_body == 0)
+ sleep (1);
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cancel failed");
+ return 1;
+ }
+
+ /* This will cause the read in the child to return. */
+ close (fd[0]);
+ close (fd[1]);
+ close (fd[2]);
+ close (fd[3]);
+
+ void *ret;
+ if (pthread_join (th, &ret) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ if (ret != PTHREAD_CANCELED)
+ {
+ puts ("result is wrong");
+ return 1;
+ }
+
+ if (cleanups != 0x1234L)
+ {
+ printf ("called cleanups %lx\n", cleanups);
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static int
+do_test (void)
+{
+ stack_t ss;
+ ss.ss_sp = malloc (2 * SIGSTKSZ);
+ if (ss.ss_sp == NULL)
+ {
+ puts ("failed to allocate alternate stack");
+ return 1;
+ }
+ ss.ss_flags = 0;
+ ss.ss_size = 2 * SIGSTKSZ;
+ if (sigaltstack (&ss, NULL) < 0)
+ {
+ printf ("sigaltstack failed %m\n");
+ return 1;
+ }
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ struct sigaction sa;
+ sa.sa_handler = sh;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+
+ if (sigaction (SIGHUP, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ puts ("sa_flags = 0 test");
+ if (do_one_test ())
+ return 1;
+
+ sa.sa_handler = sh;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = SA_ONSTACK;
+
+ if (sigaction (SIGHUP, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ puts ("sa_flags = SA_ONSTACK test");
+ if (do_one_test ())
+ return 1;
+
+ sa.sa_sigaction = (void (*)(int, siginfo_t *, void *)) sh;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO;
+
+ if (sigaction (SIGHUP, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ puts ("sa_flags = SA_SIGINFO test");
+ if (do_one_test ())
+ return 1;
+
+ sa.sa_sigaction = (void (*)(int, siginfo_t *, void *)) sh;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
+
+ if (sigaction (SIGHUP, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ puts ("sa_flags = SA_SIGINFO|SA_ONSTACK test");
+ if (do_one_test ())
+ return 1;
+
+ return 0;
+}
+
+#define TIMEOUT 40
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel21-static.c
@@ -0,0 +1 @@
+#include "tst-cancel21.c"
--- /dev/null
+++ b/fbtl/tst-cancel21.c
@@ -0,0 +1,293 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+
+static int fd[4];
+static pthread_barrier_t b;
+volatile int in_sh_body;
+unsigned long cleanups;
+
+static void
+cl (void *arg)
+{
+ cleanups = (cleanups << 4) | (long) arg;
+}
+
+
+static void __attribute__((noinline))
+sh_body (void)
+{
+ char c;
+
+ pthread_cleanup_push (cl, (void *) 1L);
+
+ in_sh_body = 1;
+ if (read (fd[2], &c, 1) == 1)
+ {
+ puts ("read succeeded");
+ exit (1);
+ }
+
+ pthread_cleanup_pop (0);
+}
+
+
+static void
+sh (int sig)
+{
+ pthread_cleanup_push (cl, (void *) 2L);
+ sh_body ();
+ in_sh_body = 0;
+
+ pthread_cleanup_pop (0);
+}
+
+
+static void __attribute__((noinline))
+tf_body (void)
+{
+ char c;
+
+ pthread_cleanup_push (cl, (void *) 3L);
+
+ int r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child thread: barrier_wait failed");
+ exit (1);
+ }
+
+ if (read (fd[0], &c, 1) == 1)
+ {
+ puts ("read succeeded");
+ exit (1);
+ }
+
+ read (fd[0], &c, 1);
+
+ pthread_cleanup_pop (0);
+}
+
+
+static void *
+tf (void *arg)
+{
+ pthread_t th = (pthread_t) arg;
+
+ int r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("parent thread: barrier_wait failed");
+ exit (1);
+ }
+
+ sleep (1);
+
+ r = pthread_kill (th, SIGHUP);
+ if (r)
+ {
+ errno = r;
+ printf ("pthread_kill failed %m\n");
+ exit (1);
+ }
+
+ while (in_sh_body == 0)
+ sleep (1);
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cancel failed");
+ exit (1);
+ }
+
+ /* This will cause the read in the initial thread to return. */
+ close (fd[0]);
+ close (fd[1]);
+ close (fd[2]);
+ close (fd[3]);
+
+ void *ret;
+ if (pthread_join (th, &ret) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ if (ret != PTHREAD_CANCELED)
+ {
+ puts ("result is wrong");
+ exit (1);
+ }
+
+ if (cleanups != 0x1234L)
+ {
+ printf ("called cleanups %lx\n", cleanups);
+ exit (1);
+ }
+
+ if (pthread_barrier_destroy (&b))
+ {
+ puts ("barrier destroy failed");
+ exit (1);
+ }
+
+ exit (0);
+}
+
+
+static int
+do_one_test (void)
+{
+ in_sh_body = 0;
+
+ pid_t pid = fork ();
+
+ if (pid == -1)
+ {
+ printf ("fork failed: %m\n");
+ return 1;
+ }
+
+ if (pid)
+ {
+ int status;
+ if (waitpid (pid, &status, 0) < 0)
+ {
+ printf ("waitpid failed %m\n");
+ return 1;
+ }
+
+ return !WIFEXITED (status) || WEXITSTATUS (status);
+ }
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ cleanups = 0;
+ if (pipe (fd) != 0 || pipe (fd + 2) != 0)
+ {
+ puts ("pipe failed");
+ exit (1);
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, (void *) 4L);
+ tf_body ();
+ pthread_cleanup_pop (0);
+ exit (1);
+}
+
+
+static int
+do_test (void)
+{
+ stack_t ss;
+ ss.ss_sp = malloc (2 * SIGSTKSZ);
+ if (ss.ss_sp == NULL)
+ {
+ puts ("failed to allocate alternate stack");
+ return 1;
+ }
+ ss.ss_flags = 0;
+ ss.ss_size = 2 * SIGSTKSZ;
+ if (sigaltstack (&ss, NULL) < 0)
+ {
+ printf ("sigaltstack failed %m\n");
+ return 1;
+ }
+
+ struct sigaction sa;
+ sa.sa_handler = sh;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+
+ if (sigaction (SIGHUP, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ puts ("sa_flags = 0 test");
+ if (do_one_test ())
+ return 1;
+
+ sa.sa_handler = sh;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = SA_ONSTACK;
+
+ if (sigaction (SIGHUP, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ puts ("sa_flags = SA_ONSTACK test");
+ if (do_one_test ())
+ return 1;
+
+ sa.sa_sigaction = (void (*)(int, siginfo_t *, void *)) sh;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO;
+
+ if (sigaction (SIGHUP, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ puts ("sa_flags = SA_SIGINFO test");
+ if (do_one_test ())
+ return 1;
+
+ sa.sa_sigaction = (void (*)(int, siginfo_t *, void *)) sh;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
+
+ if (sigaction (SIGHUP, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ puts ("sa_flags = SA_SIGINFO|SA_ONSTACK test");
+ if (do_one_test ())
+ return 1;
+
+ return 0;
+}
+
+#define TIMEOUT 40
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel22.c
@@ -0,0 +1,120 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+pthread_barrier_t b;
+int seen;
+
+static void *
+tf (void *arg)
+{
+ int old;
+ int r = pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &old);
+ if (r != 0)
+ {
+ puts ("setcancelstate failed");
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ for (int i = 0; i < 10; ++i)
+ {
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+ TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
+ }
+
+ seen = 1;
+ pthread_setcancelstate (old, NULL);
+
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+ TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
+
+ exit (1);
+}
+
+
+static int
+do_test (void)
+{
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier init failed");
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("thread creation failed");
+ return 1;
+ }
+
+ int r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ return 1;
+ }
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cancel failed");
+ return 1;
+ }
+
+ void *status;
+ if (pthread_join (th, &status) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+ if (status != PTHREAD_CANCELED)
+ {
+ puts ("thread not canceled");
+ return 1;
+ }
+
+ if (pthread_barrier_destroy (&b) != 0)
+ {
+ puts ("barrier_destroy failed");
+ return 1;
+ }
+
+ if (seen != 1)
+ {
+ puts ("thread cancelled when PTHREAD_CANCEL_DISABLED");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TIMEOUT 5
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel23.c
@@ -0,0 +1 @@
+#include "tst-cancel22.c"
--- /dev/null
+++ b/fbtl/tst-cancel24-static.cc
@@ -0,0 +1 @@
+#include "tst-cancel24.cc"
--- /dev/null
+++ b/fbtl/tst-cancel24.cc
@@ -0,0 +1,113 @@
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+static volatile bool destr_called;
+static volatile bool except_caught;
+
+static pthread_barrier_t b;
+
+
+struct monitor
+{
+ // gcc is broken and would generate a warning without this dummy
+ // constructor.
+ monitor () { }
+ ~monitor() { destr_called = true; }
+};
+
+
+static void *
+tf (void *arg)
+{
+ sem_t *s = static_cast<sem_t *> (arg);
+
+ try
+ {
+ monitor m;
+
+ pthread_barrier_wait (&b);
+
+ while (1)
+ sem_wait (s);
+ }
+ catch (...)
+ {
+ except_caught = true;
+ throw;
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test ()
+{
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ sem_t s;
+ if (sem_init (&s, 0, 0) != 0)
+ {
+ puts ("sem_init failed");
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, &s) != 0)
+ {
+ puts ("pthread_create failed");
+ return 1;
+ }
+
+ pthread_barrier_wait (&b);
+
+ /* There is unfortunately no better method to try to assure the
+ child thread reached the sem_wait call and is actually waiting
+ than to sleep here. */
+ sleep (1);
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cancel failed");
+ return 1;
+ }
+
+ void *res;
+ if (pthread_join (th, &res) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ if (res != PTHREAD_CANCELED)
+ {
+ puts ("thread was not canceled");
+ return 1;
+ }
+
+ if (! except_caught)
+ {
+ puts ("exception not caught");
+ return 1;
+ }
+
+ if (! destr_called)
+ {
+ puts ("destructor not called");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 3
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel25.c
@@ -0,0 +1,171 @@
+#include <pthreadP.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_barrier_t b;
+static pthread_t th2;
+
+
+static void *
+tf2 (void *arg)
+{
+ sigset_t mask;
+ if (pthread_sigmask (SIG_SETMASK, NULL, &mask) != 0)
+ {
+ puts ("pthread_sigmask failed");
+ exit (1);
+ }
+ if (sigismember (&mask, SIGCANCEL))
+ {
+ puts ("SIGCANCEL blocked in new thread");
+ exit (1);
+ }
+
+ /* Sync with the main thread so that we do not test anything else. */
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ while (1)
+ {
+ /* Just a cancelable call. */
+ struct timespec ts = { 10000, 0 };
+ nanosleep (&ts, 0);
+ }
+
+ return NULL;
+}
+
+
+static void
+unwhand (void *arg)
+{
+ if (pthread_create (&th2, NULL, tf2, NULL) != 0)
+ {
+ puts ("unwhand: create failed");
+ exit (1);
+ }
+}
+
+
+static void *
+tf (void *arg)
+{
+ pthread_cleanup_push (unwhand, NULL);
+
+ /* Sync with the main thread so that we do not test anything else. */
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ while (1)
+ {
+ /* Just a cancelable call. */
+ struct timespec ts = { 10000, 0 };
+ nanosleep (&ts, 0);
+ }
+
+ pthread_cleanup_pop (0);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ pthread_t th1;
+ if (pthread_create (&th1, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ return 1;
+ }
+
+ /* Make sure tf1 enters nanosleep. */
+ struct timespec ts = { 0, 500000000 };
+ while (nanosleep (&ts, &ts) != 0)
+ ;
+
+ if (pthread_cancel (th1) != 0)
+ {
+ puts ("1st cancel failed");
+ return 1;
+ }
+
+ void *res;
+ if (pthread_join (th1, &res) != 0)
+ {
+ puts ("1st join failed");
+ return 1;
+ }
+ if (res != PTHREAD_CANCELED)
+ {
+ puts ("1st thread not canceled");
+ return 1;
+ }
+
+ e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ return 1;
+ }
+
+ /* Make sure tf2 enters nanosleep. */
+ ts.tv_sec = 0;
+ ts.tv_nsec = 500000000;
+ while (nanosleep (&ts, &ts) != 0)
+ ;
+
+ puts ("calling pthread_cancel the second time");
+ if (pthread_cancel (th2) != 0)
+ {
+ puts ("2nd cancel failed");
+ return 1;
+ }
+
+ puts ("calling pthread_join the second time");
+ if (pthread_join (th2, &res) != 0)
+ {
+ puts ("2nd join failed");
+ return 1;
+ }
+ if (res != PTHREAD_CANCELED)
+ {
+ puts ("2nd thread not canceled");
+ return 1;
+ }
+
+ if (pthread_barrier_destroy (&b) != 0)
+ {
+ puts ("barrier_destroy failed");
+ return 0;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 4
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel3.c
@@ -0,0 +1,97 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+static int fd[2];
+
+
+static void *
+tf (void *arg)
+{
+ char buf[100];
+
+ if (read (fd[0], buf, sizeof (buf)) == sizeof (buf))
+ {
+ puts ("read succeeded");
+ return (void *) 1l;
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+ void *r;
+ struct sigaction sa;
+
+ sa.sa_handler = SIG_IGN;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+
+ if (sigaction (SIGPIPE, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ if (pipe (fd) != 0)
+ {
+ puts ("pipe failed");
+ return 1;
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cancel failed");
+ return 1;
+ }
+
+ /* This will cause the read in the child to return. */
+ close (fd[0]);
+
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("result is wrong");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel4.c
@@ -0,0 +1,2375 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* NOTE: this tests functionality beyond POSIX. POSIX does not allow
+ exit to be called more than once. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pthread.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/msg.h>
+#include <sys/poll.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+
+#include "pthreadP.h"
+
+
+/* Since STREAMS are not supported in the standard Linux kernel and
+ there we don't advertise STREAMS as supported is no need to test
+ the STREAMS related functions. This affects
+ getmsg() getpmsg() putmsg()
+ putpmsg()
+
+ lockf() and fcntl() are tested in tst-cancel16.
+
+ pthread_join() is tested in tst-join5.
+
+ pthread_testcancel()'s only purpose is to allow cancellation. This
+ is tested in several places.
+
+ sem_wait() and sem_timedwait() are checked in tst-cancel1[2345] tests.
+
+ mq_send(), mq_timedsend(), mq_receive() and mq_timedreceive() are checked
+ in tst-mqueue8{,x} tests.
+
+ aio_suspend() is tested in tst-cancel17.
+
+ clock_nanosleep() is tested in tst-cancel18.
+*/
+
+/* Pipe descriptors. */
+static int fds[2];
+
+/* Temporary file descriptor, to be closed after each round. */
+static int tempfd = -1;
+static int tempfd2 = -1;
+/* Name of temporary file to be removed after each round. */
+static char *tempfname;
+/* Temporary message queue. */
+static int tempmsg = -1;
+
+/* Often used barrier for two threads. */
+static pthread_barrier_t b2;
+
+
+#ifndef IPC_ADDVAL
+# define IPC_ADDVAL 0
+#endif
+
+#define WRITE_BUFFER_SIZE 4096
+
+/* Cleanup handling test. */
+static int cl_called;
+
+static void
+cl (void *arg)
+{
+ ++cl_called;
+}
+
+
+
+static void *
+tf_read (void *arg)
+{
+ int fd;
+ int r;
+
+ if (arg == NULL)
+ fd = fds[0];
+ else
+ {
+ char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+ tempfd = fd = mkstemp (fname);
+ if (fd == -1)
+ printf ("%s: mkstemp failed\n", __FUNCTION__);
+ unlink (fname);
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ ssize_t s;
+ pthread_cleanup_push (cl, NULL);
+
+ char buf[100];
+ s = read (fd, buf, sizeof (buf));
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: read returns with %zd\n", __FUNCTION__, s);
+
+ exit (1);
+}
+
+
+static void *
+tf_readv (void *arg)
+{
+ int fd;
+ int r;
+
+ if (arg == NULL)
+ fd = fds[0];
+ else
+ {
+ char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+ tempfd = fd = mkstemp (fname);
+ if (fd == -1)
+ printf ("%s: mkstemp failed\n", __FUNCTION__);
+ unlink (fname);
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ ssize_t s;
+ pthread_cleanup_push (cl, NULL);
+
+ char buf[100];
+ struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } };
+ s = readv (fd, iov, 1);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: readv returns with %zd\n", __FUNCTION__, s);
+
+ exit (1);
+}
+
+
+static void *
+tf_write (void *arg)
+{
+ int fd;
+ int r;
+
+ if (arg == NULL)
+ fd = fds[1];
+ else
+ {
+ char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+ tempfd = fd = mkstemp (fname);
+ if (fd == -1)
+ printf ("%s: mkstemp failed\n", __FUNCTION__);
+ unlink (fname);
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ ssize_t s;
+ pthread_cleanup_push (cl, NULL);
+
+ char buf[WRITE_BUFFER_SIZE];
+ memset (buf, '\0', sizeof (buf));
+ s = write (fd, buf, sizeof (buf));
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: write returns with %zd\n", __FUNCTION__, s);
+
+ exit (1);
+}
+
+
+static void *
+tf_writev (void *arg)
+{
+ int fd;
+ int r;
+
+ if (arg == NULL)
+ fd = fds[1];
+ else
+ {
+ char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+ tempfd = fd = mkstemp (fname);
+ if (fd == -1)
+ printf ("%s: mkstemp failed\n", __FUNCTION__);
+ unlink (fname);
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ ssize_t s;
+ pthread_cleanup_push (cl, NULL);
+
+ char buf[WRITE_BUFFER_SIZE];
+ memset (buf, '\0', sizeof (buf));
+ struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } };
+ s = writev (fd, iov, 1);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: writev returns with %zd\n", __FUNCTION__, s);
+
+ exit (1);
+}
+
+
+static void *
+tf_sleep (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ sleep (arg == NULL ? 1000000 : 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: sleep returns\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_usleep (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ usleep (arg == NULL ? (useconds_t) ULONG_MAX : 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: usleep returns\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_nanosleep (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ struct timespec ts = { .tv_sec = arg == NULL ? 10000000 : 0, .tv_nsec = 0 };
+ TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: nanosleep returns\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_select (void *arg)
+{
+ int fd;
+ int r;
+
+ if (arg == NULL)
+ fd = fds[0];
+ else
+ {
+ char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+ tempfd = fd = mkstemp (fname);
+ if (fd == -1)
+ printf ("%s: mkstemp failed\n", __FUNCTION__);
+ unlink (fname);
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ fd_set rfs;
+ FD_ZERO (&rfs);
+ FD_SET (fd, &rfs);
+
+ int s;
+ pthread_cleanup_push (cl, NULL);
+
+ s = select (fd + 1, &rfs, NULL, NULL, NULL);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: select returns with %d (%s)\n", __FUNCTION__, s,
+ strerror (errno));
+
+ exit (1);
+}
+
+
+static void *
+tf_pselect (void *arg)
+{
+ int fd;
+ int r;
+
+ if (arg == NULL)
+ fd = fds[0];
+ else
+ {
+ char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+ tempfd = fd = mkstemp (fname);
+ if (fd == -1)
+ printf ("%s: mkstemp failed\n", __FUNCTION__);
+ unlink (fname);
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ fd_set rfs;
+ FD_ZERO (&rfs);
+ FD_SET (fd, &rfs);
+
+ int s;
+ pthread_cleanup_push (cl, NULL);
+
+ s = pselect (fd + 1, &rfs, NULL, NULL, NULL, NULL);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: pselect returns with %d (%s)\n", __FUNCTION__, s,
+ strerror (errno));
+
+ exit (1);
+}
+
+
+static void *
+tf_poll (void *arg)
+{
+ int fd;
+ int r;
+
+ if (arg == NULL)
+ fd = fds[0];
+ else
+ {
+ char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+ tempfd = fd = mkstemp (fname);
+ if (fd == -1)
+ printf ("%s: mkstemp failed\n", __FUNCTION__);
+ unlink (fname);
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ struct pollfd rfs[1] = { [0] = { .fd = fd, .events = POLLIN } };
+
+ int s;
+ pthread_cleanup_push (cl, NULL);
+
+ s = poll (rfs, 1, -1);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: poll returns with %d (%s)\n", __FUNCTION__, s,
+ strerror (errno));
+
+ exit (1);
+}
+
+
+static void *
+tf_ppoll (void *arg)
+{
+ int fd;
+ int r;
+
+ if (arg == NULL)
+ fd = fds[0];
+ else
+ {
+ char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+ tempfd = fd = mkstemp (fname);
+ if (fd == -1)
+ printf ("%s: mkstemp failed\n", __FUNCTION__);
+ unlink (fname);
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ struct pollfd rfs[1] = { [0] = { .fd = fd, .events = POLLIN } };
+
+ int s;
+ pthread_cleanup_push (cl, NULL);
+
+ s = ppoll (rfs, 1, NULL, NULL);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: ppoll returns with %d (%s)\n", __FUNCTION__, s,
+ strerror (errno));
+
+ exit (1);
+}
+
+
+static void *
+tf_wait (void *arg)
+{
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+
+ if (pid == 0)
+ {
+ /* Make the program disappear after a while. */
+ if (arg == NULL)
+ sleep (10);
+ exit (0);
+ }
+
+ int r;
+ if (arg != NULL)
+ {
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+ while (nanosleep (&ts, &ts) != 0)
+ continue;
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int s;
+ pthread_cleanup_push (cl, NULL);
+
+ s = wait (NULL);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: wait returns with %d (%s)\n", __FUNCTION__, s,
+ strerror (errno));
+
+ exit (1);
+}
+
+
+static void *
+tf_waitpid (void *arg)
+{
+
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+
+ if (pid == 0)
+ {
+ /* Make the program disappear after a while. */
+ if (arg == NULL)
+ sleep (10);
+ exit (0);
+ }
+
+ int r;
+ if (arg != NULL)
+ {
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+ while (nanosleep (&ts, &ts) != 0)
+ continue;
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int s;
+ pthread_cleanup_push (cl, NULL);
+
+ s = waitpid (-1, NULL, 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: waitpid returns with %d (%s)\n", __FUNCTION__, s,
+ strerror (errno));
+
+ exit (1);
+}
+
+
+static void *
+tf_waitid (void *arg)
+{
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+
+ if (pid == 0)
+ {
+ /* Make the program disappear after a while. */
+ if (arg == NULL)
+ sleep (10);
+ exit (0);
+ }
+
+ int r;
+ if (arg != NULL)
+ {
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+ while (nanosleep (&ts, &ts) != 0)
+ continue;
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int s;
+ pthread_cleanup_push (cl, NULL);
+
+#ifndef WEXITED
+# define WEXITED 0
+#endif
+ siginfo_t si;
+ s = waitid (P_PID, pid, &si, WEXITED);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: waitid returns with %d (%s)\n", __FUNCTION__, s,
+ strerror (errno));
+
+ exit (1);
+}
+
+
+static void *
+tf_sigpause (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ /* Just for fun block the cancellation signal. We need to use
+ __xpg_sigpause since otherwise we will get the BSD version. */
+ __xpg_sigpause (SIGCANCEL);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: sigpause returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_sigsuspend (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ /* Just for fun block all signals. */
+ sigset_t mask;
+ sigfillset (&mask);
+ sigsuspend (&mask);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: sigsuspend returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_sigwait (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ /* Block SIGUSR1. */
+ sigset_t mask;
+ sigemptyset (&mask);
+ sigaddset (&mask, SIGUSR1);
+ if (pthread_sigmask (SIG_BLOCK, &mask, NULL) != 0)
+ {
+ printf ("%s: pthread_sigmask failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int sig;
+ pthread_cleanup_push (cl, NULL);
+
+ /* Wait for SIGUSR1. */
+ sigwait (&mask, &sig);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: sigwait returned with signal %d\n", __FUNCTION__, sig);
+
+ exit (1);
+}
+
+
+static void *
+tf_sigwaitinfo (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ /* Block SIGUSR1. */
+ sigset_t mask;
+ sigemptyset (&mask);
+ sigaddset (&mask, SIGUSR1);
+ if (pthread_sigmask (SIG_BLOCK, &mask, NULL) != 0)
+ {
+ printf ("%s: pthread_sigmask failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ siginfo_t info;
+ pthread_cleanup_push (cl, NULL);
+
+ /* Wait for SIGUSR1. */
+ sigwaitinfo (&mask, &info);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: sigwaitinfo returned with signal %d\n", __FUNCTION__,
+ info.si_signo);
+
+ exit (1);
+}
+
+
+static void *
+tf_sigtimedwait (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ /* Block SIGUSR1. */
+ sigset_t mask;
+ sigemptyset (&mask);
+ sigaddset (&mask, SIGUSR1);
+ if (pthread_sigmask (SIG_BLOCK, &mask, NULL) != 0)
+ {
+ printf ("%s: pthread_sigmask failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ /* Wait for SIGUSR1. */
+ siginfo_t info;
+ struct timespec ts = { .tv_sec = 60, .tv_nsec = 0 };
+ pthread_cleanup_push (cl, NULL);
+
+ sigtimedwait (&mask, &info, &ts);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: sigtimedwait returned with signal %d\n", __FUNCTION__,
+ info.si_signo);
+
+ exit (1);
+}
+
+
+static void *
+tf_pause (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ pause ();
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: pause returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_accept (void *arg)
+{
+ struct sockaddr_un sun;
+ /* To test a non-blocking accept call we make the call file by using
+ a datagrame socket. */
+ int pf = arg == NULL ? SOCK_STREAM : SOCK_DGRAM;
+
+ tempfd = socket (AF_UNIX, pf, 0);
+ if (tempfd == -1)
+ {
+ printf ("%s: socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int tries = 0;
+ do
+ {
+ if (++tries > 10)
+ {
+ printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+ }
+
+ strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-1-XXXXXX");
+ if (mktemp (sun.sun_path) == NULL)
+ {
+ printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+ exit (1);
+ }
+
+ sun.sun_family = AF_UNIX;
+ }
+ while (bind (tempfd, (struct sockaddr *) &sun,
+ offsetof (struct sockaddr_un, sun_path)
+ + strlen (sun.sun_path) + 1) != 0);
+
+ unlink (sun.sun_path);
+
+ listen (tempfd, 5);
+
+ socklen_t len = sizeof (sun);
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ accept (tempfd, (struct sockaddr *) &sun, &len);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: accept returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_send (void *arg)
+{
+ struct sockaddr_un sun;
+
+ tempfd = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (tempfd == -1)
+ {
+ printf ("%s: first socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int tries = 0;
+ do
+ {
+ if (++tries > 10)
+ {
+ printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+ }
+
+ strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-2-XXXXXX");
+ if (mktemp (sun.sun_path) == NULL)
+ {
+ printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+ exit (1);
+ }
+
+ sun.sun_family = AF_UNIX;
+ }
+ while (bind (tempfd, (struct sockaddr *) &sun,
+ offsetof (struct sockaddr_un, sun_path)
+ + strlen (sun.sun_path) + 1) != 0);
+
+ listen (tempfd, 5);
+
+ tempfd2 = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (tempfd2 == -1)
+ {
+ printf ("%s: second socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (connect (tempfd2, (struct sockaddr *) &sun, sizeof (sun)) != 0)
+ {
+ printf ("%s: connect failed\n", __FUNCTION__);
+ exit(1);
+ }
+
+ unlink (sun.sun_path);
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ /* Very large block, so that the send call blocks. */
+ char mem[700000];
+
+ send (tempfd2, mem, arg == NULL ? sizeof (mem) : 1, 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: send returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_recv (void *arg)
+{
+ struct sockaddr_un sun;
+
+ tempfd = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (tempfd == -1)
+ {
+ printf ("%s: first socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int tries = 0;
+ do
+ {
+ if (++tries > 10)
+ {
+ printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+ }
+
+ strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-3-XXXXXX");
+ if (mktemp (sun.sun_path) == NULL)
+ {
+ printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+ exit (1);
+ }
+
+ sun.sun_family = AF_UNIX;
+ }
+ while (bind (tempfd, (struct sockaddr *) &sun,
+ offsetof (struct sockaddr_un, sun_path)
+ + strlen (sun.sun_path) + 1) != 0);
+
+ listen (tempfd, 5);
+
+ tempfd2 = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (tempfd2 == -1)
+ {
+ printf ("%s: second socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (connect (tempfd2, (struct sockaddr *) &sun, sizeof (sun)) != 0)
+ {
+ printf ("%s: connect failed\n", __FUNCTION__);
+ exit(1);
+ }
+
+ unlink (sun.sun_path);
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ char mem[70];
+
+ recv (tempfd2, mem, arg == NULL ? sizeof (mem) : 0, 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: recv returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_recvfrom (void *arg)
+{
+ struct sockaddr_un sun;
+
+ tempfd = socket (AF_UNIX, SOCK_DGRAM, 0);
+ if (tempfd == -1)
+ {
+ printf ("%s: first socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int tries = 0;
+ do
+ {
+ if (++tries > 10)
+ {
+ printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+ }
+
+ strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-4-XXXXXX");
+ if (mktemp (sun.sun_path) == NULL)
+ {
+ printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+ exit (1);
+ }
+
+ sun.sun_family = AF_UNIX;
+ }
+ while (bind (tempfd, (struct sockaddr *) &sun,
+ offsetof (struct sockaddr_un, sun_path)
+ + strlen (sun.sun_path) + 1) != 0);
+
+ tempfname = strdup (sun.sun_path);
+
+ tempfd2 = socket (AF_UNIX, SOCK_DGRAM, 0);
+ if (tempfd2 == -1)
+ {
+ printf ("%s: second socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ char mem[70];
+ socklen_t len = sizeof (sun);
+
+ recvfrom (tempfd2, mem, arg == NULL ? sizeof (mem) : 0, 0,
+ (struct sockaddr *) &sun, &len);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: recvfrom returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_recvmsg (void *arg)
+{
+ struct sockaddr_un sun;
+
+ tempfd = socket (AF_UNIX, SOCK_DGRAM, 0);
+ if (tempfd == -1)
+ {
+ printf ("%s: first socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int tries = 0;
+ do
+ {
+ if (++tries > 10)
+ {
+ printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+ }
+
+ strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-5-XXXXXX");
+ if (mktemp (sun.sun_path) == NULL)
+ {
+ printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+ exit (1);
+ }
+
+ sun.sun_family = AF_UNIX;
+ }
+ while (bind (tempfd, (struct sockaddr *) &sun,
+ offsetof (struct sockaddr_un, sun_path)
+ + strlen (sun.sun_path) + 1) != 0);
+
+ tempfname = strdup (sun.sun_path);
+
+ tempfd2 = socket (AF_UNIX, SOCK_DGRAM, 0);
+ if (tempfd2 == -1)
+ {
+ printf ("%s: second socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ char mem[70];
+ struct iovec iov[1];
+ iov[0].iov_base = mem;
+ iov[0].iov_len = arg == NULL ? sizeof (mem) : 0;
+
+ struct msghdr m;
+ m.msg_name = &sun;
+ m.msg_namelen = sizeof (sun);
+ m.msg_iov = iov;
+ m.msg_iovlen = 1;
+ m.msg_control = NULL;
+ m.msg_controllen = 0;
+
+ recvmsg (tempfd2, &m, 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: recvmsg returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_open (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which open()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ open ("Makefile", O_RDONLY);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: open returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_close (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which close()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ char fname[] = "/tmp/tst-cancel-fd-XXXXXX";
+ tempfd = mkstemp (fname);
+ if (tempfd == -1)
+ {
+ printf ("%s: mkstemp failed\n", __FUNCTION__);
+ exit (1);
+ }
+ unlink (fname);
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ close (tempfd);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: close returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_pread (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which pread()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ tempfd = open ("Makefile", O_RDONLY);
+ if (tempfd == -1)
+ {
+ printf ("%s: cannot open Makefile\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ char mem[10];
+ pread (tempfd, mem, sizeof (mem), 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: pread returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_pwrite (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which pwrite()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+ tempfd = mkstemp (fname);
+ if (tempfd == -1)
+ {
+ printf ("%s: mkstemp failed\n", __FUNCTION__);
+ exit (1);
+ }
+ unlink (fname);
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ char mem[10];
+ pwrite (tempfd, mem, sizeof (mem), 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: pwrite returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_fsync (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which fsync()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ tempfd = open ("Makefile", O_RDONLY);
+ if (tempfd == -1)
+ {
+ printf ("%s: cannot open Makefile\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ fsync (tempfd);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: fsync returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_fdatasync (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which fdatasync()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ tempfd = open ("Makefile", O_RDONLY);
+ if (tempfd == -1)
+ {
+ printf ("%s: cannot open Makefile\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ fdatasync (tempfd);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: fdatasync returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_msync (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which msync()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ tempfd = open ("Makefile", O_RDONLY);
+ if (tempfd == -1)
+ {
+ printf ("%s: cannot open Makefile\n", __FUNCTION__);
+ exit (1);
+ }
+ void *p = mmap (NULL, 10, PROT_READ, MAP_SHARED, tempfd, 0);
+ if (p == MAP_FAILED)
+ {
+ printf ("%s: mmap failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ msync (p, 10, 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: msync returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_sendto (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which sendto()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ struct sockaddr_un sun;
+
+ tempfd = socket (AF_UNIX, SOCK_DGRAM, 0);
+ if (tempfd == -1)
+ {
+ printf ("%s: first socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int tries = 0;
+ do
+ {
+ if (++tries > 10)
+ {
+ printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+ }
+
+ strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-6-XXXXXX");
+ if (mktemp (sun.sun_path) == NULL)
+ {
+ printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+ exit (1);
+ }
+
+ sun.sun_family = AF_UNIX;
+ }
+ while (bind (tempfd, (struct sockaddr *) &sun,
+ offsetof (struct sockaddr_un, sun_path)
+ + strlen (sun.sun_path) + 1) != 0);
+ tempfname = strdup (sun.sun_path);
+
+ tempfd2 = socket (AF_UNIX, SOCK_DGRAM, 0);
+ if (tempfd2 == -1)
+ {
+ printf ("%s: second socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ char mem[1];
+
+ sendto (tempfd2, mem, arg == NULL ? sizeof (mem) : 1, 0,
+ (struct sockaddr *) &sun,
+ offsetof (struct sockaddr_un, sun_path) + strlen (sun.sun_path) + 1);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: sendto returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_sendmsg (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which sendmsg()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ struct sockaddr_un sun;
+
+ tempfd = socket (AF_UNIX, SOCK_DGRAM, 0);
+ if (tempfd == -1)
+ {
+ printf ("%s: first socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int tries = 0;
+ do
+ {
+ if (++tries > 10)
+ {
+ printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+ }
+
+ strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-7-XXXXXX");
+ if (mktemp (sun.sun_path) == NULL)
+ {
+ printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+ exit (1);
+ }
+
+ sun.sun_family = AF_UNIX;
+ }
+ while (bind (tempfd, (struct sockaddr *) &sun,
+ offsetof (struct sockaddr_un, sun_path)
+ + strlen (sun.sun_path) + 1) != 0);
+ tempfname = strdup (sun.sun_path);
+
+ tempfd2 = socket (AF_UNIX, SOCK_DGRAM, 0);
+ if (tempfd2 == -1)
+ {
+ printf ("%s: second socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ char mem[1];
+ struct iovec iov[1];
+ iov[0].iov_base = mem;
+ iov[0].iov_len = 1;
+
+ struct msghdr m;
+ m.msg_name = &sun;
+ m.msg_namelen = (offsetof (struct sockaddr_un, sun_path)
+ + strlen (sun.sun_path) + 1);
+ m.msg_iov = iov;
+ m.msg_iovlen = 1;
+ m.msg_control = NULL;
+ m.msg_controllen = 0;
+
+ sendmsg (tempfd2, &m, 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: sendmsg returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_creat (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which sendmsg()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ creat ("tmp/tst-cancel-4-should-not-exist", 0666);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: creat returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_connect (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which connect()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ struct sockaddr_un sun;
+
+ tempfd = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (tempfd == -1)
+ {
+ printf ("%s: first socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int tries = 0;
+ do
+ {
+ if (++tries > 10)
+ {
+ printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+ }
+
+ strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-2-XXXXXX");
+ if (mktemp (sun.sun_path) == NULL)
+ {
+ printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+ exit (1);
+ }
+
+ sun.sun_family = AF_UNIX;
+ }
+ while (bind (tempfd, (struct sockaddr *) &sun,
+ offsetof (struct sockaddr_un, sun_path)
+ + strlen (sun.sun_path) + 1) != 0);
+ tempfname = strdup (sun.sun_path);
+
+ listen (tempfd, 5);
+
+ tempfd2 = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (tempfd2 == -1)
+ {
+ printf ("%s: second socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ connect (tempfd2, (struct sockaddr *) &sun, sizeof (sun));
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: connect returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_tcdrain (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which tcdrain()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ /* Regardless of stderr being a terminal, the tcdrain call should be
+ canceled. */
+ tcdrain (STDERR_FILENO);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: tcdrain returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_msgrcv (void *arg)
+{
+ tempmsg = msgget (IPC_PRIVATE, 0666 | IPC_CREAT);
+ if (tempmsg == -1)
+ {
+ printf ("%s: msgget failed: %s\n", __FUNCTION__, strerror (errno));
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ ssize_t s;
+
+ pthread_cleanup_push (cl, NULL);
+
+ struct
+ {
+ long int type;
+ char mem[10];
+ } m;
+ int randnr;
+ /* We need a positive random number. */
+ do
+ randnr = random () % 64000;
+ while (randnr <= 0);
+ do
+ {
+ errno = 0;
+ s = msgrcv (tempmsg, (struct msgbuf *) &m, 10, randnr, 0);
+ }
+ while (errno == EIDRM || errno == EINTR);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: msgrcv returned %zd with errno = %m\n", __FUNCTION__, s);
+
+ msgctl (tempmsg, IPC_RMID, NULL);
+
+ exit (1);
+}
+
+
+static void *
+tf_msgsnd (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which msgsnd()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ tempmsg = msgget (IPC_PRIVATE, 0666 | IPC_CREAT);
+ if (tempmsg == -1)
+ {
+ printf ("%s: msgget failed: %s\n", __FUNCTION__, strerror (errno));
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ struct
+ {
+ long int type;
+ char mem[1];
+ } m;
+ /* We need a positive random number. */
+ do
+ m.type = random () % 64000;
+ while (m.type <= 0);
+ msgsnd (tempmsg, (struct msgbuf *) &m, sizeof (m.mem), 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: msgsnd returned\n", __FUNCTION__);
+
+ msgctl (tempmsg, IPC_RMID, NULL);
+
+ exit (1);
+}
+
+
+static struct
+{
+ const char *name;
+ void *(*tf) (void *);
+ int nb;
+ int only_early;
+} tests[] =
+{
+#define ADD_TEST(name, nbar, early) { #name, tf_##name, nbar, early }
+ ADD_TEST (read, 2, 0),
+ ADD_TEST (readv, 2, 0),
+ ADD_TEST (select, 2, 0),
+ ADD_TEST (pselect, 2, 0),
+ ADD_TEST (poll, 2, 0),
+ ADD_TEST (ppoll, 2, 0),
+ ADD_TEST (write, 2, 0),
+ ADD_TEST (writev, 2, 0),
+ ADD_TEST (sleep, 2, 0),
+ ADD_TEST (usleep, 2, 0),
+ ADD_TEST (nanosleep, 2, 0),
+ ADD_TEST (wait, 2, 0),
+ ADD_TEST (waitid, 2, 0),
+ ADD_TEST (waitpid, 2, 0),
+ ADD_TEST (sigpause, 2, 0),
+ ADD_TEST (sigsuspend, 2, 0),
+ ADD_TEST (sigwait, 2, 0),
+ ADD_TEST (sigwaitinfo, 2, 0),
+ ADD_TEST (sigtimedwait, 2, 0),
+ ADD_TEST (pause, 2, 0),
+ ADD_TEST (accept, 2, 0),
+ ADD_TEST (send, 2, 0),
+ ADD_TEST (recv, 2, 0),
+ ADD_TEST (recvfrom, 2, 0),
+ ADD_TEST (recvmsg, 2, 0),
+ ADD_TEST (open, 2, 1),
+ ADD_TEST (close, 2, 1),
+ ADD_TEST (pread, 2, 1),
+ ADD_TEST (pwrite, 2, 1),
+ ADD_TEST (fsync, 2, 1),
+ ADD_TEST (fdatasync, 2, 1),
+ ADD_TEST (msync, 2, 1),
+ ADD_TEST (sendto, 2, 1),
+ ADD_TEST (sendmsg, 2, 1),
+ ADD_TEST (creat, 2, 1),
+ ADD_TEST (connect, 2, 1),
+ ADD_TEST (tcdrain, 2, 1),
+ ADD_TEST (msgrcv, 2, 0),
+ ADD_TEST (msgsnd, 2, 1),
+};
+#define ntest_tf (sizeof (tests) / sizeof (tests[0]))
+
+
+static int
+do_test (void)
+{
+ int val;
+ socklen_t len;
+
+#ifdef __FreeBSD_kernel__
+ if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) != 0)
+#else
+ if (socketpair (AF_UNIX, SOCK_STREAM, PF_UNIX, fds) != 0)
+#endif
+ {
+ perror ("socketpair");
+ exit (1);
+ }
+
+ val = 1;
+ len = sizeof(val);
+ setsockopt (fds[1], SOL_SOCKET, SO_SNDBUF, &val, sizeof(val));
+ if (getsockopt (fds[1], SOL_SOCKET, SO_SNDBUF, &val, &len) < 0)
+ {
+ perror ("getsockopt");
+ exit (1);
+ }
+ if (val >= WRITE_BUFFER_SIZE)
+ {
+ puts ("minimum write buffer size too large");
+ exit (1);
+ }
+ setsockopt (fds[1], SOL_SOCKET, SO_SNDBUF, &val, sizeof(val));
+
+ int result = 0;
+ size_t cnt;
+ for (cnt = 0; cnt < ntest_tf; ++cnt)
+ {
+ if (tests[cnt].only_early)
+ continue;
+
+ if (pthread_barrier_init (&b2, NULL, tests[cnt].nb) != 0)
+ {
+ puts ("b2 init failed");
+ exit (1);
+ }
+
+ /* Reset the counter for the cleanup handler. */
+ cl_called = 0;
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tests[cnt].tf, NULL) != 0)
+ {
+ printf ("create for '%s' test failed\n", tests[cnt].name);
+ result = 1;
+ continue;
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ result = 1;
+ continue;
+ }
+
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+ while (nanosleep (&ts, &ts) != 0)
+ continue;
+
+ if (pthread_cancel (th) != 0)
+ {
+ printf ("cancel for '%s' failed\n", tests[cnt].name);
+ result = 1;
+ continue;
+ }
+
+ void *status;
+ if (pthread_join (th, &status) != 0)
+ {
+ printf ("join for '%s' failed\n", tests[cnt].name);
+ result = 1;
+ continue;
+ }
+ if (status != PTHREAD_CANCELED)
+ {
+ printf ("thread for '%s' not canceled\n", tests[cnt].name);
+ result = 1;
+ continue;
+ }
+
+ if (pthread_barrier_destroy (&b2) != 0)
+ {
+ puts ("barrier_destroy failed");
+ result = 1;
+ continue;
+ }
+
+ if (cl_called == 0)
+ {
+ printf ("cleanup handler not called for '%s'\n", tests[cnt].name);
+ result = 1;
+ continue;
+ }
+ if (cl_called > 1)
+ {
+ printf ("cleanup handler called more than once for '%s'\n",
+ tests[cnt].name);
+ result = 1;
+ continue;
+ }
+
+ printf ("in-time cancel test of '%s' successful\n", tests[cnt].name);
+
+ if (tempfd != -1)
+ {
+ close (tempfd);
+ tempfd = -1;
+ }
+ if (tempfd2 != -1)
+ {
+ close (tempfd2);
+ tempfd2 = -1;
+ }
+ if (tempfname != NULL)
+ {
+ unlink (tempfname);
+ free (tempfname);
+ tempfname = NULL;
+ }
+ if (tempmsg != -1)
+ {
+ msgctl (tempmsg, IPC_RMID, NULL);
+ tempmsg = -1;
+ }
+ }
+
+ for (cnt = 0; cnt < ntest_tf; ++cnt)
+ {
+ if (pthread_barrier_init (&b2, NULL, tests[cnt].nb) != 0)
+ {
+ puts ("b2 init failed");
+ exit (1);
+ }
+
+ /* Reset the counter for the cleanup handler. */
+ cl_called = 0;
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tests[cnt].tf, (void *) 1l) != 0)
+ {
+ printf ("create for '%s' test failed\n", tests[cnt].name);
+ result = 1;
+ continue;
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ result = 1;
+ continue;
+ }
+
+ if (pthread_cancel (th) != 0)
+ {
+ printf ("cancel for '%s' failed\n", tests[cnt].name);
+ result = 1;
+ continue;
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ result = 1;
+ continue;
+ }
+
+ void *status;
+ if (pthread_join (th, &status) != 0)
+ {
+ printf ("join for '%s' failed\n", tests[cnt].name);
+ result = 1;
+ continue;
+ }
+ if (status != PTHREAD_CANCELED)
+ {
+ printf ("thread for '%s' not canceled\n", tests[cnt].name);
+ result = 1;
+ continue;
+ }
+
+ if (pthread_barrier_destroy (&b2) != 0)
+ {
+ puts ("barrier_destroy failed");
+ result = 1;
+ continue;
+ }
+
+ if (cl_called == 0)
+ {
+ printf ("cleanup handler not called for '%s'\n", tests[cnt].name);
+ result = 1;
+ continue;
+ }
+ if (cl_called > 1)
+ {
+ printf ("cleanup handler called more than once for '%s'\n",
+ tests[cnt].name);
+ result = 1;
+ continue;
+ }
+
+ printf ("early cancel test of '%s' successful\n", tests[cnt].name);
+
+ if (tempfd != -1)
+ {
+ close (tempfd);
+ tempfd = -1;
+ }
+ if (tempfd2 != -1)
+ {
+ close (tempfd2);
+ tempfd2 = -1;
+ }
+ if (tempfname != NULL)
+ {
+ unlink (tempfname);
+ free (tempfname);
+ tempfname = NULL;
+ }
+ if (tempmsg != -1)
+ {
+ msgctl (tempmsg, IPC_RMID, NULL);
+ tempmsg = -1;
+ }
+ }
+
+ return result;
+}
+
+#define TIMEOUT 60
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel5.c
@@ -0,0 +1 @@
+#include "tst-cancel4.c"
--- /dev/null
+++ b/fbtl/tst-cancel6.c
@@ -0,0 +1,78 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static void *
+tf (void *arg)
+{
+ char buf[100];
+ fgets (buf, sizeof (buf), arg);
+ /* This call should never return. */
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ int fd[2];
+ if (pipe (fd) != 0)
+ {
+ puts ("pipe failed");
+ return 1;
+ }
+
+ FILE *fp = fdopen (fd[0], "r");
+ if (fp == NULL)
+ {
+ puts ("fdopen failed");
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, fp) != 0)
+ {
+ puts ("pthread_create failed");
+ return 1;
+ }
+
+ sleep (1);
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("pthread_cancel failed");
+ return 1;
+ }
+
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("pthread_join failed");
+ return 1;
+ }
+
+ return r != PTHREAD_CANCELED;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel7.c
@@ -0,0 +1,210 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+const char *command;
+const char *pidfile;
+char pidfilename[] = "/tmp/tst-cancel7-XXXXXX";
+
+static void *
+tf (void *arg)
+{
+ const char *args = " --direct --pidfile ";
+ char *cmd = alloca (strlen (command) + strlen (args)
+ + strlen (pidfilename) + 1);
+
+ strcpy (stpcpy (stpcpy (cmd, command), args), pidfilename);
+ system (cmd);
+ /* This call should never return. */
+ return NULL;
+}
+
+
+static void
+sl (void)
+{
+ FILE *f = fopen (pidfile, "w");
+ if (f == NULL)
+ exit (1);
+
+ fprintf (f, "%lld\n", (long long) getpid ());
+ fflush (f);
+
+ struct flock fl =
+ {
+ .l_type = F_WRLCK,
+ .l_start = 0,
+ .l_whence = SEEK_SET,
+ .l_len = 1
+ };
+ if (fcntl (fileno (f), F_SETLK, &fl) != 0)
+ exit (1);
+
+ sigset_t ss;
+ sigfillset (&ss);
+ sigsuspend (&ss);
+ exit (0);
+}
+
+
+static void
+do_prepare (int argc, char *argv[])
+{
+ if (command == NULL)
+ command = argv[0];
+
+ if (pidfile)
+ sl ();
+
+ int fd = mkstemp (pidfilename);
+ if (fd == -1)
+ {
+ puts ("mkstemp failed");
+ exit (1);
+ }
+
+ write (fd, " ", 1);
+ close (fd);
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("pthread_create failed");
+ return 1;
+ }
+
+ do
+ sleep (1);
+ while (access (pidfilename, R_OK) != 0);
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("pthread_cancel failed");
+ return 1;
+ }
+
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("pthread_join failed");
+ return 1;
+ }
+
+ sleep (1);
+
+ FILE *f = fopen (pidfilename, "r+");
+ if (f == NULL)
+ {
+ puts ("no pidfile");
+ return 1;
+ }
+
+ long long ll;
+ if (fscanf (f, "%lld\n", &ll) != 1)
+ {
+ puts ("could not read pid");
+ unlink (pidfilename);
+ return 1;
+ }
+
+ struct flock fl =
+ {
+ .l_type = F_WRLCK,
+ .l_start = 0,
+ .l_whence = SEEK_SET,
+ .l_len = 1
+ };
+ if (fcntl (fileno (f), F_GETLK, &fl) != 0)
+ {
+ puts ("F_GETLK failed");
+ unlink (pidfilename);
+ return 1;
+ }
+
+ if (fl.l_type != F_UNLCK)
+ {
+ printf ("child %lld still running\n", (long long) fl.l_pid);
+ if (fl.l_pid == ll)
+ kill (fl.l_pid, SIGKILL);
+
+ unlink (pidfilename);
+ return 1;
+ }
+
+ fclose (f);
+
+ unlink (pidfilename);
+
+ return r != PTHREAD_CANCELED;
+}
+
+static void
+do_cleanup (void)
+{
+ FILE *f = fopen (pidfilename, "r+");
+ long long ll;
+
+ if (f != NULL && fscanf (f, "%lld\n", &ll) == 1)
+ {
+ struct flock fl =
+ {
+ .l_type = F_WRLCK,
+ .l_start = 0,
+ .l_whence = SEEK_SET,
+ .l_len = 1
+ };
+ if (fcntl (fileno (f), F_GETLK, &fl) == 0 && fl.l_type != F_UNLCK
+ && fl.l_pid == ll)
+ kill (fl.l_pid, SIGKILL);
+
+ fclose (f);
+ }
+
+ unlink (pidfilename);
+}
+
+#define OPT_COMMAND 10000
+#define OPT_PIDFILE 10001
+#define CMDLINE_OPTIONS \
+ { "command", required_argument, NULL, OPT_COMMAND }, \
+ { "pidfile", required_argument, NULL, OPT_PIDFILE },
+#define CMDLINE_PROCESS \
+ case OPT_COMMAND: \
+ command = optarg; \
+ break; \
+ case OPT_PIDFILE: \
+ pidfile = optarg; \
+ break;
+#define CLEANUP_HANDLER do_cleanup ()
+#define PREPARE(argc, argv) do_prepare (argc, argv)
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 5
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel8.c
@@ -0,0 +1,142 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static pthread_barrier_t bar;
+
+static int global;
+
+
+static void
+cleanup (void *arg)
+{
+ global = 1;
+}
+
+
+static void *
+tf (void *arg)
+{
+ /* Enable cancellation, but defer it. */
+ if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0)
+ {
+ puts ("setcancelstate failed");
+ exit (1);
+ }
+ if (pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL) != 0)
+ {
+ puts ("setcanceltype failed");
+ exit (1);
+ }
+
+ /* Add cleanup handler. */
+ pthread_cleanup_push (cleanup, NULL);
+
+ /* Synchronize with the main thread. */
+ int r = pthread_barrier_wait (&bar);
+ if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("tf: first barrier_wait failed");
+ exit (1);
+ }
+
+ /* And again. Once this is done the main thread should have canceled
+ this thread. */
+ r = pthread_barrier_wait (&bar);
+ if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("tf: second barrier_wait failed");
+ exit (1);
+ }
+
+ /* Remove the cleanup handler without executing it. */
+ pthread_cleanup_pop (0);
+
+ /* Now react on the cancellation. */
+ pthread_testcancel ();
+
+ /* This call should never return. */
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ if (pthread_barrier_init (&bar, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("pthread_create failed");
+ return 1;
+ }
+
+ int r = pthread_barrier_wait (&bar);
+ if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("first barrier_wait failed");
+ exit (1);
+ }
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("pthread_cancel failed");
+ return 1;
+ }
+
+ r = pthread_barrier_wait (&bar);
+ if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("second barrier_wait failed");
+ exit (1);
+ }
+
+ void *result;
+ if (pthread_join (th, &result) != 0)
+ {
+ puts ("pthread_join failed");
+ return 1;
+ }
+
+ if (result != PTHREAD_CANCELED)
+ {
+ puts ("thread was not canceled");
+ exit (1);
+ }
+
+ if (global != 0)
+ {
+ puts ("cancellation handler has been called");
+ exit (1);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancel9.c
@@ -0,0 +1,125 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+static pthread_barrier_t b;
+
+
+static void
+cleanup (void *arg)
+{
+ fputs ("in cleanup\n", stdout);
+}
+
+
+static void *
+tf (void *arg)
+{
+ int fd = open ("/dev/null", O_RDWR);
+ if (fd == -1)
+ {
+ puts ("cannot open /dev/null");
+ exit (1);
+ }
+ FILE *fp = fdopen (fd, "w");
+ if (fp == NULL)
+ {
+ puts ("fdopen failed");
+ exit (1);
+ }
+
+ pthread_cleanup_push (cleanup, NULL);
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ while (1)
+ /* fprintf() uses write() which is a cancallation point. */
+ fprintf (fp, "foo");
+
+ pthread_cleanup_pop (0);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ sleep (1);
+
+ puts ("cancel now");
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cancel failed");
+ exit (1);
+ }
+
+ puts ("waiting for the child");
+
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("thread wasn't canceled");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cancelx1.c
@@ -0,0 +1 @@
+#include "tst-cancel1.c"
--- /dev/null
+++ b/fbtl/tst-cancelx10.c
@@ -0,0 +1 @@
+#include "tst-cancel10.c"
--- /dev/null
+++ b/fbtl/tst-cancelx11.c
@@ -0,0 +1 @@
+#include "tst-cancel11.c"
--- /dev/null
+++ b/fbtl/tst-cancelx12.c
@@ -0,0 +1 @@
+#include "tst-cancel12.c"
--- /dev/null
+++ b/fbtl/tst-cancelx13.c
@@ -0,0 +1 @@
+#include "tst-cancel13.c"
--- /dev/null
+++ b/fbtl/tst-cancelx14.c
@@ -0,0 +1 @@
+#include "tst-cancel14.c"
--- /dev/null
+++ b/fbtl/tst-cancelx15.c
@@ -0,0 +1 @@
+#include "tst-cancel15.c"
--- /dev/null
+++ b/fbtl/tst-cancelx16.c
@@ -0,0 +1 @@
+#include "tst-cancel16.c"
--- /dev/null
+++ b/fbtl/tst-cancelx17.c
@@ -0,0 +1 @@
+#include "tst-cancel17.c"
--- /dev/null
+++ b/fbtl/tst-cancelx18.c
@@ -0,0 +1 @@
+#include "tst-cancel18.c"
--- /dev/null
+++ b/fbtl/tst-cancelx2.c
@@ -0,0 +1 @@
+#include "tst-cancel2.c"
--- /dev/null
+++ b/fbtl/tst-cancelx20.c
@@ -0,0 +1 @@
+#include "tst-cancel20.c"
--- /dev/null
+++ b/fbtl/tst-cancelx21.c
@@ -0,0 +1 @@
+#include "tst-cancel21.c"
--- /dev/null
+++ b/fbtl/tst-cancelx3.c
@@ -0,0 +1 @@
+#include "tst-cancel3.c"
--- /dev/null
+++ b/fbtl/tst-cancelx4.c
@@ -0,0 +1 @@
+#include "tst-cancel4.c"
--- /dev/null
+++ b/fbtl/tst-cancelx5.c
@@ -0,0 +1 @@
+#include "tst-cancel5.c"
--- /dev/null
+++ b/fbtl/tst-cancelx6.c
@@ -0,0 +1 @@
+#include "tst-cancel6.c"
--- /dev/null
+++ b/fbtl/tst-cancelx7.c
@@ -0,0 +1 @@
+#include "tst-cancel7.c"
--- /dev/null
+++ b/fbtl/tst-cancelx8.c
@@ -0,0 +1 @@
+#include "tst-cancel8.c"
--- /dev/null
+++ b/fbtl/tst-cancelx9.c
@@ -0,0 +1 @@
+#include "tst-cancel9.c"
--- /dev/null
+++ b/fbtl/tst-cleanup0.c
@@ -0,0 +1,75 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static int global;
+
+
+static void
+ch (void *arg)
+{
+ int val = (long int) arg;
+
+ printf ("ch (%d)\n", val);
+
+ global *= val;
+ global += val;
+}
+
+
+static void
+endfct (void)
+{
+ /* We force exit right here. */
+ _exit (global);
+}
+
+
+static int
+do_test (void)
+{
+ atexit (endfct);
+
+ pthread_cancel (pthread_self ());
+
+ pthread_cleanup_push (ch, (void *) 1l);
+
+ pthread_cleanup_push (ch, (void *) 2l);
+
+ pthread_cleanup_push (ch, (void *) 3l);
+
+ pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+
+ pthread_cleanup_pop (1);
+
+ pthread_cleanup_pop (1);
+
+ pthread_cleanup_pop (1);
+
+ return 100;
+}
+
+
+#define EXPECTED_STATUS 9
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cleanup0.expect
@@ -0,0 +1,3 @@
+ch (3)
+ch (2)
+ch (1)
--- /dev/null
+++ b/fbtl/tst-cleanup1.c
@@ -0,0 +1,99 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static int global;
+
+
+static void
+ch (void *arg)
+{
+ int val = (long int) arg;
+
+ printf ("ch (%d)\n", val);
+
+ global *= val;
+ global += val;
+}
+
+
+static void *
+tf (void *a)
+{
+ pthread_cancel (pthread_self ());
+
+ pthread_cleanup_push (ch, (void *) 1l);
+
+ pthread_cleanup_push (ch, (void *) 2l);
+
+ pthread_cleanup_push (ch, (void *) 3l);
+
+ pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+
+ pthread_cleanup_pop (1);
+
+ pthread_cleanup_pop (1);
+
+ pthread_cleanup_pop (1);
+
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ write (2, "create failed\n", 14);
+ _exit (1);
+ }
+
+ void *r;
+ int e;
+ if ((e = pthread_join (th, &r)) != 0)
+ {
+ printf ("join failed: %d\n", e);
+ _exit (1);
+ }
+
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("thread not canceled");
+ exit (1);
+ }
+
+ if (global != 9)
+ {
+ printf ("global = %d, expected 9\n", global);
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cleanup2.c
@@ -0,0 +1,62 @@
+/* Copyright (C) 2003-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Bao Duong <bduong@progress.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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+static sigjmp_buf jmpbuf;
+
+static void
+sig_handler (int signo)
+{
+ siglongjmp (jmpbuf, 1);
+}
+
+static int
+do_test (void)
+{
+ char *p = NULL;
+ struct sigaction sa;
+
+ sa.sa_handler = sig_handler;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO;
+
+ if (sigaction (SIGSEGV, &sa, 0))
+ {
+ perror ("installing SIGSEGV handler\n");
+ exit (1);
+ }
+
+ puts ("Attempting to sprintf to null ptr");
+ if (setjmp (jmpbuf))
+ {
+ puts ("Exiting main...");
+ return 0;
+ }
+
+ sprintf (p, "This should segv\n");
+
+ return 1;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cleanup3.c
@@ -0,0 +1,97 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static int global;
+
+
+static void
+ch (void *arg)
+{
+ int val = (long int) arg;
+
+ printf ("ch (%d)\n", val);
+
+ global *= val;
+ global += val;
+}
+
+
+static void *
+tf (void *a)
+{
+ pthread_cleanup_push (ch, (void *) 1l);
+
+ pthread_cleanup_push (ch, (void *) 2l);
+
+ pthread_cleanup_push (ch, (void *) 3l);
+
+ pthread_exit ((void *) 1l);
+
+ pthread_cleanup_pop (1);
+
+ pthread_cleanup_pop (1);
+
+ pthread_cleanup_pop (1);
+
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ write (2, "create failed\n", 14);
+ _exit (1);
+ }
+
+ void *r;
+ int e;
+ if ((e = pthread_join (th, &r)) != 0)
+ {
+ printf ("join failed: %d\n", e);
+ _exit (1);
+ }
+
+ if (r != (void *) 1l)
+ {
+ puts ("thread not canceled");
+ exit (1);
+ }
+
+ if (global != 9)
+ {
+ printf ("global = %d, expected 9\n", global);
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cleanup4.c
@@ -0,0 +1,197 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/* LinuxThreads pthread_cleanup_{push,pop} helpers. */
+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);
+
+static int fds[2];
+static pthread_barrier_t b2;
+static int global;
+
+/* Defined in tst-cleanup4aux.c, never compiled with -fexceptions. */
+extern void fn5 (void);
+extern void fn7 (void);
+extern void fn9 (void);
+
+void
+clh (void *arg)
+{
+ int val = (long int) arg;
+
+ printf ("clh (%d)\n", val);
+
+ global *= val;
+ global += val;
+}
+
+
+static __attribute__((noinline)) void
+fn_read (void)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ char c;
+ read (fds[0], &c, 1);
+}
+
+
+__attribute__((noinline)) void
+fn0 (void)
+{
+ pthread_cleanup_push (clh, (void *) 1l);
+
+ fn_read ();
+
+ pthread_cleanup_pop (1);
+}
+
+
+__attribute__((noinline)) void
+fn1 (void)
+{
+ /* This is the old LinuxThreads pthread_cleanup_{push,pop}. */
+ struct _pthread_cleanup_buffer b;
+ _pthread_cleanup_push (&b, clh, (void *) 2l);
+
+ fn0 ();
+
+ _pthread_cleanup_pop (&b, 1);
+}
+
+
+static __attribute__((noinline)) void
+fn2 (void)
+{
+ pthread_cleanup_push (clh, (void *) 3l);
+
+ fn1 ();
+
+ pthread_cleanup_pop (1);
+}
+
+
+static void *
+tf (void *a)
+{
+ switch ((long) a)
+ {
+ case 0:
+ fn2 ();
+ break;
+ case 1:
+ fn5 ();
+ break;
+ case 2:
+ fn7 ();
+ break;
+ case 3:
+ fn9 ();
+ break;
+ }
+
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+ int result = 0;
+
+ if (pipe (fds) != 0)
+ {
+ puts ("pipe failed");
+ exit (1);
+ }
+
+ if (pthread_barrier_init (&b2, NULL, 2) != 0)
+ {
+ puts ("b2 init failed");
+ exit (1);
+ }
+
+ const int expect[] =
+ {
+ 15, /* 1 2 3 */
+ 276, /* 1 4 5 6 */
+ 120, /* 1 7 8 */
+ 460 /* 1 2 9 10 */
+ };
+
+ long i;
+ for (i = 0; i < 4; ++i)
+ {
+ global = 0;
+
+ printf ("test %ld\n", i);
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, (void *) i) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&b2);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cancel (th);
+
+ void *r;
+ if ((e = pthread_join (th, &r)) != 0)
+ {
+ printf ("join failed: %d\n", e);
+ _exit (1);
+ }
+
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("thread not canceled");
+ exit (1);
+ }
+
+ if (global != expect[i])
+ {
+ printf ("global = %d, expected %d\n", global, expect[i]);
+ result = 1;
+ }
+ }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cleanup4aux.c
@@ -0,0 +1,120 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+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 clh (void *arg);
+extern void fn0 (void);
+extern void fn1 (void);
+extern void fn5 (void);
+extern void fn7 (void);
+extern void fn9 (void);
+
+
+static __attribute__((noinline)) void
+fn3 (void)
+{
+ /* This is the old LinuxThreads pthread_cleanup_{push,pop}. */
+ struct _pthread_cleanup_buffer b;
+ _pthread_cleanup_push (&b, clh, (void *) 4l);
+
+ fn0 ();
+
+ _pthread_cleanup_pop (&b, 1);
+}
+
+
+static __attribute__((noinline)) void
+fn4 (void)
+{
+ pthread_cleanup_push (clh, (void *) 5l);
+
+ fn3 ();
+
+ pthread_cleanup_pop (1);
+}
+
+
+void
+fn5 (void)
+{
+ /* This is the old LinuxThreads pthread_cleanup_{push,pop}. */
+ struct _pthread_cleanup_buffer b;
+ _pthread_cleanup_push (&b, clh, (void *) 6l);
+
+ fn4 ();
+
+ _pthread_cleanup_pop (&b, 1);
+}
+
+
+static __attribute__((noinline)) void
+fn6 (void)
+{
+ pthread_cleanup_push (clh, (void *) 7l);
+
+ fn0 ();
+
+ pthread_cleanup_pop (1);
+}
+
+
+void
+fn7 (void)
+{
+ /* This is the old LinuxThreads pthread_cleanup_{push,pop}. */
+ struct _pthread_cleanup_buffer b;
+ _pthread_cleanup_push (&b, clh, (void *) 8l);
+
+ fn6 ();
+
+ _pthread_cleanup_pop (&b, 1);
+}
+
+
+static __attribute__((noinline)) void
+fn8 (void)
+{
+ pthread_cleanup_push (clh, (void *) 9l);
+
+ fn1 ();
+
+ pthread_cleanup_pop (1);
+}
+
+
+void
+fn9 (void)
+{
+ /* This is the old LinuxThreads pthread_cleanup_{push,pop}. */
+ struct _pthread_cleanup_buffer b;
+ _pthread_cleanup_push (&b, clh, (void *) 10l);
+
+ fn8 ();
+
+ _pthread_cleanup_pop (&b, 1);
+}
--- /dev/null
+++ b/fbtl/tst-cleanupx0.c
@@ -0,0 +1 @@
+#include "tst-cleanup0.c"
--- /dev/null
+++ b/fbtl/tst-cleanupx0.expect
@@ -0,0 +1,3 @@
+ch (3)
+ch (2)
+ch (1)
--- /dev/null
+++ b/fbtl/tst-cleanupx1.c
@@ -0,0 +1 @@
+#include "tst-cleanup1.c"
--- /dev/null
+++ b/fbtl/tst-cleanupx2.c
@@ -0,0 +1 @@
+#include "tst-cleanup2.c"
--- /dev/null
+++ b/fbtl/tst-cleanupx3.c
@@ -0,0 +1 @@
+#include "tst-cleanup3.c"
--- /dev/null
+++ b/fbtl/tst-cleanupx4.c
@@ -0,0 +1 @@
+#include "tst-cleanup4.c"
--- /dev/null
+++ b/fbtl/tst-clock1.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+
+int
+do_test (void)
+{
+#if defined _POSIX_THREAD_CPUTIME && _POSIX_THREAD_CPUTIME >= 0
+ clockid_t cl;
+ /* This is really only a linking-test here. */
+ int e = pthread_getcpuclockid (pthread_self (), &cl);
+ if (e != 0)
+ {
+# if _POSIX_THREAD_CPUTIME == 0
+ if (sysconf (_SC_THREAD_CPUTIME) >= 0)
+# endif
+ {
+ puts ("cpuclock advertized, but cannot get ID");
+ exit (1);
+ }
+ }
+#endif
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-clock2.c
@@ -0,0 +1,201 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+
+#if defined _POSIX_THREAD_CPUTIME && _POSIX_THREAD_CPUTIME >= 0
+static pthread_barrier_t b2;
+static pthread_barrier_t bN;
+
+
+static void *
+tf (void *arg)
+{
+ int e = pthread_barrier_wait (&b2);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ e = pthread_barrier_wait (&bN);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ return NULL;
+}
+#endif
+
+
+int
+do_test (void)
+{
+#if defined _POSIX_THREAD_CPUTIME && _POSIX_THREAD_CPUTIME >= 0
+# define N 10
+
+# if _POSIX_THREAD_CPUTIME == 0
+ if (sysconf (_SC_THREAD_CPUTIME) < 0)
+ {
+ puts ("_POSIX_THREAD_CPUTIME option not available");
+ return 0;
+ }
+# endif
+
+ if (pthread_barrier_init (&b2, NULL, 2) != 0
+ || pthread_barrier_init (&bN, NULL, N + 1) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+ TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
+
+ pthread_t th[N + 1];
+ clockid_t cl[N + 1];
+# ifndef CLOCK_THREAD_CPUTIME_ID
+ if (pthread_getcpuclockid (pthread_self (), &cl[0]) != 0)
+ {
+ puts ("own pthread_getcpuclockid failed");
+ return 1;
+ }
+# else
+ cl[0] = CLOCK_THREAD_CPUTIME_ID;
+# endif
+
+ pthread_attr_t at;
+
+ if (pthread_attr_init (&at) != 0)
+ {
+ puts ("attr_init failed");
+ return 1;
+ }
+
+ if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+ int i;
+ int e;
+ for (i = 0; i < N; ++i)
+ {
+ if (pthread_create (&th[i], &at, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ e = pthread_barrier_wait (&b2);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ return 1;
+ }
+
+ ts.tv_sec = 0;
+ ts.tv_nsec = 100000000;
+ TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
+
+ if (pthread_getcpuclockid (th[i], &cl[i + 1]) != 0)
+ {
+ puts ("pthread_getcpuclockid failed");
+ return 1;
+ }
+ }
+
+ if (pthread_attr_destroy (&at) != 0)
+ {
+ puts ("attr_destroy failed");
+ return 1;
+ }
+
+ struct timespec t[N + 1];
+ for (i = 0; i < N + 1; ++i)
+ if (clock_gettime (cl[i], &t[i]) != 0)
+ {
+ printf ("clock_gettime round %d failed\n", i);
+ return 1;
+ }
+
+ for (i = 0; i < N; ++i)
+ {
+ struct timespec diff;
+
+ diff.tv_sec = t[i].tv_sec - t[i + 1].tv_sec;
+ diff.tv_nsec = t[i].tv_nsec - t[i + 1].tv_nsec;
+ if (diff.tv_nsec < 0)
+ {
+ diff.tv_nsec += 1000000000;
+ --diff.tv_sec;
+ }
+
+ if (diff.tv_sec < 0 || (diff.tv_sec == 0 && diff.tv_nsec < 100000000))
+ {
+ printf ("\
+difference between thread %d and %d too small (%ld.%09ld)\n",
+ i, i + 1, (long int) diff.tv_sec, (long int) diff.tv_nsec);
+ return 1;
+ }
+
+ printf ("diff %d->%d: %ld.%09ld\n",
+ i, i + 1, (long int) diff.tv_sec, (long int) diff.tv_nsec);
+ }
+
+ ts.tv_sec = 0;
+ ts.tv_nsec = 0;
+ for (i = 0; i < N + 1; ++i)
+ if (clock_settime (cl[i], &ts) != 0)
+ {
+ printf ("clock_settime(%d) round %d failed\n", cl[i], i);
+ return 1;
+ }
+
+ for (i = 0; i < N + 1; ++i)
+ {
+ if (clock_gettime (cl[i], &ts) != 0)
+ {
+ puts ("clock_gettime failed");
+ return 1;
+ }
+
+ if (ts.tv_sec > t[i].tv_sec
+ || (ts.tv_sec == t[i].tv_sec && ts.tv_nsec > t[i].tv_nsec))
+ {
+ puts ("clock_settime didn't reset clock");
+ return 1;
+ }
+ }
+#endif
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cond-except.c
@@ -0,0 +1,110 @@
+/* Verify that exception table for pthread_cond_wait is correct.
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+pthread_mutex_t mutex;
+pthread_cond_t cond;
+
+#define CHECK_RETURN_VAL_OR_FAIL(ret,str) \
+ ({ if ((ret) != 0) \
+ { \
+ printf ("%s failed: %s\n", (str), strerror (ret)); \
+ ret = 1; \
+ goto out; \
+ } \
+ })
+
+
+void
+clean (void *arg)
+{
+ puts ("clean: Unlocking mutex...");
+ pthread_mutex_unlock ((pthread_mutex_t *) arg);
+ puts ("clean: Mutex unlocked...");
+}
+
+void *
+thr (void *arg)
+{
+ int ret = 0;
+ pthread_mutexattr_t mutexAttr;
+ ret = pthread_mutexattr_init (&mutexAttr);
+ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_mutexattr_init");
+
+ ret = pthread_mutexattr_setprotocol (&mutexAttr, PTHREAD_PRIO_INHERIT);
+ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_mutexattr_setprotocol");
+
+ ret = pthread_mutex_init (&mutex, &mutexAttr);
+ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_mutex_init");
+
+ ret = pthread_cond_init (&cond, 0);
+ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_cond_init");
+
+ puts ("th: Init done, entering wait...");
+
+ pthread_cleanup_push (clean, (void *) &mutex);
+ ret = pthread_mutex_lock (&mutex);
+ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_mutex_lock");
+ while (1)
+ {
+ ret = pthread_cond_wait (&cond, &mutex);
+ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_cond_wait");
+ }
+ pthread_cleanup_pop (1);
+
+out:
+ return (void *) (uintptr_t) ret;
+}
+
+int
+do_test (void)
+{
+ pthread_t thread;
+ int ret = 0;
+ void *thr_ret = 0;
+ ret = pthread_create (&thread, 0, thr, &thr_ret);
+ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_create");
+
+ puts ("main: Thread created, waiting a bit...");
+ sleep (2);
+
+ puts ("main: Cancelling thread...");
+ ret = pthread_cancel (thread);
+ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_cancel");
+
+ puts ("main: Joining th...");
+ ret = pthread_join (thread, NULL);
+ CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_join");
+
+ if (thr_ret != NULL)
+ return 1;
+
+ puts ("main: Joined thread, done!");
+
+out:
+ return ret;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 5
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cond1.c
@@ -0,0 +1,93 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <error.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void *
+tf (void *p)
+{
+ int err;
+
+ err = pthread_mutex_lock (&mut);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "child: cannot get mutex");
+
+ puts ("child: got mutex; signalling");
+
+ pthread_cond_signal (&cond);
+
+ puts ("child: unlock");
+
+ err = pthread_mutex_unlock (&mut);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "child: cannot unlock");
+
+ puts ("child: done");
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+ int err;
+
+ printf ("&cond = %p\n&mut = %p\n", &cond, &mut);
+
+ puts ("parent: get mutex");
+
+ err = pthread_mutex_lock (&mut);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "parent: cannot get mutex");
+
+ puts ("parent: create child");
+
+ err = pthread_create (&th, NULL, tf, NULL);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "parent: cannot create thread");
+
+ puts ("parent: wait for condition");
+
+ err = pthread_cond_wait (&cond, &mut);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "parent: cannot wait fir signal");
+
+ puts ("parent: got signal");
+
+ err = pthread_join (th, NULL);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "parent: failed to join");
+
+ puts ("done");
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cond10.c
@@ -0,0 +1,172 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <error.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+#define N 10
+#define ROUNDS 100
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+static pthread_barrier_t bN1;
+static pthread_barrier_t b2;
+
+
+static void *
+tf (void *p)
+{
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ puts ("child: 1st mutex_lock failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&b2);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child: 1st barrier_wait failed");
+ exit (1);
+ }
+
+ if (pthread_cond_wait (&cond, &mut) != 0)
+ {
+ puts ("child: cond_wait failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&mut) != 0)
+ {
+ puts ("child: mutex_unlock failed");
+ exit (1);
+ }
+
+ e = pthread_barrier_wait (&bN1);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child: 2nd barrier_wait failed");
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ if (pthread_barrier_init (&bN1, NULL, N + 1) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (pthread_barrier_init (&b2, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ pthread_attr_t at;
+
+ if (pthread_attr_init (&at) != 0)
+ {
+ puts ("attr_init failed");
+ return 1;
+ }
+
+ if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+ int r;
+ for (r = 0; r < ROUNDS; ++r)
+ {
+ printf ("round %d\n", r + 1);
+
+ int i;
+ pthread_t th[N];
+ for (i = 0; i < N; ++i)
+ {
+ if (pthread_create (&th[i], &at, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&b2);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("parent: 1st barrier_wait failed");
+ exit (1);
+ }
+ }
+
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ puts ("parent: mutex_lock failed");
+ exit (1);
+ }
+ if (pthread_mutex_unlock (&mut) != 0)
+ {
+ puts ("parent: mutex_unlock failed");
+ exit (1);
+ }
+
+ /* N single signal calls. Without locking. This tests that no
+ signal gets lost. */
+ for (i = 0; i < N; ++i)
+ if (pthread_cond_signal (&cond) != 0)
+ {
+ puts ("cond_signal failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&bN1);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("parent: 2nd barrier_wait failed");
+ exit (1);
+ }
+
+ for (i = 0; i < N; ++i)
+ if (pthread_join (th[i], NULL) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+ }
+
+ if (pthread_attr_destroy (&at) != 0)
+ {
+ puts ("attr_destroy failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cond11.c
@@ -0,0 +1,204 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+
+
+#if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0
+static int
+run_test (clockid_t cl)
+{
+ pthread_condattr_t condattr;
+ pthread_cond_t cond;
+ pthread_mutexattr_t mutattr;
+ pthread_mutex_t mut;
+
+ printf ("clock = %d\n", (int) cl);
+
+ if (pthread_condattr_init (&condattr) != 0)
+ {
+ puts ("condattr_init failed");
+ return 1;
+ }
+
+ if (pthread_condattr_setclock (&condattr, cl) != 0)
+ {
+ puts ("condattr_setclock failed");
+ return 1;
+ }
+
+ clockid_t cl2;
+ if (pthread_condattr_getclock (&condattr, &cl2) != 0)
+ {
+ puts ("condattr_getclock failed");
+ return 1;
+ }
+ if (cl != cl2)
+ {
+ printf ("condattr_getclock returned wrong value: %d, expected %d\n",
+ (int) cl2, (int) cl);
+ return 1;
+ }
+
+ if (pthread_cond_init (&cond, &condattr) != 0)
+ {
+ puts ("cond_init failed");
+ return 1;
+ }
+
+ if (pthread_condattr_destroy (&condattr) != 0)
+ {
+ puts ("condattr_destroy failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_init (&mutattr) != 0)
+ {
+ puts ("mutexattr_init failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_settype (&mutattr, PTHREAD_MUTEX_ERRORCHECK) != 0)
+ {
+ puts ("mutexattr_settype failed");
+ return 1;
+ }
+
+ if (pthread_mutex_init (&mut, &mutattr) != 0)
+ {
+ puts ("mutex_init failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_destroy (&mutattr) != 0)
+ {
+ puts ("mutexattr_destroy failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ puts ("mutex_lock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&mut) != EDEADLK)
+ {
+ puts ("2nd mutex_lock did not return EDEADLK");
+ return 1;
+ }
+
+ struct timespec ts;
+ if (clock_gettime (cl, &ts) != 0)
+ {
+ puts ("clock_gettime failed");
+ return 1;
+ }
+
+ /* Wait one second. */
+ ++ts.tv_sec;
+
+ int e = pthread_cond_timedwait (&cond, &mut, &ts);
+ if (e == 0)
+ {
+ puts ("cond_timedwait succeeded");
+ return 1;
+ }
+ else if (e != ETIMEDOUT)
+ {
+ puts ("cond_timedwait did not return ETIMEDOUT");
+ return 1;
+ }
+
+ struct timespec ts2;
+ if (clock_gettime (cl, &ts2) != 0)
+ {
+ puts ("second clock_gettime failed");
+ return 1;
+ }
+
+ if (ts2.tv_sec < ts.tv_sec
+ || (ts2.tv_sec == ts.tv_sec && ts2.tv_nsec < ts.tv_nsec))
+ {
+ puts ("timeout too short");
+ return 1;
+ }
+
+ if (pthread_mutex_unlock (&mut) != 0)
+ {
+ puts ("mutex_unlock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_destroy (&mut) != 0)
+ {
+ puts ("mutex_destroy failed");
+ return 1;
+ }
+
+ if (pthread_cond_destroy (&cond) != 0)
+ {
+ puts ("cond_destroy failed");
+ return 1;
+ }
+
+ return 0;
+}
+#endif
+
+
+static int
+do_test (void)
+{
+#if !defined _POSIX_CLOCK_SELECTION || _POSIX_CLOCK_SELECTION == -1
+
+ puts ("_POSIX_CLOCK_SELECTION not supported, test skipped");
+ return 0;
+
+#else
+
+ int res = run_test (CLOCK_REALTIME);
+
+# if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
+# if _POSIX_MONOTONIC_CLOCK == 0
+ int e = sysconf (_SC_MONOTONIC_CLOCK);
+ if (e < 0)
+ puts ("CLOCK_MONOTONIC not supported");
+ else if (e == 0)
+ {
+ puts ("sysconf (_SC_MONOTONIC_CLOCK) must not return 0");
+ res = 1;
+ }
+ else
+# endif
+ res |= run_test (CLOCK_MONOTONIC);
+# else
+ puts ("_POSIX_MONOTONIC_CLOCK not defined");
+# endif
+
+ return res;
+#endif
+}
+
+#define TIMEOUT 3
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cond12.c
@@ -0,0 +1,195 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+
+static char fname[] = "/tmp/tst-cond12-XXXXXX";
+static int fd;
+
+
+static void prepare (void);
+#define PREPARE(argc, argv) prepare ()
+
+static int do_test (void);
+#define TEST_FUNCTION do_test ()
+
+#include "../test-skeleton.c"
+
+
+static void
+prepare (void)
+{
+ fd = mkstemp (fname);
+ if (fd == -1)
+ {
+ printf ("mkstemp failed: %m\n");
+ exit (1);
+ }
+ add_temp_file (fname);
+ if (ftruncate (fd, 1000) < 0)
+ {
+ printf ("ftruncate failed: %m\n");
+ exit (1);
+ }
+}
+
+
+static int
+do_test (void)
+{
+ struct
+ {
+ pthread_mutex_t m;
+ pthread_cond_t c;
+ int var;
+ } *p = mmap (NULL, sizeof (*p), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ if (p == MAP_FAILED)
+ {
+ printf ("initial mmap failed: %m\n");
+ return 1;
+ }
+
+ pthread_mutexattr_t ma;
+ if (pthread_mutexattr_init (&ma) != 0)
+ {
+ puts ("mutexattr_init failed");
+ return 1;
+ }
+ if (pthread_mutexattr_setpshared (&ma, 1) != 0)
+ {
+ puts ("mutexattr_setpshared failed");
+ return 1;
+ }
+ if (pthread_mutex_init (&p->m, &ma) != 0)
+ {
+ puts ("mutex_init failed");
+ return 1;
+ }
+ if (pthread_mutexattr_destroy (&ma) != 0)
+ {
+ puts ("mutexattr_destroy failed");
+ return 1;
+ }
+
+ pthread_condattr_t ca;
+ if (pthread_condattr_init (&ca) != 0)
+ {
+ puts ("condattr_init failed");
+ return 1;
+ }
+ if (pthread_condattr_setpshared (&ca, 1) != 0)
+ {
+ puts ("condattr_setpshared failed");
+ return 1;
+ }
+ if (pthread_cond_init (&p->c, &ca) != 0)
+ {
+ puts ("mutex_init failed");
+ return 1;
+ }
+ if (pthread_condattr_destroy (&ca) != 0)
+ {
+ puts ("condattr_destroy failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&p->m) != 0)
+ {
+ puts ("initial mutex_lock failed");
+ return 1;
+ }
+
+ p->var = 42;
+
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ printf ("fork failed: %m\n");
+ return 1;
+ }
+
+ if (pid == 0)
+ {
+ void *oldp = p;
+ p = mmap (NULL, sizeof (*p), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+
+ if (p == oldp)
+ {
+ puts ("child: mapped to same address");
+ kill (getppid (), SIGKILL);
+ exit (1);
+ }
+
+ munmap (oldp, sizeof (*p));
+
+ if (pthread_mutex_lock (&p->m) != 0)
+ {
+ puts ("child: mutex_lock failed");
+ kill (getppid (), SIGKILL);
+ exit (1);
+ }
+
+ p->var = 0;
+
+#ifndef USE_COND_SIGNAL
+ if (pthread_cond_broadcast (&p->c) != 0)
+ {
+ puts ("child: cond_broadcast failed");
+ kill (getppid (), SIGKILL);
+ exit (1);
+ }
+#else
+ if (pthread_cond_signal (&p->c) != 0)
+ {
+ puts ("child: cond_signal failed");
+ kill (getppid (), SIGKILL);
+ exit (1);
+ }
+#endif
+
+ if (pthread_mutex_unlock (&p->m) != 0)
+ {
+ puts ("child: mutex_unlock failed");
+ kill (getppid (), SIGKILL);
+ exit (1);
+ }
+
+ exit (0);
+ }
+
+ do
+ pthread_cond_wait (&p->c, &p->m);
+ while (p->var != 0);
+
+ if (TEMP_FAILURE_RETRY (waitpid (pid, NULL, 0)) != pid)
+ {
+ printf ("waitpid failed: %m\n");
+ kill (pid, SIGKILL);
+ return 1;
+ }
+
+ return 0;
+}
--- /dev/null
+++ b/fbtl/tst-cond13.c
@@ -0,0 +1,2 @@
+#define USE_COND_SIGNAL 1
+#include "tst-cond12.c"
--- /dev/null
+++ b/fbtl/tst-cond14.c
@@ -0,0 +1,117 @@
+/* Copyright (C) 2004-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+static pthread_mutex_t mut2 = PTHREAD_MUTEX_INITIALIZER;
+
+static void *
+tf (void *p)
+{
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ printf ("%s: 1st mutex_lock failed\n", __func__);
+ exit (1);
+ }
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ printf ("%s: 2nd mutex_lock failed\n", __func__);
+ exit (1);
+ }
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ printf ("%s: 3rd mutex_lock failed\n", __func__);
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&mut2) != 0)
+ {
+ printf ("%s: mutex_unlock failed\n", __func__);
+ exit (1);
+ }
+
+ if (pthread_cond_wait (&cond, &mut) != 0)
+ {
+ printf ("%s: cond_wait failed\n", __func__);
+ exit (1);
+ }
+
+ puts ("child: done");
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ if (pthread_mutex_lock (&mut2) != 0)
+ {
+ puts ("1st mutex_lock failed");
+ return 1;
+ }
+
+ puts ("parent: create child");
+
+ pthread_t th;
+ int err = pthread_create (&th, NULL, tf, NULL);
+ if (err != 0)
+ {
+ printf ("parent: cannot create thread: %s\n", strerror (err));
+ return 1;
+ }
+
+ /* We have to synchronize with the child. */
+ if (pthread_mutex_lock (&mut2) != 0)
+ {
+ puts ("2nd mutex_lock failed");
+ return 1;
+ }
+
+ /* Give the child to reach to pthread_cond_wait. */
+ sleep (1);
+
+ if (pthread_cond_signal (&cond) != 0)
+ {
+ puts ("cond_signal failed");
+ return 1;
+ }
+
+ err = pthread_join (th, NULL);
+ if (err != 0)
+ {
+ printf ("parent: failed to join: %s\n", strerror (err));
+ return 1;
+ }
+
+ puts ("done");
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 3
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cond15.c
@@ -0,0 +1,159 @@
+/* Copyright (C) 2004-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+static pthread_mutex_t mut2 = PTHREAD_MUTEX_INITIALIZER;
+
+static void *
+tf (void *p)
+{
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ printf ("%s: 1st mutex_lock failed\n", __func__);
+ exit (1);
+ }
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ printf ("%s: 2nd mutex_lock failed\n", __func__);
+ exit (1);
+ }
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ printf ("%s: 3rd mutex_lock failed\n", __func__);
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&mut2) != 0)
+ {
+ printf ("%s: mutex_unlock failed\n", __func__);
+ exit (1);
+ }
+
+ struct timeval tv;
+ gettimeofday (&tv, NULL);
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_sec += p == NULL ? 100 : 1;
+
+ int err = pthread_cond_timedwait (&cond, &mut, &ts);
+ if ((err != 0 && p == NULL) || (err != ETIMEDOUT && p != NULL))
+ {
+ printf ("%s: cond_wait failed\n", __func__);
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&mut) != 0)
+ {
+ printf ("%s: 1st mutex_unlock failed\n", __func__);
+ exit (1);
+ }
+ if (pthread_mutex_unlock (&mut) != 0)
+ {
+ printf ("%s: 2nd mutex_unlock failed\n", __func__);
+ exit (1);
+ }
+ if (pthread_mutex_unlock (&mut) != 0)
+ {
+ printf ("%s: 3rd mutex_unlock failed\n", __func__);
+ exit (1);
+ }
+
+ puts ("child: done");
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ if (pthread_mutex_lock (&mut2) != 0)
+ {
+ puts ("1st mutex_lock failed");
+ return 1;
+ }
+
+ puts ("parent: create 1st child");
+
+ pthread_t th;
+ int err = pthread_create (&th, NULL, tf, NULL);
+ if (err != 0)
+ {
+ printf ("parent: cannot 1st create thread: %s\n", strerror (err));
+ return 1;
+ }
+
+ /* We have to synchronize with the child. */
+ if (pthread_mutex_lock (&mut2) != 0)
+ {
+ puts ("2nd mutex_lock failed");
+ return 1;
+ }
+
+ /* Give the child to reach to pthread_cond_wait. */
+ sleep (1);
+
+ if (pthread_cond_signal (&cond) != 0)
+ {
+ puts ("cond_signal failed");
+ return 1;
+ }
+
+ err = pthread_join (th, NULL);
+ if (err != 0)
+ {
+ printf ("parent: failed to join: %s\n", strerror (err));
+ return 1;
+ }
+
+
+ puts ("parent: create 2nd child");
+
+ err = pthread_create (&th, NULL, tf, (void *) 1l);
+ if (err != 0)
+ {
+ printf ("parent: cannot 2nd create thread: %s\n", strerror (err));
+ return 1;
+ }
+
+ err = pthread_join (th, NULL);
+ if (err != 0)
+ {
+ printf ("parent: failed to join: %s\n", strerror (err));
+ return 1;
+ }
+
+ puts ("done");
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 6
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cond16.c
@@ -0,0 +1,110 @@
+/* Copyright (C) 2004-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
+pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+bool n, exiting;
+FILE *f;
+int count;
+
+void *
+tf (void *dummy)
+{
+ bool loop = true;
+
+ while (loop)
+ {
+ pthread_mutex_lock (&lock);
+ while (n && !exiting)
+ pthread_cond_wait (&cv, &lock);
+ n = true;
+ pthread_mutex_unlock (&lock);
+
+ fputs (".", f);
+
+ pthread_mutex_lock (&lock);
+ n = false;
+ if (exiting)
+ loop = false;
+#ifdef UNLOCK_AFTER_BROADCAST
+ pthread_cond_broadcast (&cv);
+ pthread_mutex_unlock (&lock);
+#else
+ pthread_mutex_unlock (&lock);
+ pthread_cond_broadcast (&cv);
+#endif
+ }
+
+ return NULL;
+}
+
+int
+do_test (void)
+{
+ f = fopen ("/dev/null", "w");
+ if (f == NULL)
+ {
+ printf ("couldn't open /dev/null, %m\n");
+ return 1;
+ }
+
+ count = sysconf (_SC_NPROCESSORS_ONLN);
+ if (count <= 0)
+ count = 1;
+ count *= 4;
+
+ pthread_t th[count];
+ pthread_attr_t attr;
+ int i, ret, sz;
+ pthread_attr_init (&attr);
+ sz = __getpagesize ();
+ if (sz < PTHREAD_STACK_MIN)
+ sz = PTHREAD_STACK_MIN;
+ pthread_attr_setstacksize (&attr, sz);
+ for (i = 0; i < count; ++i)
+ if ((ret = pthread_create (&th[i], &attr, tf, NULL)) != 0)
+ {
+ errno = ret;
+ printf ("pthread_create %d failed: %m\n", i);
+ return 1;
+ }
+
+ struct timespec ts = { .tv_sec = 20, .tv_nsec = 0 };
+ while (nanosleep (&ts, &ts) != 0);
+
+ pthread_mutex_lock (&lock);
+ exiting = true;
+ pthread_mutex_unlock (&lock);
+
+ for (i = 0; i < count; ++i)
+ pthread_join (th[i], NULL);
+
+ fclose (f);
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 40
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cond17.c
@@ -0,0 +1,2 @@
+#define UNLOCK_AFTER_BROADCAST 1
+#include "tst-cond16.c"
--- /dev/null
+++ b/fbtl/tst-cond18.c
@@ -0,0 +1,122 @@
+/* Copyright (C) 2004-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
+pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+bool exiting;
+int fd, count, spins, nn;
+
+void *
+tf (void *id)
+{
+ pthread_mutex_lock (&lock);
+
+ if ((long) id == 0)
+ {
+ while (!exiting)
+ {
+ if ((spins++ % 1000) == 0)
+ write (fd, ".", 1);
+ pthread_mutex_unlock (&lock);
+
+ pthread_mutex_lock (&lock);
+ int njobs = rand () % (count + 1);
+ nn = njobs;
+ if ((rand () % 30) == 0)
+ pthread_cond_broadcast (&cv);
+ else
+ while (njobs--)
+ pthread_cond_signal (&cv);
+ }
+
+ pthread_cond_broadcast (&cv);
+ }
+ else
+ {
+ while (!exiting)
+ {
+ while (!nn && !exiting)
+ pthread_cond_wait (&cv, &lock);
+ --nn;
+ pthread_mutex_unlock (&lock);
+
+ pthread_mutex_lock (&lock);
+ }
+ }
+
+ pthread_mutex_unlock (&lock);
+ return NULL;
+}
+
+int
+do_test (void)
+{
+ fd = open ("/dev/null", O_WRONLY);
+ if (fd < 0)
+ {
+ printf ("couldn't open /dev/null, %m\n");
+ return 1;
+ }
+
+ count = sysconf (_SC_NPROCESSORS_ONLN);
+ if (count <= 0)
+ count = 1;
+ count *= 8;
+
+ pthread_t th[count + 1];
+ pthread_attr_t attr;
+ int i, ret, sz;
+ pthread_attr_init (&attr);
+ sz = __getpagesize ();
+ if (sz < PTHREAD_STACK_MIN)
+ sz = PTHREAD_STACK_MIN;
+ pthread_attr_setstacksize (&attr, sz);
+
+ for (i = 0; i <= count; ++i)
+ if ((ret = pthread_create (&th[i], &attr, tf, (void *) (long) i)) != 0)
+ {
+ errno = ret;
+ printf ("pthread_create %d failed: %m\n", i);
+ return 1;
+ }
+
+ struct timespec ts = { .tv_sec = 20, .tv_nsec = 0 };
+ while (nanosleep (&ts, &ts) != 0);
+
+ pthread_mutex_lock (&lock);
+ exiting = true;
+ pthread_mutex_unlock (&lock);
+
+ for (i = 0; i < count; ++i)
+ pthread_join (th[i], NULL);
+
+ close (fd);
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 40
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cond19.c
@@ -0,0 +1,75 @@
+/* Copyright (C) 2004-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+
+
+static int
+do_test (void)
+{
+ int result = 0;
+ struct timespec ts;
+
+ if (clock_gettime (CLOCK_REALTIME, &ts) != 0)
+ {
+ puts ("clock_gettime failed");
+ return 1;
+ }
+
+ ts.tv_nsec = -1;
+
+ int e = pthread_cond_timedwait (&cond, &mut, &ts);
+ if (e == 0)
+ {
+ puts ("first cond_timedwait did not fail");
+ result = 1;
+ }
+ else if (e != EINVAL)
+ {
+ puts ("first cond_timedwait did not return EINVAL");
+ result = 1;
+ }
+
+ ts.tv_nsec = 2000000000;
+
+ e = pthread_cond_timedwait (&cond, &mut, &ts);
+ if (e == 0)
+ {
+ puts ("second cond_timedwait did not fail");
+ result = 1;
+ }
+ else if (e != EINVAL)
+ {
+ puts ("second cond_timedwait did not return EINVAL");
+ result = 1;
+ }
+
+ return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cond2.c
@@ -0,0 +1,162 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <error.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+
+static pthread_barrier_t bar;
+
+
+static void *
+tf (void *a)
+{
+ int i = (long int) a;
+ int err;
+
+ printf ("child %d: lock\n", i);
+
+ err = pthread_mutex_lock (&mut);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "locking in child failed");
+
+ printf ("child %d: sync\n", i);
+
+ int e = pthread_barrier_wait (&bar);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child: barrier_wait failed");
+ exit (1);
+ }
+
+ printf ("child %d: wait\n", i);
+
+ err = pthread_cond_wait (&cond, &mut);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "child %d: failed to wait", i);
+
+ printf ("child %d: woken up\n", i);
+
+ err = pthread_mutex_unlock (&mut);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "child %d: unlock[2] failed", i);
+
+ printf ("child %d: done\n", i);
+
+ return NULL;
+}
+
+
+#define N 10
+
+
+static int
+do_test (void)
+{
+ pthread_t th[N];
+ int i;
+ int err;
+
+ printf ("&cond = %p\n&mut = %p\n", &cond, &mut);
+
+ if (pthread_barrier_init (&bar, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ pthread_attr_t at;
+
+ if (pthread_attr_init (&at) != 0)
+ {
+ puts ("attr_init failed");
+ return 1;
+ }
+
+ if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+ for (i = 0; i < N; ++i)
+ {
+ printf ("create thread %d\n", i);
+
+ err = pthread_create (&th[i], &at, tf, (void *) (long int) i);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "cannot create thread %d", i);
+
+ printf ("wait for child %d\n", i);
+
+ /* Wait for the child to start up and get the mutex for the
+ conditional variable. */
+ int e = pthread_barrier_wait (&bar);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+ }
+
+ if (pthread_attr_destroy (&at) != 0)
+ {
+ puts ("attr_destroy failed");
+ return 1;
+ }
+
+ puts ("get lock outselves");
+
+ err = pthread_mutex_lock (&mut);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "mut locking failed");
+
+ puts ("broadcast");
+
+ /* Wake up all threads. */
+ err = pthread_cond_broadcast (&cond);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "parent: broadcast failed");
+
+ err = pthread_mutex_unlock (&mut);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "mut unlocking failed");
+
+ /* Join all threads. */
+ for (i = 0; i < N; ++i)
+ {
+ printf ("join thread %d\n", i);
+
+ err = pthread_join (th[i], NULL);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "join of child %d failed", i);
+ }
+
+ puts ("done");
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cond20.c
@@ -0,0 +1,169 @@
+/* Copyright (C) 2004-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define N 10
+#define ROUNDS 1000
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+static pthread_barrier_t b;
+static int count;
+
+static void *
+tf (void *p)
+{
+ int i;
+ for (i = 0; i < ROUNDS; ++i)
+ {
+ pthread_mutex_lock (&mut);
+
+ if (++count == N)
+ pthread_cond_signal (&cond2);
+
+#ifdef TIMED
+ struct timeval tv;
+ gettimeofday (&tv, NULL);
+ struct timespec ts;
+ /* Wait three seconds. */
+ ts.tv_sec = tv.tv_sec + 3;
+ ts.tv_nsec = tv.tv_usec * 1000;
+ pthread_cond_timedwait (&cond, &mut, &ts);
+#else
+ pthread_cond_wait (&cond, &mut);
+#endif
+
+ pthread_mutex_unlock (&mut);
+
+ int err = pthread_barrier_wait (&b);
+ if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child: barrier_wait failed");
+ exit (1);
+ }
+
+ err = pthread_barrier_wait (&b);
+ if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child: barrier_wait failed");
+ exit (1);
+ }
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ if (pthread_barrier_init (&b, NULL, N + 1) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ pthread_mutex_lock (&mut);
+
+ int i, j, err;
+ pthread_t th[N];
+ for (i = 0; i < N; ++i)
+ if ((err = pthread_create (&th[i], NULL, tf, NULL)) != 0)
+ {
+ printf ("cannot create thread %d: %s\n", i, strerror (err));
+ return 1;
+ }
+
+ for (i = 0; i < ROUNDS; ++i)
+ {
+ pthread_cond_wait (&cond2, &mut);
+
+ if (i & 1)
+ pthread_mutex_unlock (&mut);
+
+ if (i & 2)
+ pthread_cond_broadcast (&cond);
+ else if (i & 4)
+ for (j = 0; j < N; ++j)
+ pthread_cond_signal (&cond);
+ else
+ {
+ for (j = 0; j < (i / 8) % N; ++j)
+ pthread_cond_signal (&cond);
+ pthread_cond_broadcast (&cond);
+ }
+
+ if ((i & 1) == 0)
+ pthread_mutex_unlock (&mut);
+
+ err = pthread_cond_destroy (&cond);
+ if (err)
+ {
+ printf ("pthread_cond_destroy failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ /* Now clobber the cond variable which has been successfully
+ destroyed above. */
+ memset (&cond, (char) i, sizeof (cond));
+
+ err = pthread_barrier_wait (&b);
+ if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("parent: barrier_wait failed");
+ return 1;
+ }
+
+ pthread_mutex_lock (&mut);
+
+ err = pthread_barrier_wait (&b);
+ if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("parent: barrier_wait failed");
+ return 1;
+ }
+
+ count = 0;
+ err = pthread_cond_init (&cond, NULL);
+ if (err)
+ {
+ printf ("pthread_cond_init failed: %s\n", strerror (err));
+ return 1;
+ }
+ }
+
+ for (i = 0; i < N; ++i)
+ if ((err = pthread_join (th[i], NULL)) != 0)
+ {
+ printf ("failed to join thread %d: %s\n", i, strerror (err));
+ return 1;
+ }
+
+ puts ("done");
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cond21.c
@@ -0,0 +1,3 @@
+#include <sys/time.h>
+#define TIMED 1
+#include "tst-cond20.c"
--- /dev/null
+++ b/fbtl/tst-cond22.c
@@ -0,0 +1,160 @@
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_barrier_t b;
+static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void
+cl (void *arg)
+{
+ pthread_mutex_unlock (&m);
+}
+
+
+static void *
+tf (void *arg)
+{
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ printf ("%s: mutex_lock failed\n", __func__);
+ exit (1);
+ }
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __func__);
+ exit (1);
+ }
+ pthread_cleanup_push (cl, NULL);
+ /* We have to loop here because the cancellation might come after
+ the cond_wait call left the cancelable area and is then waiting
+ on the mutex. In this case the beginning of the second cond_wait
+ call will cause the cancellation to happen. */
+ do
+ if (pthread_cond_wait (&c, &m) != 0)
+ {
+ printf ("%s: cond_wait failed\n", __func__);
+ exit (1);
+ }
+ while (arg == NULL);
+ pthread_cleanup_pop (0);
+ if (pthread_mutex_unlock (&m) != 0)
+ {
+ printf ("%s: mutex_unlock failed\n", __func__);
+ exit (1);
+ }
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ int status = 0;
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("1st create failed");
+ return 1;
+ }
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("1st barrier_wait failed");
+ return 1;
+ }
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("1st mutex_lock failed");
+ return 1;
+ }
+ if (pthread_cond_signal (&c) != 0)
+ {
+ puts ("1st cond_signal failed");
+ return 1;
+ }
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cancel failed");
+ return 1;
+ }
+ if (pthread_mutex_unlock (&m) != 0)
+ {
+ puts ("1st mutex_unlock failed");
+ return 1;
+ }
+ void *res;
+ if (pthread_join (th, &res) != 0)
+ {
+ puts ("1st join failed");
+ return 1;
+ }
+ if (res != PTHREAD_CANCELED)
+ {
+ puts ("first thread not canceled");
+ status = 1;
+ }
+
+ printf ("cond = { %d, %x, %lld, %lld, %lld, %p, %u, %u }\n",
+ c.__data.__lock, c.__data.__futex, c.__data.__total_seq,
+ c.__data.__wakeup_seq, c.__data.__woken_seq, c.__data.__mutex,
+ c.__data.__nwaiters, c.__data.__broadcast_seq);
+
+ if (pthread_create (&th, NULL, tf, (void *) 1l) != 0)
+ {
+ puts ("2nd create failed");
+ return 1;
+ }
+ e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("2nd barrier_wait failed");
+ return 1;
+ }
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("2nd mutex_lock failed");
+ return 1;
+ }
+ if (pthread_cond_signal (&c) != 0)
+ {
+ puts ("2nd cond_signal failed");
+ return 1;
+ }
+ if (pthread_mutex_unlock (&m) != 0)
+ {
+ puts ("2nd mutex_unlock failed");
+ return 1;
+ }
+ if (pthread_join (th, &res) != 0)
+ {
+ puts ("2nd join failed");
+ return 1;
+ }
+ if (res != NULL)
+ {
+ puts ("2nd thread canceled");
+ status = 1;
+ }
+
+ printf ("cond = { %d, %x, %lld, %lld, %lld, %p, %u, %u }\n",
+ c.__data.__lock, c.__data.__futex, c.__data.__total_seq,
+ c.__data.__wakeup_seq, c.__data.__woken_seq, c.__data.__mutex,
+ c.__data.__nwaiters, c.__data.__broadcast_seq);
+
+ return status;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cond23.c
@@ -0,0 +1,183 @@
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@redhat.com>, 2008.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+
+
+#if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0
+static int
+check (pthread_condattr_t *condattr, int pshared, clockid_t cl)
+{
+ clockid_t cl2;
+ if (pthread_condattr_getclock (condattr, &cl2) != 0)
+ {
+ puts ("condattr_getclock failed");
+ return 1;
+ }
+ if (cl != cl2)
+ {
+ printf ("condattr_getclock returned wrong value: %d, expected %d\n",
+ (int) cl2, (int) cl);
+ return 1;
+ }
+
+ int p;
+ if (pthread_condattr_getpshared (condattr, &p) != 0)
+ {
+ puts ("condattr_getpshared failed");
+ return 1;
+ }
+ else if (p != pshared)
+ {
+ printf ("condattr_getpshared returned wrong value: %d, expected %d\n",
+ p, pshared);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+run_test (clockid_t cl)
+{
+ pthread_condattr_t condattr;
+
+ printf ("clock = %d\n", (int) cl);
+
+ if (pthread_condattr_init (&condattr) != 0)
+ {
+ puts ("condattr_init failed");
+ return 1;
+ }
+
+ if (check (&condattr, PTHREAD_PROCESS_PRIVATE, CLOCK_REALTIME))
+ return 1;
+
+ if (pthread_condattr_setpshared (&condattr, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("1st condattr_setpshared failed");
+ return 1;
+ }
+
+ if (check (&condattr, PTHREAD_PROCESS_SHARED, CLOCK_REALTIME))
+ return 1;
+
+ if (pthread_condattr_setclock (&condattr, cl) != 0)
+ {
+ puts ("1st condattr_setclock failed");
+ return 1;
+ }
+
+ if (check (&condattr, PTHREAD_PROCESS_SHARED, cl))
+ return 1;
+
+ if (pthread_condattr_setpshared (&condattr, PTHREAD_PROCESS_PRIVATE) != 0)
+ {
+ puts ("2nd condattr_setpshared failed");
+ return 1;
+ }
+
+ if (check (&condattr, PTHREAD_PROCESS_PRIVATE, cl))
+ return 1;
+
+ if (pthread_condattr_setclock (&condattr, CLOCK_REALTIME) != 0)
+ {
+ puts ("2nd condattr_setclock failed");
+ return 1;
+ }
+
+ if (check (&condattr, PTHREAD_PROCESS_PRIVATE, CLOCK_REALTIME))
+ return 1;
+
+ if (pthread_condattr_setclock (&condattr, cl) != 0)
+ {
+ puts ("3rd condattr_setclock failed");
+ return 1;
+ }
+
+ if (check (&condattr, PTHREAD_PROCESS_PRIVATE, cl))
+ return 1;
+
+ if (pthread_condattr_setpshared (&condattr, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("3rd condattr_setpshared failed");
+ return 1;
+ }
+
+ if (check (&condattr, PTHREAD_PROCESS_SHARED, cl))
+ return 1;
+
+ if (pthread_condattr_setclock (&condattr, CLOCK_REALTIME) != 0)
+ {
+ puts ("4th condattr_setclock failed");
+ return 1;
+ }
+
+ if (check (&condattr, PTHREAD_PROCESS_SHARED, CLOCK_REALTIME))
+ return 1;
+
+ if (pthread_condattr_destroy (&condattr) != 0)
+ {
+ puts ("condattr_destroy failed");
+ return 1;
+ }
+
+ return 0;
+}
+#endif
+
+
+static int
+do_test (void)
+{
+#if !defined _POSIX_CLOCK_SELECTION || _POSIX_CLOCK_SELECTION == -1
+
+ puts ("_POSIX_CLOCK_SELECTION not supported, test skipped");
+ return 0;
+
+#else
+
+ int res = run_test (CLOCK_REALTIME);
+
+# if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
+# if _POSIX_MONOTONIC_CLOCK == 0
+ int e = sysconf (_SC_MONOTONIC_CLOCK);
+ if (e < 0)
+ puts ("CLOCK_MONOTONIC not supported");
+ else if (e == 0)
+ {
+ puts ("sysconf (_SC_MONOTONIC_CLOCK) must not return 0");
+ res = 1;
+ }
+ else
+# endif
+ res |= run_test (CLOCK_MONOTONIC);
+# else
+ puts ("_POSIX_MONOTONIC_CLOCK not defined");
+# endif
+
+ return res;
+#endif
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cond24.c
@@ -0,0 +1,249 @@
+/* Verify that condition variables synchronized by PI mutexes don't hang.
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define THREADS_NUM 5
+#define MAXITER 50000
+
+static pthread_mutex_t mutex;
+static pthread_mutexattr_t mutex_attr;
+static pthread_cond_t cond;
+static pthread_t threads[THREADS_NUM];
+static int pending = 0;
+
+typedef void * (*threadfunc) (void *);
+
+void *
+thread_fun_timed (void *arg)
+{
+ int *ret = arg;
+ int rv, i;
+
+ printf ("Started thread_fun_timed[%d]\n", *ret);
+
+ for (i = 0; i < MAXITER / THREADS_NUM; i++)
+ {
+ rv = pthread_mutex_lock (&mutex);
+ if (rv)
+ {
+ printf ("pthread_mutex_lock: %s(%d)\n", strerror (rv), rv);
+ *ret = 1;
+ goto out;
+ }
+
+ while (!pending)
+ {
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ ts.tv_sec += 20;
+ rv = pthread_cond_timedwait (&cond, &mutex, &ts);
+
+ /* There should be no timeout either. */
+ if (rv)
+ {
+ printf ("pthread_cond_wait: %s(%d)\n", strerror (rv), rv);
+ *ret = 1;
+ goto out;
+ }
+ }
+
+ pending--;
+
+ rv = pthread_mutex_unlock (&mutex);
+ if (rv)
+ {
+ printf ("pthread_mutex_unlock: %s(%d)\n", strerror (rv), rv);
+ *ret = 1;
+ goto out;
+ }
+ }
+
+ *ret = 0;
+
+out:
+ return ret;
+}
+
+void *
+thread_fun (void *arg)
+{
+ int *ret = arg;
+ int rv, i;
+
+ printf ("Started thread_fun[%d]\n", *ret);
+
+ for (i = 0; i < MAXITER / THREADS_NUM; i++)
+ {
+ rv = pthread_mutex_lock (&mutex);
+ if (rv)
+ {
+ printf ("pthread_mutex_lock: %s(%d)\n", strerror (rv), rv);
+ *ret = 1;
+ goto out;
+ }
+
+ while (!pending)
+ {
+ rv = pthread_cond_wait (&cond, &mutex);
+
+ if (rv)
+ {
+ printf ("pthread_cond_wait: %s(%d)\n", strerror (rv), rv);
+ *ret = 1;
+ goto out;
+ }
+ }
+
+ pending--;
+
+ rv = pthread_mutex_unlock (&mutex);
+ if (rv)
+ {
+ printf ("pthread_mutex_unlock: %s(%d)\n", strerror (rv), rv);
+ *ret = 1;
+ goto out;
+ }
+ }
+
+ *ret = 0;
+
+out:
+ return ret;
+}
+
+static int
+do_test_wait (threadfunc f)
+{
+ int i;
+ int rv;
+ int counter = 0;
+ int retval[THREADS_NUM];
+
+ puts ("Starting test");
+
+ rv = pthread_mutexattr_init (&mutex_attr);
+ if (rv)
+ {
+ printf ("pthread_mutexattr_init: %s(%d)\n", strerror (rv), rv);
+ return 1;
+ }
+
+ rv = pthread_mutexattr_setprotocol (&mutex_attr, PTHREAD_PRIO_INHERIT);
+ if (rv)
+ {
+ printf ("pthread_mutexattr_setprotocol: %s(%d)\n", strerror (rv), rv);
+ return 1;
+ }
+
+ rv = pthread_mutex_init (&mutex, &mutex_attr);
+ if (rv)
+ {
+ printf ("pthread_mutex_init: %s(%d)\n", strerror (rv), rv);
+ return 1;
+ }
+
+ rv = pthread_cond_init (&cond, NULL);
+ if (rv)
+ {
+ printf ("pthread_cond_init: %s(%d)\n", strerror (rv), rv);
+ return 1;
+ }
+
+ for (i = 0; i < THREADS_NUM; i++)
+ {
+ retval[i] = i;
+ rv = pthread_create (&threads[i], NULL, f, &retval[i]);
+ if (rv)
+ {
+ printf ("pthread_create: %s(%d)\n", strerror (rv), rv);
+ return 1;
+ }
+ }
+
+ for (; counter < MAXITER; counter++)
+ {
+ rv = pthread_mutex_lock (&mutex);
+ if (rv)
+ {
+ printf ("pthread_mutex_lock: %s(%d)\n", strerror (rv), rv);
+ return 1;
+ }
+
+ if (!(counter % 100))
+ printf ("counter: %d\n", counter);
+ pending += 1;
+
+ rv = pthread_cond_signal (&cond);
+ if (rv)
+ {
+ printf ("pthread_cond_signal: %s(%d)\n", strerror (rv), rv);
+ return 1;
+ }
+
+ rv = pthread_mutex_unlock (&mutex);
+ if (rv)
+ {
+ printf ("pthread_mutex_unlock: %s(%d)\n", strerror (rv), rv);
+ return 1;
+ }
+ }
+
+ for (i = 0; i < THREADS_NUM; i++)
+ {
+ void *ret;
+ rv = pthread_join (threads[i], &ret);
+ if (rv)
+ {
+ printf ("pthread_join: %s(%d)\n", strerror (rv), rv);
+ return 1;
+ }
+ if (ret && *(int *)ret)
+ {
+ printf ("Thread %d returned with an error\n", i);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+do_test (void)
+{
+ puts ("Testing pthread_cond_wait");
+ int ret = do_test_wait (thread_fun);
+ if (ret)
+ return ret;
+
+ puts ("Testing pthread_cond_timedwait");
+ return do_test_wait (thread_fun_timed);
+}
+
+#define TIMEOUT 20
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cond25.c
@@ -0,0 +1,281 @@
+/* Verify that condition variables synchronized by PI mutexes don't hang on
+ on cancellation.
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define NUM 5
+#define ITERS 10000
+#define COUNT 100
+
+typedef void *(*thr_func) (void *);
+
+pthread_mutex_t mutex;
+pthread_cond_t cond;
+
+void cleanup (void *u)
+{
+ /* pthread_cond_wait should always return with the mutex locked. */
+ if (pthread_mutex_unlock (&mutex))
+ abort ();
+}
+
+void *
+signaller (void *u)
+{
+ int i, ret = 0;
+ void *tret = NULL;
+
+ for (i = 0; i < ITERS; i++)
+ {
+ if ((ret = pthread_mutex_lock (&mutex)) != 0)
+ {
+ tret = (void *)1;
+ printf ("signaller:mutex_lock failed: %s\n", strerror (ret));
+ goto out;
+ }
+ if ((ret = pthread_cond_signal (&cond)) != 0)
+ {
+ tret = (void *)1;
+ printf ("signaller:signal failed: %s\n", strerror (ret));
+ goto unlock_out;
+ }
+ if ((ret = pthread_mutex_unlock (&mutex)) != 0)
+ {
+ tret = (void *)1;
+ printf ("signaller:mutex_unlock failed: %s\n", strerror (ret));
+ goto out;
+ }
+ pthread_testcancel ();
+ }
+
+out:
+ return tret;
+
+unlock_out:
+ if ((ret = pthread_mutex_unlock (&mutex)) != 0)
+ printf ("signaller:mutex_unlock[2] failed: %s\n", strerror (ret));
+ goto out;
+}
+
+void *
+waiter (void *u)
+{
+ int i, ret = 0;
+ void *tret = NULL;
+ int seq = (uintptr_t) u;
+
+ for (i = 0; i < ITERS / NUM; i++)
+ {
+ if ((ret = pthread_mutex_lock (&mutex)) != 0)
+ {
+ tret = (void *) (uintptr_t) 1;
+ printf ("waiter[%u]:mutex_lock failed: %s\n", seq, strerror (ret));
+ goto out;
+ }
+ pthread_cleanup_push (cleanup, NULL);
+
+ if ((ret = pthread_cond_wait (&cond, &mutex)) != 0)
+ {
+ tret = (void *) (uintptr_t) 1;
+ printf ("waiter[%u]:wait failed: %s\n", seq, strerror (ret));
+ goto unlock_out;
+ }
+
+ if ((ret = pthread_mutex_unlock (&mutex)) != 0)
+ {
+ tret = (void *) (uintptr_t) 1;
+ printf ("waiter[%u]:mutex_unlock failed: %s\n", seq, strerror (ret));
+ goto out;
+ }
+ pthread_cleanup_pop (0);
+ }
+
+out:
+ puts ("waiter tests done");
+ return tret;
+
+unlock_out:
+ if ((ret = pthread_mutex_unlock (&mutex)) != 0)
+ printf ("waiter:mutex_unlock[2] failed: %s\n", strerror (ret));
+ goto out;
+}
+
+void *
+timed_waiter (void *u)
+{
+ int i, ret;
+ void *tret = NULL;
+ int seq = (uintptr_t) u;
+
+ for (i = 0; i < ITERS / NUM; i++)
+ {
+ struct timespec ts;
+
+ if ((ret = clock_gettime(CLOCK_REALTIME, &ts)) != 0)
+ {
+ tret = (void *) (uintptr_t) 1;
+ printf ("%u:clock_gettime failed: %s\n", seq, strerror (errno));
+ goto out;
+ }
+ ts.tv_sec += 20;
+
+ if ((ret = pthread_mutex_lock (&mutex)) != 0)
+ {
+ tret = (void *) (uintptr_t) 1;
+ printf ("waiter[%u]:mutex_lock failed: %s\n", seq, strerror (ret));
+ goto out;
+ }
+ pthread_cleanup_push (cleanup, NULL);
+
+ /* We should not time out either. */
+ if ((ret = pthread_cond_timedwait (&cond, &mutex, &ts)) != 0)
+ {
+ tret = (void *) (uintptr_t) 1;
+ printf ("waiter[%u]:timedwait failed: %s\n", seq, strerror (ret));
+ goto unlock_out;
+ }
+ if ((ret = pthread_mutex_unlock (&mutex)) != 0)
+ {
+ tret = (void *) (uintptr_t) 1;
+ printf ("waiter[%u]:mutex_unlock failed: %s\n", seq, strerror (ret));
+ goto out;
+ }
+ pthread_cleanup_pop (0);
+ }
+
+out:
+ puts ("timed_waiter tests done");
+ return tret;
+
+unlock_out:
+ if ((ret = pthread_mutex_unlock (&mutex)) != 0)
+ printf ("waiter[%u]:mutex_unlock[2] failed: %s\n", seq, strerror (ret));
+ goto out;
+}
+
+int
+do_test_wait (thr_func f)
+{
+ pthread_t w[NUM];
+ pthread_t s;
+ pthread_mutexattr_t attr;
+ int i, j, ret = 0;
+ void *thr_ret;
+
+ for (i = 0; i < COUNT; i++)
+ {
+ if ((ret = pthread_mutexattr_init (&attr)) != 0)
+ {
+ printf ("mutexattr_init failed: %s\n", strerror (ret));
+ goto out;
+ }
+
+ if ((ret = pthread_mutexattr_setprotocol (&attr,
+ PTHREAD_PRIO_INHERIT)) != 0)
+ {
+ printf ("mutexattr_setprotocol failed: %s\n", strerror (ret));
+ goto out;
+ }
+
+ if ((ret = pthread_cond_init (&cond, NULL)) != 0)
+ {
+ printf ("cond_init failed: %s\n", strerror (ret));
+ goto out;
+ }
+
+ if ((ret = pthread_mutex_init (&mutex, &attr)) != 0)
+ {
+ printf ("mutex_init failed: %s\n", strerror (ret));
+ goto out;
+ }
+
+ for (j = 0; j < NUM; j++)
+ if ((ret = pthread_create (&w[j], NULL,
+ f, (void *) (uintptr_t) j)) != 0)
+ {
+ printf ("waiter[%d]: create failed: %s\n", j, strerror (ret));
+ goto out;
+ }
+
+ if ((ret = pthread_create (&s, NULL, signaller, NULL)) != 0)
+ {
+ printf ("signaller: create failed: %s\n", strerror (ret));
+ goto out;
+ }
+
+ for (j = 0; j < NUM; j++)
+ {
+ pthread_cancel (w[j]);
+
+ if ((ret = pthread_join (w[j], &thr_ret)) != 0)
+ {
+ printf ("waiter[%d]: join failed: %s\n", j, strerror (ret));
+ goto out;
+ }
+
+ if (thr_ret != NULL && thr_ret != PTHREAD_CANCELED)
+ {
+ ret = 1;
+ goto out;
+ }
+ }
+
+ /* The signalling thread could have ended before it was cancelled. */
+ pthread_cancel (s);
+
+ if ((ret = pthread_join (s, &thr_ret)) != 0)
+ {
+ printf ("signaller: join failed: %s\n", strerror (ret));
+ goto out;
+ }
+
+ if (thr_ret != NULL && thr_ret != PTHREAD_CANCELED)
+ {
+ ret = 1;
+ goto out;
+ }
+ }
+
+out:
+ return ret;
+}
+
+int
+do_test (int argc, char **argv)
+{
+ int ret = do_test_wait (waiter);
+
+ if (ret)
+ return ret;
+
+ return do_test_wait (timed_waiter);
+}
+
+#define TIMEOUT 5
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cond3.c
@@ -0,0 +1,111 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+/* Note that this test requires more than the standard. It is
+ required that there are no spurious wakeups if only more readers
+ are added. This is a reasonable demand. */
+
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+
+
+#define N 10
+
+
+static void *
+tf (void *arg)
+{
+ int i = (long int) arg;
+ int err;
+
+ /* Get the mutex. */
+ err = pthread_mutex_lock (&mut);
+ if (err != 0)
+ {
+ printf ("child %d mutex_lock failed: %s\n", i, strerror (err));
+ exit (1);
+ }
+
+ /* This call should never return. */
+ xpthread_cond_wait (&cond, &mut);
+ puts ("error: pthread_cond_wait in tf returned");
+
+ /* We should never get here. */
+ exit (1);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ int err;
+ int i;
+
+ for (i = 0; i < N; ++i)
+ {
+ pthread_t th;
+
+ if (i != 0)
+ {
+ /* Release the mutex. */
+ err = pthread_mutex_unlock (&mut);
+ if (err != 0)
+ {
+ printf ("mutex_unlock %d failed: %s\n", i, strerror (err));
+ return 1;
+ }
+ }
+
+ err = pthread_create (&th, NULL, tf, (void *) (long int) i);
+ if (err != 0)
+ {
+ printf ("create %d failed: %s\n", i, strerror (err));
+ return 1;
+ }
+
+ /* Get the mutex. */
+ err = pthread_mutex_lock (&mut);
+ if (err != 0)
+ {
+ printf ("mutex_lock %d failed: %s\n", i, strerror (err));
+ return 1;
+ }
+ }
+
+ delayed_exit (1);
+
+ /* This call should never return. */
+ xpthread_cond_wait (&cond, &mut);
+
+ puts ("error: pthread_cond_wait in do_test returned");
+ return 1;
+}
--- /dev/null
+++ b/fbtl/tst-cond4.c
@@ -0,0 +1,262 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+
+int *condition;
+
+static int
+do_test (void)
+{
+ size_t ps = sysconf (_SC_PAGESIZE);
+ char tmpfname[] = "/tmp/tst-cond4.XXXXXX";
+ char data[ps];
+ void *mem;
+ int fd;
+ pthread_mutexattr_t ma;
+ pthread_mutex_t *mut1;
+ pthread_mutex_t *mut2;
+ pthread_condattr_t ca;
+ pthread_cond_t *cond;
+ pid_t pid;
+ int result = 0;
+ int p;
+
+ fd = mkstemp (tmpfname);
+ if (fd == -1)
+ {
+ printf ("cannot open temporary file: %m\n");
+ return 1;
+ }
+
+ /* Make sure it is always removed. */
+ unlink (tmpfname);
+
+ /* Create one page of data. */
+ memset (data, '\0', ps);
+
+ /* Write the data to the file. */
+ if (write (fd, data, ps) != (ssize_t) ps)
+ {
+ puts ("short write");
+ return 1;
+ }
+
+ mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (mem == MAP_FAILED)
+ {
+ printf ("mmap failed: %m\n");
+ return 1;
+ }
+
+ mut1 = (pthread_mutex_t *) (((uintptr_t) mem
+ + __alignof (pthread_mutex_t))
+ & ~(__alignof (pthread_mutex_t) - 1));
+ mut2 = mut1 + 1;
+
+ cond = (pthread_cond_t *) (((uintptr_t) (mut2 + 1)
+ + __alignof (pthread_cond_t))
+ & ~(__alignof (pthread_cond_t) - 1));
+
+ condition = (int *) (((uintptr_t) (cond + 1) + __alignof (int))
+ & ~(__alignof (int) - 1));
+
+ if (pthread_mutexattr_init (&ma) != 0)
+ {
+ puts ("mutexattr_init failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_getpshared (&ma, &p) != 0)
+ {
+ puts ("1st mutexattr_getpshared failed");
+ return 1;
+ }
+
+ if (p != PTHREAD_PROCESS_PRIVATE)
+ {
+ puts ("default pshared value wrong");
+ return 1;
+ }
+
+ if (pthread_mutexattr_setpshared (&ma, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("mutexattr_setpshared failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_getpshared (&ma, &p) != 0)
+ {
+ puts ("2nd mutexattr_getpshared failed");
+ return 1;
+ }
+
+ if (p != PTHREAD_PROCESS_SHARED)
+ {
+ puts ("pshared value after setpshared call wrong");
+ return 1;
+ }
+
+ if (pthread_mutex_init (mut1, &ma) != 0)
+ {
+ puts ("1st mutex_init failed");
+ return 1;
+ }
+
+ if (pthread_mutex_init (mut2, &ma) != 0)
+ {
+ puts ("2nd mutex_init failed");
+ return 1;
+ }
+
+ if (pthread_condattr_init (&ca) != 0)
+ {
+ puts ("condattr_init failed");
+ return 1;
+ }
+
+ if (pthread_condattr_getpshared (&ca, &p) != 0)
+ {
+ puts ("1st condattr_getpshared failed");
+ return 1;
+ }
+
+ if (p != PTHREAD_PROCESS_PRIVATE)
+ {
+ puts ("default value for pshared in condattr wrong");
+ return 1;
+ }
+
+ if (pthread_condattr_setpshared (&ca, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("condattr_setpshared failed");
+ return 1;
+ }
+
+ if (pthread_condattr_getpshared (&ca, &p) != 0)
+ {
+ puts ("2nd condattr_getpshared failed");
+ return 1;
+ }
+
+ if (p != PTHREAD_PROCESS_SHARED)
+ {
+ puts ("pshared condattr still not set");
+ return 1;
+ }
+
+ if (pthread_cond_init (cond, &ca) != 0)
+ {
+ puts ("cond_init failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (mut1) != 0)
+ {
+ puts ("parent: 1st mutex_lock failed");
+ return 1;
+ }
+
+ puts ("going to fork now");
+ pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ return 1;
+ }
+ else if (pid == 0)
+ {
+ if (pthread_mutex_lock (mut2) != 0)
+ {
+ puts ("child: mutex_lock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_unlock (mut1) != 0)
+ {
+ puts ("child: 1st mutex_unlock failed");
+ return 1;
+ }
+
+ do
+ if (pthread_cond_wait (cond, mut2) != 0)
+ {
+ puts ("child: cond_wait failed");
+ return 1;
+ }
+ while (*condition == 0);
+
+ if (pthread_mutex_unlock (mut2) != 0)
+ {
+ puts ("child: 2nd mutex_unlock failed");
+ return 1;
+ }
+
+ puts ("child done");
+ }
+ else
+ {
+ int status;
+
+ if (pthread_mutex_lock (mut1) != 0)
+ {
+ puts ("parent: 2nd mutex_lock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (mut2) != 0)
+ {
+ puts ("parent: 3rd mutex_lock failed");
+ return 1;
+ }
+
+ if (pthread_cond_signal (cond) != 0)
+ {
+ puts ("parent: cond_signal failed");
+ return 1;
+ }
+
+ *condition = 1;
+
+ if (pthread_mutex_unlock (mut2) != 0)
+ {
+ puts ("parent: mutex_unlock failed");
+ return 1;
+ }
+
+ puts ("waiting for child");
+
+ waitpid (pid, &status, 0);
+ result |= status;
+
+ puts ("parent done");
+ }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cond5.c
@@ -0,0 +1,105 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/time.h>
+
+
+static pthread_mutex_t mut;
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+
+
+static int
+do_test (void)
+{
+ pthread_mutexattr_t ma;
+ int err;
+ struct timespec ts;
+ struct timeval tv;
+
+ if (pthread_mutexattr_init (&ma) != 0)
+ {
+ puts ("mutexattr_init failed");
+ exit (1);
+ }
+
+ if (pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_ERRORCHECK) != 0)
+ {
+ puts ("mutexattr_settype failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_init (&mut, &ma) != 0)
+ {
+ puts ("mutex_init failed");
+ exit (1);
+ }
+
+ /* Get the mutex. */
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ puts ("mutex_lock failed");
+ exit (1);
+ }
+
+ /* Waiting for the condition will fail. But we want the timeout here. */
+ if (gettimeofday (&tv, NULL) != 0)
+ {
+ puts ("gettimeofday failed");
+ exit (1);
+ }
+
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_nsec += 500000000;
+ if (ts.tv_nsec >= 1000000000)
+ {
+ ts.tv_nsec -= 1000000000;
+ ++ts.tv_sec;
+ }
+ err = pthread_cond_timedwait (&cond, &mut, &ts);
+ if (err == 0)
+ {
+ /* This could in theory happen but here without any signal and
+ additional waiter it should not. */
+ puts ("cond_timedwait succeeded");
+ exit (1);
+ }
+ else if (err != ETIMEDOUT)
+ {
+ printf ("cond_timedwait returned with %s\n", strerror (err));
+ exit (1);
+ }
+
+ err = pthread_mutex_unlock (&mut);
+ if (err != 0)
+ {
+ printf ("mutex_unlock failed: %s\n", strerror (err));
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cond6.c
@@ -0,0 +1,232 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+
+
+int *condition;
+
+static int
+do_test (void)
+{
+ size_t ps = sysconf (_SC_PAGESIZE);
+ char tmpfname[] = "/tmp/tst-cond6.XXXXXX";
+ char data[ps];
+ void *mem;
+ int fd;
+ pthread_mutexattr_t ma;
+ pthread_mutex_t *mut1;
+ pthread_mutex_t *mut2;
+ pthread_condattr_t ca;
+ pthread_cond_t *cond;
+ pid_t pid;
+ int result = 0;
+
+ fd = mkstemp (tmpfname);
+ if (fd == -1)
+ {
+ printf ("cannot open temporary file: %m\n");
+ exit (1);
+ }
+
+ /* Make sure it is always removed. */
+ unlink (tmpfname);
+
+ /* Create one page of data. */
+ memset (data, '\0', ps);
+
+ /* Write the data to the file. */
+ if (write (fd, data, ps) != (ssize_t) ps)
+ {
+ puts ("short write");
+ exit (1);
+ }
+
+ mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (mem == MAP_FAILED)
+ {
+ printf ("mmap failed: %m\n");
+ exit (1);
+ }
+
+ mut1 = (pthread_mutex_t *) (((uintptr_t) mem
+ + __alignof (pthread_mutex_t))
+ & ~(__alignof (pthread_mutex_t) - 1));
+ mut2 = mut1 + 1;
+
+ cond = (pthread_cond_t *) (((uintptr_t) (mut2 + 1)
+ + __alignof (pthread_cond_t))
+ & ~(__alignof (pthread_cond_t) - 1));
+
+ condition = (int *) (((uintptr_t) (cond + 1) + __alignof (int))
+ & ~(__alignof (int) - 1));
+
+ if (pthread_mutexattr_init (&ma) != 0)
+ {
+ puts ("mutexattr_init failed");
+ exit (1);
+ }
+
+ if (pthread_mutexattr_setpshared (&ma, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("mutexattr_setpshared failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_init (mut1, &ma) != 0)
+ {
+ puts ("1st mutex_init failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_init (mut2, &ma) != 0)
+ {
+ puts ("2nd mutex_init failed");
+ exit (1);
+ }
+
+ if (pthread_condattr_init (&ca) != 0)
+ {
+ puts ("condattr_init failed");
+ exit (1);
+ }
+
+ if (pthread_condattr_setpshared (&ca, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("condattr_setpshared failed");
+ exit (1);
+ }
+
+ if (pthread_cond_init (cond, &ca) != 0)
+ {
+ puts ("cond_init failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_lock (mut1) != 0)
+ {
+ puts ("parent: 1st mutex_lock failed");
+ exit (1);
+ }
+
+ puts ("going to fork now");
+ pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+ else if (pid == 0)
+ {
+ struct timespec ts;
+ struct timeval tv;
+
+ if (pthread_mutex_lock (mut2) != 0)
+ {
+ puts ("child: mutex_lock failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (mut1) != 0)
+ {
+ puts ("child: 1st mutex_unlock failed");
+ exit (1);
+ }
+
+ if (gettimeofday (&tv, NULL) != 0)
+ {
+ puts ("gettimeofday failed");
+ exit (1);
+ }
+
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_nsec += 500000000;
+ if (ts.tv_nsec >= 1000000000)
+ {
+ ts.tv_nsec -= 1000000000;
+ ++ts.tv_sec;
+ }
+
+ do
+ if (pthread_cond_timedwait (cond, mut2, &ts) != 0)
+ {
+ puts ("child: cond_wait failed");
+ exit (1);
+ }
+ while (*condition == 0);
+
+ if (pthread_mutex_unlock (mut2) != 0)
+ {
+ puts ("child: 2nd mutex_unlock failed");
+ exit (1);
+ }
+
+ puts ("child done");
+ }
+ else
+ {
+ int status;
+
+ if (pthread_mutex_lock (mut1) != 0)
+ {
+ puts ("parent: 2nd mutex_lock failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_lock (mut2) != 0)
+ {
+ puts ("parent: 3rd mutex_lock failed");
+ exit (1);
+ }
+
+ if (pthread_cond_signal (cond) != 0)
+ {
+ puts ("parent: cond_signal failed");
+ exit (1);
+ }
+
+ *condition = 1;
+
+ if (pthread_mutex_unlock (mut2) != 0)
+ {
+ puts ("parent: mutex_unlock failed");
+ exit (1);
+ }
+
+ puts ("waiting for child");
+
+ waitpid (pid, &status, 0);
+ result |= status;
+
+ puts ("parent done");
+ }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cond7.c
@@ -0,0 +1,167 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/time.h>
+
+
+typedef struct
+ {
+ pthread_cond_t cond;
+ pthread_mutex_t lock;
+ pthread_t h;
+ } T;
+
+
+static volatile bool done;
+
+
+static void *
+tf (void *arg)
+{
+ puts ("child created");
+
+ if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0
+ || pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL) != 0)
+ {
+ puts ("cannot set cancellation options");
+ exit (1);
+ }
+
+ T *t = (T *) arg;
+
+ if (pthread_mutex_lock (&t->lock) != 0)
+ {
+ puts ("child: lock failed");
+ exit (1);
+ }
+
+ done = true;
+
+ if (pthread_cond_signal (&t->cond) != 0)
+ {
+ puts ("child: cond_signal failed");
+ exit (1);
+ }
+
+ if (pthread_cond_wait (&t->cond, &t->lock) != 0)
+ {
+ puts ("child: cond_wait failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&t->lock) != 0)
+ {
+ puts ("child: unlock failed");
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ int i;
+#define N 100
+ T *t[N];
+ for (i = 0; i < N; ++i)
+ {
+ printf ("round %d\n", i);
+
+ t[i] = (T *) malloc (sizeof (T));
+ if (t[i] == NULL)
+ {
+ puts ("out of memory");
+ exit (1);
+ }
+
+ if (pthread_mutex_init (&t[i]->lock, NULL) != 0
+ || pthread_cond_init (&t[i]->cond, NULL) != 0)
+ {
+ puts ("an _init function failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_lock (&t[i]->lock) != 0)
+ {
+ puts ("initial mutex_lock failed");
+ exit (1);
+ }
+
+ done = false;
+
+ if (pthread_create (&t[i]->h, NULL, tf, t[i]) != 0)
+ {
+ puts ("pthread_create failed");
+ exit (1);
+ }
+
+ do
+ if (pthread_cond_wait (&t[i]->cond, &t[i]->lock) != 0)
+ {
+ puts ("cond_wait failed");
+ exit (1);
+ }
+ while (! done);
+
+ /* Release the lock since the cancel handler will get it. */
+ if (pthread_mutex_unlock (&t[i]->lock) != 0)
+ {
+ puts ("mutex_unlock failed");
+ exit (1);
+ }
+
+ if (pthread_cancel (t[i]->h) != 0)
+ {
+ puts ("cancel failed");
+ exit (1);
+ }
+
+ puts ("parent: joining now");
+
+ void *result;
+ if (pthread_join (t[i]->h, &result) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ if (result != PTHREAD_CANCELED)
+ {
+ puts ("result != PTHREAD_CANCELED");
+ exit (1);
+ }
+ }
+
+ for (i = 0; i < N; ++i)
+ free (t[i]);
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cond8-static.c
@@ -0,0 +1 @@
+#include "tst-cond8.c"
--- /dev/null
+++ b/fbtl/tst-cond8.c
@@ -0,0 +1,276 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
+
+static pthread_barrier_t bar;
+
+
+static void
+ch (void *arg)
+{
+ int e = pthread_mutex_lock (&mut);
+ if (e == 0)
+ {
+ puts ("mutex not locked at all by cond_wait");
+ exit (1);
+ }
+
+ if (e != EDEADLK)
+ {
+ puts ("no deadlock error signaled");
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&mut) != 0)
+ {
+ puts ("ch: cannot unlock mutex");
+ exit (1);
+ }
+
+ puts ("ch done");
+}
+
+
+static void *
+tf1 (void *p)
+{
+ int err;
+
+ if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0
+ || pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL) != 0)
+ {
+ puts ("cannot set cancellation options");
+ exit (1);
+ }
+
+ err = pthread_mutex_lock (&mut);
+ if (err != 0)
+ {
+ puts ("child: cannot get mutex");
+ exit (1);
+ }
+
+ err = pthread_barrier_wait (&bar);
+ if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("barrier_wait returned %d\n", err);
+ exit (1);
+ }
+
+ puts ("child: got mutex; waiting");
+
+ pthread_cleanup_push (ch, NULL);
+
+ pthread_cond_wait (&cond, &mut);
+
+ pthread_cleanup_pop (0);
+
+ puts ("child: cond_wait should not have returned");
+
+ return NULL;
+}
+
+
+static void *
+tf2 (void *p)
+{
+ int err;
+
+ if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0
+ || pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL) != 0)
+ {
+ puts ("cannot set cancellation options");
+ exit (1);
+ }
+
+ err = pthread_mutex_lock (&mut);
+ if (err != 0)
+ {
+ puts ("child: cannot get mutex");
+ exit (1);
+ }
+
+ err = pthread_barrier_wait (&bar);
+ if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("barrier_wait returned %d\n", err);
+ exit (1);
+ }
+
+ puts ("child: got mutex; waiting");
+
+ pthread_cleanup_push (ch, NULL);
+
+ /* Current time. */
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+ /* +1000 seconds in correct format. */
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_sec += 1000;
+
+ pthread_cond_timedwait (&cond, &mut, &ts);
+
+ pthread_cleanup_pop (0);
+
+ puts ("child: cond_wait should not have returned");
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+ int err;
+
+ printf ("&cond = %p\n&mut = %p\n", &cond, &mut);
+
+ puts ("parent: get mutex");
+
+ err = pthread_barrier_init (&bar, NULL, 2);
+ if (err != 0)
+ {
+ puts ("parent: cannot init barrier");
+ exit (1);
+ }
+
+ puts ("parent: create child");
+
+ err = pthread_create (&th, NULL, tf1, NULL);
+ if (err != 0)
+ {
+ puts ("parent: cannot create thread");
+ exit (1);
+ }
+
+ puts ("parent: wait for child to lock mutex");
+
+ err = pthread_barrier_wait (&bar);
+ if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("parent: cannot wait for barrier");
+ exit (1);
+ }
+
+ err = pthread_mutex_lock (&mut);
+ if (err != 0)
+ {
+ puts ("parent: mutex_lock failed");
+ exit (1);
+ }
+
+ err = pthread_mutex_unlock (&mut);
+ if (err != 0)
+ {
+ puts ("parent: mutex_unlock failed");
+ exit (1);
+ }
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cannot cancel thread");
+ exit (1);
+ }
+
+ void *r;
+ err = pthread_join (th, &r);
+ if (err != 0)
+ {
+ puts ("parent: failed to join");
+ exit (1);
+ }
+
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("child hasn't been canceled");
+ exit (1);
+ }
+
+
+
+ puts ("parent: create 2nd child");
+
+ err = pthread_create (&th, NULL, tf2, NULL);
+ if (err != 0)
+ {
+ puts ("parent: cannot create thread");
+ exit (1);
+ }
+
+ puts ("parent: wait for child to lock mutex");
+
+ err = pthread_barrier_wait (&bar);
+ if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("parent: cannot wait for barrier");
+ exit (1);
+ }
+
+ err = pthread_mutex_lock (&mut);
+ if (err != 0)
+ {
+ puts ("parent: mutex_lock failed");
+ exit (1);
+ }
+
+ err = pthread_mutex_unlock (&mut);
+ if (err != 0)
+ {
+ puts ("parent: mutex_unlock failed");
+ exit (1);
+ }
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cannot cancel thread");
+ exit (1);
+ }
+
+ err = pthread_join (th, &r);
+ if (err != 0)
+ {
+ puts ("parent: failed to join");
+ exit (1);
+ }
+
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("child hasn't been canceled");
+ exit (1);
+ }
+
+ puts ("done");
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-cond9.c
@@ -0,0 +1,149 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
+
+
+static void *
+tf (void *arg)
+{
+ int err = pthread_cond_wait (&cond, &mut);
+ if (err == 0)
+ {
+ puts ("cond_wait did not fail");
+ exit (1);
+ }
+
+ if (err != EPERM)
+ {
+ printf ("cond_wait didn't return EPERM but %d\n", err);
+ exit (1);
+ }
+
+
+ /* Current time. */
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+ /* +1000 seconds in correct format. */
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_sec += 1000;
+
+ err = pthread_cond_timedwait (&cond, &mut, &ts);
+ if (err == 0)
+ {
+ puts ("cond_timedwait did not fail");
+ exit (1);
+ }
+
+ if (err != EPERM)
+ {
+ printf ("cond_timedwait didn't return EPERM but %d\n", err);
+ exit (1);
+ }
+
+ return (void *) 1l;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+ int err;
+
+ printf ("&cond = %p\n&mut = %p\n", &cond, &mut);
+
+ err = pthread_cond_wait (&cond, &mut);
+ if (err == 0)
+ {
+ puts ("cond_wait did not fail");
+ exit (1);
+ }
+
+ if (err != EPERM)
+ {
+ printf ("cond_wait didn't return EPERM but %d\n", err);
+ exit (1);
+ }
+
+
+ /* Current time. */
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+ /* +1000 seconds in correct format. */
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_sec += 1000;
+
+ err = pthread_cond_timedwait (&cond, &mut, &ts);
+ if (err == 0)
+ {
+ puts ("cond_timedwait did not fail");
+ exit (1);
+ }
+
+ if (err != EPERM)
+ {
+ printf ("cond_timedwait didn't return EPERM but %d\n", err);
+ exit (1);
+ }
+
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ puts ("parent: mutex_lock failed");
+ exit (1);
+ }
+
+ puts ("creating thread");
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+ if (r != (void *) 1l)
+ {
+ puts ("thread has wrong return value");
+ exit (1);
+ }
+
+ puts ("done");
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-context1.c
@@ -0,0 +1,205 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <error.h>
+#include <limits.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ucontext.h>
+
+#define N 4
+#if __WORDSIZE == 64
+#define GUARD_PATTERN 0xdeadbeafdeadbeaf
+#else
+#define GUARD_PATTERN 0xdeadbeaf
+#endif
+
+typedef struct {
+ ucontext_t uctx;
+ unsigned long guard[3];
+ } tst_context_t;
+
+static char stacks[N][2 * PTHREAD_STACK_MIN];
+static tst_context_t ctx[N][2];
+static volatile int failures;
+
+
+static void
+fct (long int n)
+{
+ char on_stack[1];
+
+ /* Just to use the thread local descriptor. */
+ printf ("%ld: in %s now, on_stack = %p\n", n, __FUNCTION__, on_stack);
+ errno = 0;
+
+ if (ctx[n][1].uctx.uc_link != &ctx[n][0].uctx)
+ {
+ printf ("context[%ld][1] uc_link damaged, = %p\n", n,
+ ctx[n][1].uctx.uc_link);
+ exit (1);
+ }
+
+ if ((ctx[n][0].guard[0] != GUARD_PATTERN)
+ || (ctx[n][0].guard[1] != GUARD_PATTERN)
+ || (ctx[n][0].guard[2] != GUARD_PATTERN))
+ {
+ printf ("%ld: %s context[0] overflow detected!\n", n, __FUNCTION__);
+ ++failures;
+ }
+
+ if ((ctx[n][1].guard[0] != GUARD_PATTERN)
+ || (ctx[n][1].guard[1] != GUARD_PATTERN)
+ || (ctx[n][1].guard[2] != GUARD_PATTERN))
+ {
+ printf ("%ld: %s context[1] overflow detected!\n", n, __FUNCTION__);
+ ++failures;
+ }
+
+ if (n < 0 || n >= N)
+ {
+ printf ("%ld out of range\n", n);
+ exit (1);
+ }
+
+ if (on_stack < stacks[n] || on_stack >= stacks[n] + sizeof (stacks[0]))
+ {
+ printf ("%ld: on_stack not on appropriate stack\n", n);
+ exit (1);
+ }
+}
+
+
+static void *
+tf (void *arg)
+{
+ int n = (int) (long int) arg;
+
+ ctx[n][0].guard[0] = GUARD_PATTERN;
+ ctx[n][0].guard[1] = GUARD_PATTERN;
+ ctx[n][0].guard[2] = GUARD_PATTERN;
+
+ ctx[n][1].guard[0] = GUARD_PATTERN;
+ ctx[n][1].guard[1] = GUARD_PATTERN;
+ ctx[n][1].guard[2] = GUARD_PATTERN;
+
+ if (getcontext (&ctx[n][1].uctx) != 0)
+ {
+ printf ("%d: cannot get context: %m\n", n);
+ exit (1);
+ }
+
+ printf ("%d: %s: before makecontext\n", n, __FUNCTION__);
+
+ ctx[n][1].uctx.uc_stack.ss_sp = stacks[n];
+ ctx[n][1].uctx.uc_stack.ss_size = sizeof (stacks[n]);
+ ctx[n][1].uctx.uc_link = &ctx[n][0].uctx;
+ makecontext (&ctx[n][1].uctx, (void (*) (void)) fct, 1, (long int) n);
+
+ printf ("%d: %s: before swapcontext\n", n, __FUNCTION__);
+
+ if (swapcontext (&ctx[n][0].uctx, &ctx[n][1].uctx) != 0)
+ {
+ ++failures;
+ printf ("%d: %s: swapcontext failed\n", n, __FUNCTION__);
+ }
+ else
+ printf ("%d: back in %s\n", n, __FUNCTION__);
+
+ return NULL;
+}
+
+
+static volatile int global;
+
+
+static int
+do_test (void)
+{
+ int n;
+ pthread_t th[N];
+ ucontext_t mctx;
+
+ puts ("making contexts");
+ if (getcontext (&mctx) != 0)
+ {
+ if (errno == ENOSYS)
+ {
+ puts ("context handling not supported");
+ exit (0);
+ }
+
+ printf ("%s: getcontext: %m\n", __FUNCTION__);
+ exit (1);
+ }
+
+ /* Play some tricks with this context. */
+ if (++global == 1)
+ if (setcontext (&mctx) != 0)
+ {
+ puts ("setcontext failed");
+ exit (1);
+ }
+ if (global != 2)
+ {
+ puts ("global not incremented twice");
+ exit (1);
+ }
+ puts ("global OK");
+
+ pthread_attr_t at;
+
+ if (pthread_attr_init (&at) != 0)
+ {
+ puts ("attr_init failed");
+ return 1;
+ }
+
+ if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+ for (n = 0; n < N; ++n)
+ if (pthread_create (&th[n], &at, tf, (void *) (long int) n) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ if (pthread_attr_destroy (&at) != 0)
+ {
+ puts ("attr_destroy failed");
+ return 1;
+ }
+
+ for (n = 0; n < N; ++n)
+ if (pthread_join (th[n], NULL) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ return failures;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-default-attr.c
@@ -0,0 +1,385 @@
+/* Verify that pthread_[gs]etattr_default_np work correctly.
+
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdbool.h>
+
+#define RETURN_IF_FAIL(f, ...) \
+ ({ \
+ int ret = f (__VA_ARGS__); \
+ if (ret != 0) \
+ { \
+ printf ("%s:%d: %s returned %d (errno = %d)\n", __FILE__, __LINE__, \
+ #f, ret, errno); \
+ return ret; \
+ } \
+ })
+
+static int (*verify_result) (pthread_attr_t *);
+static size_t stacksize = 1024 * 1024;
+static size_t guardsize;
+static bool do_join = true;
+static int running = 0;
+static int detach_failed = 0;
+static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
+
+static void *
+thr (void *unused __attribute__ ((unused)))
+{
+ pthread_attr_t attr;
+ int ret;
+
+ memset (&attr, 0xab, sizeof attr);
+ /* To verify that the pthread_setattr_default_np worked. */
+ if ((ret = pthread_getattr_default_np (&attr)) != 0)
+ {
+ printf ("pthread_getattr_default_np failed: %s\n", strerror (ret));
+ goto out;
+ }
+
+ if ((ret = (*verify_result) (&attr)) != 0)
+ goto out;
+
+ memset (&attr, 0xab, sizeof attr);
+ /* To verify that the attributes actually got applied. */
+ if ((ret = pthread_getattr_np (pthread_self (), &attr)) != 0)
+ {
+ printf ("pthread_getattr_default_np failed: %s\n", strerror (ret));
+ goto out;
+ }
+
+ ret = (*verify_result) (&attr);
+
+out:
+ if (!do_join)
+ {
+ pthread_mutex_lock (&m);
+ running--;
+ pthread_cond_signal (&c);
+ pthread_mutex_unlock (&m);
+
+ detach_failed |= ret;
+ }
+
+ return (void *) (uintptr_t) ret;
+}
+
+static int
+run_threads (const pthread_attr_t *attr)
+{
+ pthread_t t;
+ void *tret = NULL;
+
+ RETURN_IF_FAIL (pthread_setattr_default_np, attr);
+
+ /* Run twice to ensure that the attributes do not get overwritten in the
+ first run somehow. */
+ for (int i = 0; i < 2; i++)
+ {
+ RETURN_IF_FAIL (pthread_create, &t, NULL, thr, NULL);
+ if (do_join)
+ RETURN_IF_FAIL (pthread_join, t, &tret);
+ else
+ {
+ pthread_mutex_lock (&m);
+ running++;
+ pthread_mutex_unlock (&m);
+ }
+
+ if (tret != NULL)
+ {
+ puts ("Thread failed");
+ return 1;
+ }
+ }
+
+ /* Stay in sync for detached threads and get their status. */
+ while (!do_join)
+ {
+ pthread_mutex_lock (&m);
+ if (running == 0)
+ {
+ pthread_mutex_unlock (&m);
+ break;
+ }
+ pthread_cond_wait (&c, &m);
+ pthread_mutex_unlock (&m);
+ }
+
+ return 0;
+}
+
+static int
+verify_detach_result (pthread_attr_t *attr)
+{
+ int state;
+
+ RETURN_IF_FAIL (pthread_attr_getdetachstate, attr, &state);
+
+ if (state != PTHREAD_CREATE_DETACHED)
+ {
+ puts ("failed to set detach state");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+do_detach_test (void)
+{
+ pthread_attr_t attr;
+
+ do_join = false;
+ RETURN_IF_FAIL (pthread_attr_init, &attr);
+ RETURN_IF_FAIL (pthread_attr_setdetachstate, &attr, PTHREAD_CREATE_DETACHED);
+
+ RETURN_IF_FAIL (run_threads, &attr);
+ return detach_failed;
+}
+
+static int
+verify_affinity_result (pthread_attr_t *attr)
+{
+ cpu_set_t cpuset;
+
+ RETURN_IF_FAIL (pthread_attr_getaffinity_np, attr, sizeof (cpuset), &cpuset);
+ if (!CPU_ISSET (0, &cpuset))
+ {
+ puts ("failed to set cpu affinity");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+do_affinity_test (void)
+{
+ pthread_attr_t attr;
+
+ RETURN_IF_FAIL (pthread_attr_init, &attr);
+
+ /* Processor affinity. Like scheduling policy, this could fail if the user
+ does not have the necessary privileges. So we only spew a warning if
+ pthread_create fails with EPERM. A computer has at least one CPU. */
+ cpu_set_t cpuset;
+ CPU_ZERO (&cpuset);
+ CPU_SET (0, &cpuset);
+ RETURN_IF_FAIL (pthread_attr_setaffinity_np, &attr, sizeof (cpuset), &cpuset);
+
+ int ret = run_threads (&attr);
+
+ if (ret == EPERM)
+ {
+ printf ("Skipping CPU Affinity test: %s\n", strerror (ret));
+ return 0;
+ }
+ else if (ret != 0)
+ return ret;
+
+ return 0;
+}
+
+static int
+verify_sched_result (pthread_attr_t *attr)
+{
+ int inherited, policy;
+ struct sched_param param;
+
+ RETURN_IF_FAIL (pthread_attr_getinheritsched, attr, &inherited);
+ if (inherited != PTHREAD_EXPLICIT_SCHED)
+ {
+ puts ("failed to set EXPLICIT_SCHED (%d != %d)");
+ return 1;
+ }
+
+ RETURN_IF_FAIL (pthread_attr_getschedpolicy, attr, &policy);
+ if (policy != SCHED_RR)
+ {
+ printf ("failed to set SCHED_RR (%d != %d)\n", policy, SCHED_RR);
+ return 1;
+ }
+
+ RETURN_IF_FAIL (pthread_attr_getschedparam, attr, ¶m);
+ if (param.sched_priority != 42)
+ {
+ printf ("failed to set sched_priority (%d != %d)\n",
+ param.sched_priority, 42);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+do_sched_test (void)
+{
+ pthread_attr_t attr;
+
+ RETURN_IF_FAIL (pthread_attr_init, &attr);
+
+ /* Scheduling policy. Note that we don't always test these since it's
+ possible that the user the tests run as don't have the appropriate
+ privileges. */
+ RETURN_IF_FAIL (pthread_attr_setinheritsched, &attr, PTHREAD_EXPLICIT_SCHED);
+ RETURN_IF_FAIL (pthread_attr_setschedpolicy, &attr, SCHED_RR);
+
+ struct sched_param param;
+ param.sched_priority = 42;
+ RETURN_IF_FAIL (pthread_attr_setschedparam, &attr, ¶m);
+
+ int ret = run_threads (&attr);
+
+ if (ret == EPERM)
+ {
+ printf ("Skipping Scheduler Attributes test: %s\n", strerror (ret));
+ return 0;
+ }
+ else if (ret != 0)
+ return ret;
+
+ return 0;
+}
+
+static int
+verify_guardsize_result (pthread_attr_t *attr)
+{
+ size_t guard;
+
+ RETURN_IF_FAIL (pthread_attr_getguardsize, attr, &guard);
+
+ if (guardsize != guard)
+ {
+ printf ("failed to set guardsize (%zu, %zu)\n", guardsize, guard);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+do_guardsize_test (void)
+{
+ long int pagesize = sysconf (_SC_PAGESIZE);
+ pthread_attr_t attr;
+
+ if (pagesize < 0)
+ {
+ printf ("sysconf failed: %s\n", strerror (errno));
+ return 1;
+ }
+
+ RETURN_IF_FAIL (pthread_getattr_default_np, &attr);
+
+ /* Increase default guardsize by a page. */
+ RETURN_IF_FAIL (pthread_attr_getguardsize, &attr, &guardsize);
+ guardsize += pagesize;
+ RETURN_IF_FAIL (pthread_attr_setguardsize, &attr, guardsize);
+ RETURN_IF_FAIL (run_threads, &attr);
+
+ return 0;
+}
+
+static int
+verify_stacksize_result (pthread_attr_t *attr)
+{
+ size_t stack;
+
+ RETURN_IF_FAIL (pthread_attr_getstacksize, attr, &stack);
+
+ if (stacksize != stack)
+ {
+ printf ("failed to set default stacksize (%zu, %zu)\n", stacksize, stack);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+do_stacksize_test (void)
+{
+ long int pagesize = sysconf (_SC_PAGESIZE);
+ pthread_attr_t attr;
+
+ if (pagesize < 0)
+ {
+ printf ("sysconf failed: %s\n", strerror (errno));
+ return 1;
+ }
+
+ /* Perturb the size by a page so that we're not aligned on the 64K boundary.
+ pthread_create does this perturbation on x86 to avoid causing the 64k
+ aliasing conflict. We want to prevent pthread_create from doing that
+ since it is not consistent for all architectures. */
+ stacksize += pagesize;
+
+ RETURN_IF_FAIL (pthread_attr_init, &attr);
+
+ /* Run twice to ensure that we don't give a false positive. */
+ RETURN_IF_FAIL (pthread_attr_setstacksize, &attr, stacksize);
+ RETURN_IF_FAIL (run_threads, &attr);
+ stacksize *= 2;
+ RETURN_IF_FAIL (pthread_attr_setstacksize, &attr, stacksize);
+ RETURN_IF_FAIL (run_threads, &attr);
+ return 0;
+}
+
+/* We test each attribute separately because sched and affinity tests may need
+ additional user privileges that may not be available during the test run.
+ Each attribute test is a set of two functions, viz. a function to set the
+ default attribute (do_foo_test) and another to verify its result
+ (verify_foo_result). Each test spawns a thread and checks (1) if the
+ attribute values were applied correctly and (2) if the change in the default
+ value reflected. */
+static int
+do_test (void)
+{
+ puts ("stacksize test");
+ verify_result = verify_stacksize_result;
+ RETURN_IF_FAIL (do_stacksize_test);
+
+ puts ("guardsize test");
+ verify_result = verify_guardsize_result;
+ RETURN_IF_FAIL (do_guardsize_test);
+
+ puts ("sched test");
+ verify_result = verify_sched_result;
+ RETURN_IF_FAIL (do_sched_test);
+
+ puts ("affinity test");
+ verify_result = verify_affinity_result;
+ RETURN_IF_FAIL (do_affinity_test);
+
+ puts ("detach test");
+ verify_result = verify_detach_result;
+ RETURN_IF_FAIL (do_detach_test);
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-detach1.c
@@ -0,0 +1,55 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static void *
+tf (void *arg)
+{
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ /* Give the child a chance to finish. */
+ sleep (1);
+
+ if (pthread_detach (th) != 0)
+ {
+ puts ("detach failed");
+ exit (1);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-dlsym1.c
@@ -0,0 +1,66 @@
+/* Test case by Hui Huang <hui.huang@sun.com>. */
+#include <dlfcn.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static void *
+start_routine (void *args)
+{
+ int i;
+ void **addrs = (void **) args;
+ for (i = 0; i < 10000; ++i)
+ addrs[i % 1024] = dlsym (NULL, "does_not_exist");
+
+ return addrs;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t tid1, tid2, tid3;
+
+ void *addrs1[1024];
+ void *addrs2[1024];
+ void *addrs3[1024];
+
+ if (pthread_create (&tid1, NULL, start_routine, addrs1) != 0)
+ {
+ puts ("1st create failed");
+ exit (1);
+ }
+ if (pthread_create (&tid2, NULL, start_routine, addrs2) != 0)
+ {
+ puts ("2nd create failed");
+ exit (1);
+ }
+ if (pthread_create (&tid3, NULL, start_routine, addrs3) != 0)
+ {
+ puts ("3rd create failed");
+ exit (1);
+ }
+
+ if (pthread_join (tid1, NULL) != 0)
+ {
+ puts ("1st join failed");
+ exit (1);
+ }
+ if (pthread_join (tid2, NULL) != 0)
+ {
+ puts ("2nd join failed");
+ exit (1);
+ }
+ if (pthread_join (tid3, NULL) != 0)
+ {
+ puts ("2rd join failed");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-eintr1.c
@@ -0,0 +1,104 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+#include "eintr.c"
+
+
+static void *
+tf2 (void *arg)
+{
+ return arg;
+}
+
+
+static void *
+tf1 (void *arg)
+{
+ while (1)
+ {
+ pthread_t th;
+
+ int e = pthread_create (&th, NULL, tf2, NULL);
+ if (e != 0)
+ {
+ if (e == EINTR)
+ {
+ puts ("pthread_create returned EINTR");
+ exit (1);
+ }
+
+ char buf[100];
+ printf ("tf1: pthread_create failed: %s\n",
+ strerror_r (e, buf, sizeof (buf)));
+ exit (1);
+ }
+
+ e = pthread_join (th, NULL);
+ if (e != 0)
+ {
+ if (e == EINTR)
+ {
+ puts ("pthread_join returned EINTR");
+ exit (1);
+ }
+
+ char buf[100];
+ printf ("tf1: pthread_join failed: %s\n",
+ strerror_r (e, buf, sizeof (buf)));
+ exit (1);
+ }
+ }
+}
+
+
+static int
+do_test (void)
+{
+ setup_eintr (SIGUSR1, NULL);
+
+ int i;
+ for (i = 0; i < 10; ++i)
+ {
+ pthread_t th;
+ int e = pthread_create (&th, NULL, tf1, NULL);
+ if (e != 0)
+ {
+ char buf[100];
+ printf ("main: pthread_create failed: %s\n",
+ strerror_r (e, buf, sizeof (buf)));
+ exit (1);
+ }
+ }
+
+ delayed_exit (3);
+ /* This call must never return. */
+ (void) tf1 (NULL);
+ return 1;
+}
--- /dev/null
+++ b/fbtl/tst-eintr2.c
@@ -0,0 +1,118 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+#include "eintr.c"
+
+
+static pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void *
+tf1 (void *arg)
+{
+ struct timespec ts;
+ struct timeval tv;
+
+ gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_sec += 10000;
+
+ /* This call must never return. */
+ int e = pthread_mutex_timedlock (&m1, &ts);
+ char buf[100];
+ printf ("tf1: mutex_timedlock returned: %s\n",
+ strerror_r (e, buf, sizeof (buf)));
+
+ exit (1);
+}
+
+
+static void *
+tf2 (void *arg)
+{
+ while (1)
+ {
+ int e = pthread_mutex_lock (&m2);
+ if (e != 0)
+ {
+ puts ("tf2: mutex_lock failed");
+ exit (1);
+ }
+ e = pthread_mutex_unlock (&m2);
+ if (e != 0)
+ {
+ puts ("tf2: mutex_unlock failed");
+ exit (1);
+ }
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
+ nanosleep (&ts, NULL);
+ }
+}
+
+
+static int
+do_test (void)
+{
+ if (pthread_mutex_lock (&m1) != 0)
+ {
+ puts ("mutex_lock failed");
+ exit (1);
+ }
+
+ setup_eintr (SIGUSR1, NULL);
+
+ pthread_t th;
+ char buf[100];
+ int e = pthread_create (&th, NULL, tf1, NULL);
+ if (e != 0)
+ {
+ printf ("main: 1st pthread_create failed: %s\n",
+ strerror_r (e, buf, sizeof (buf)));
+ exit (1);
+ }
+
+ e = pthread_create (&th, NULL, tf2, NULL);
+ if (e != 0)
+ {
+ printf ("main: 2nd pthread_create failed: %s\n",
+ strerror_r (e, buf, sizeof (buf)));
+ exit (1);
+ }
+
+ delayed_exit (3);
+ /* This call must never return. */
+ e = pthread_mutex_lock (&m1);
+ printf ("main: mutex_lock returned: %s\n",
+ strerror_r (e, buf, sizeof (buf)));
+
+ return 1;
+}
--- /dev/null
+++ b/fbtl/tst-eintr3.c
@@ -0,0 +1,69 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+#include "eintr.c"
+
+
+static void *
+tf (void *arg)
+{
+ pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+ pthread_mutex_lock (&m);
+ /* This call must not return. */
+ pthread_mutex_lock (&m);
+
+ puts ("tf: mutex_lock returned");
+ exit (1);
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t self = pthread_self ();
+
+ setup_eintr (SIGUSR1, &self);
+
+ pthread_t th;
+ char buf[100];
+ int e = pthread_create (&th, NULL, tf, NULL);
+ if (e != 0)
+ {
+ printf ("main: pthread_create failed: %s\n",
+ strerror_r (e, buf, sizeof (buf)));
+ exit (1);
+ }
+
+ delayed_exit (1);
+ /* This call must never return. */
+ xpthread_join (th);
+ puts ("error: pthread_join returned");
+ return 1;
+}
--- /dev/null
+++ b/fbtl/tst-eintr4.c
@@ -0,0 +1,53 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+#include "eintr.c"
+
+
+static int
+do_test (void)
+{
+ pthread_t self = pthread_self ();
+
+ setup_eintr (SIGUSR1, &self);
+
+ pthread_barrier_t b;
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ delayed_exit (1);
+ /* This call must never return. */
+ xpthread_barrier_wait (&b);
+ puts ("error: pthread_barrier_wait returned");
+ return 1;
+}
--- /dev/null
+++ b/fbtl/tst-eintr5.c
@@ -0,0 +1,79 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+#include "eintr.c"
+
+
+static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
+
+
+static void *
+tf (void *arg)
+{
+ struct timespec ts;
+ struct timeval tv;
+
+ gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_sec += 10000;
+
+ /* This call must never return. */
+ int e = pthread_cond_timedwait (&c, &m, &ts);
+ char buf[100];
+ printf ("tf: cond_timedwait returned: %s\n",
+ strerror_r (e, buf, sizeof (buf)));
+
+ exit (1);
+}
+
+
+static int
+do_test (void)
+{
+ setup_eintr (SIGUSR1, NULL);
+
+ pthread_t th;
+ char buf[100];
+ int e = pthread_create (&th, NULL, tf, NULL);
+ if (e != 0)
+ {
+ printf ("main: pthread_create failed: %s\n",
+ strerror_r (e, buf, sizeof (buf)));
+ exit (1);
+ }
+
+ delayed_exit (3);
+ /* This call must never return. */
+ xpthread_cond_wait (&c, &m);
+ puts ("error: pthread_cond_wait returned");
+ return 1;
+}
--- /dev/null
+++ b/fbtl/tst-exec1.c
@@ -0,0 +1,159 @@
+/* Simple exec test, only a thread in the parent.
+ Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <paths.h>
+#include <pthread.h>
+#include <signal.h>
+#include <spawn.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+
+static void *
+tf (void *arg)
+{
+ pthread_t th = (pthread_t) arg;
+
+ if (pthread_join (th, NULL) == 0)
+ {
+ puts ("thread in parent joined!?");
+ exit (1);
+ }
+
+ puts ("join in thread in parent returned!?");
+ exit (1);
+}
+
+
+static int
+do_test (void)
+{
+ int fd[2];
+ if (pipe (fd) != 0)
+ {
+ puts ("pipe failed");
+ exit (1);
+ }
+
+ /* Not interested in knowing when the pipe is closed. */
+ if (sigignore (SIGPIPE) != 0)
+ {
+ puts ("sigignore failed");
+ exit (1);
+ }
+
+ posix_spawn_file_actions_t a;
+ if (posix_spawn_file_actions_init (&a) != 0)
+ {
+ puts ("spawn_file_actions_init failed");
+ exit (1);
+ }
+
+ if (posix_spawn_file_actions_adddup2 (&a, fd[1], STDOUT_FILENO) != 0)
+ {
+ puts ("spawn_file_actions_adddup2 failed");
+ exit (1);
+ }
+
+ if (posix_spawn_file_actions_addclose (&a, fd[0]) != 0)
+ {
+ puts ("spawn_file_actions_addclose");
+ exit (1);
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ pid_t pid;
+ char *argv[] = { (char *) _PATH_BSHELL, (char *) "-c", (char *) "echo $$",
+ NULL };
+ if (posix_spawn (&pid, _PATH_BSHELL, &a, NULL, argv, NULL) != 0)
+ {
+ puts ("spawn failed");
+ exit (1);
+ }
+
+ close (fd[1]);
+
+ char buf[200];
+ ssize_t n;
+ bool seen_pid = false;
+ while (TEMP_FAILURE_RETRY ((n = read (fd[0], buf, sizeof (buf)))) > 0)
+ {
+ /* We only expect to read the PID. */
+ char *endp;
+ long int rpid = strtol (buf, &endp, 10);
+
+ if (*endp != '\n')
+ {
+ printf ("didn't parse whole line: \"%s\"\n", buf);
+ exit (1);
+ }
+ if (endp == buf)
+ {
+ puts ("read empty line");
+ exit (1);
+ }
+
+ if (rpid != pid)
+ {
+ printf ("found \"%s\", expected PID %ld\n", buf, (long int) pid);
+ exit (1);
+ }
+
+ if (seen_pid)
+ {
+ puts ("found more than one PID line");
+ exit (1);
+ }
+
+ seen_pid = true;
+ }
+
+ close (fd[0]);
+
+ int status;
+ int err = waitpid (pid, &status, 0);
+ if (err != pid)
+ {
+ puts ("waitpid failed");
+ exit (1);
+ }
+
+ if (!seen_pid)
+ {
+ puts ("didn't get PID");
+ exit (1);
+ }
+
+ puts ("read correct PID");
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-exec2.c
@@ -0,0 +1,154 @@
+/* Thread with running thread calls exec.
+ Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <paths.h>
+#include <pthread.h>
+#include <signal.h>
+#include <spawn.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+
+static void *
+tf (void *arg)
+{
+ pthread_t th = (pthread_t) arg;
+
+ if (pthread_join (th, NULL) == 0)
+ {
+ puts ("thread in parent joined!?");
+ exit (1);
+ }
+
+ puts ("join in thread in parent returned!?");
+ exit (1);
+}
+
+
+static int
+do_test (void)
+{
+ int fd[2];
+ if (pipe (fd) != 0)
+ {
+ puts ("pipe failed");
+ exit (1);
+ }
+
+ /* Not interested in knowing when the pipe is closed. */
+ if (sigignore (SIGPIPE) != 0)
+ {
+ puts ("sigignore failed");
+ exit (1);
+ }
+
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+
+ if (pid == 0)
+ {
+ /* Use the fd for stdout. This is kind of ugly because it
+ substitutes the fd of stdout but we know what we are doing
+ here... */
+ if (dup2 (fd[1], STDOUT_FILENO) != STDOUT_FILENO)
+ {
+ puts ("dup2 failed");
+ exit (1);
+ }
+
+ close (fd[0]);
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ execl (_PATH_BSHELL, _PATH_BSHELL, "-c", "echo $$", NULL);
+
+ puts ("execl failed");
+ exit (1);
+ }
+
+ close (fd[1]);
+
+ char buf[200];
+ ssize_t n;
+ bool seen_pid = false;
+ while (TEMP_FAILURE_RETRY ((n = read (fd[0], buf, sizeof (buf)))) > 0)
+ {
+ /* We only expect to read the PID. */
+ char *endp;
+ long int rpid = strtol (buf, &endp, 10);
+
+ if (*endp != '\n')
+ {
+ printf ("didn't parse whole line: \"%s\"\n", buf);
+ exit (1);
+ }
+ if (endp == buf)
+ {
+ puts ("read empty line");
+ exit (1);
+ }
+
+ if (rpid != pid)
+ {
+ printf ("found \"%s\", expected PID %ld\n", buf, (long int) pid);
+ exit (1);
+ }
+
+ if (seen_pid)
+ {
+ puts ("found more than one PID line");
+ exit (1);
+ }
+ seen_pid = true;
+ }
+
+ close (fd[0]);
+
+ int status;
+ int err = waitpid (pid, &status, 0);
+ if (err != pid)
+ {
+ puts ("waitpid failed");
+ exit (1);
+ }
+
+ if (!seen_pid)
+ {
+ puts ("didn't get PID");
+ exit (1);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-exec3.c
@@ -0,0 +1,152 @@
+/* Thread calls exec.
+ Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <paths.h>
+#include <pthread.h>
+#include <signal.h>
+#include <spawn.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+
+static void *
+tf (void *arg)
+{
+ execl (_PATH_BSHELL, _PATH_BSHELL, "-c", "echo $$", NULL);
+
+ puts ("execl failed");
+ exit (1);
+}
+
+
+static int
+do_test (void)
+{
+ int fd[2];
+ if (pipe (fd) != 0)
+ {
+ puts ("pipe failed");
+ exit (1);
+ }
+
+ /* Not interested in knowing when the pipe is closed. */
+ if (sigignore (SIGPIPE) != 0)
+ {
+ puts ("sigignore failed");
+ exit (1);
+ }
+
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+
+ if (pid == 0)
+ {
+ /* Use the fd for stdout. This is kind of ugly because it
+ substitutes the fd of stdout but we know what we are doing
+ here... */
+ if (dup2 (fd[1], STDOUT_FILENO) != STDOUT_FILENO)
+ {
+ puts ("dup2 failed");
+ exit (1);
+ }
+
+ close (fd[0]);
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ if (pthread_join (th, NULL) == 0)
+ {
+ puts ("join succeeded!?");
+ exit (1);
+ }
+
+ puts ("join returned!?");
+ exit (1);
+ }
+
+ close (fd[1]);
+
+ char buf[200];
+ ssize_t n;
+ bool seen_pid = false;
+ while (TEMP_FAILURE_RETRY ((n = read (fd[0], buf, sizeof (buf)))) > 0)
+ {
+ /* We only expect to read the PID. */
+ char *endp;
+ long int rpid = strtol (buf, &endp, 10);
+
+ if (*endp != '\n')
+ {
+ printf ("didn't parse whole line: \"%s\"\n", buf);
+ exit (1);
+ }
+ if (endp == buf)
+ {
+ puts ("read empty line");
+ exit (1);
+ }
+
+ if (rpid != pid)
+ {
+ printf ("found \"%s\", expected PID %ld\n", buf, (long int) pid);
+ exit (1);
+ }
+
+ if (seen_pid)
+ {
+ puts ("found more than one PID line");
+ exit (1);
+ }
+ seen_pid = true;
+ }
+
+ close (fd[0]);
+
+ int status;
+ int err = waitpid (pid, &status, 0);
+ if (err != pid)
+ {
+ puts ("waitpid failed");
+ exit (1);
+ }
+
+ if (!seen_pid)
+ {
+ puts ("didn't get PID");
+ exit (1);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-exec4.c
@@ -0,0 +1,115 @@
+/* Signal handler and mask set in thread which calls exec.
+ Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static void *
+tf (void *arg)
+{
+ /* Ignore SIGUSR1 and block SIGUSR2. */
+ if (sigignore (SIGUSR1) != 0)
+ {
+ puts ("sigignore failed");
+ exit (1);
+ }
+
+ sigset_t ss;
+ sigemptyset (&ss);
+ sigaddset (&ss, SIGUSR2);
+ if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+ {
+ puts ("1st run: sigmask failed");
+ exit (1);
+ }
+
+ char **oldargv = (char **) arg;
+ size_t n = 1;
+ while (oldargv[n] != NULL)
+ ++n;
+
+ char **argv = (char **) alloca ((n + 1) * sizeof (char *));
+ for (n = 0; oldargv[n + 1] != NULL; ++n)
+ argv[n] = oldargv[n + 1];
+ argv[n++] = (char *) "--direct";
+ argv[n] = NULL;
+
+ execv (argv[0], argv);
+
+ puts ("execv failed");
+
+ exit (1);
+}
+
+
+static int
+do_test (int argc, char *argv[])
+{
+ if (argc == 1)
+ {
+ /* This is the second call. Perform the test. */
+ struct sigaction sa;
+
+ if (sigaction (SIGUSR1, NULL, &sa) != 0)
+ {
+ puts ("2nd run: sigaction failed");
+ return 1;
+ }
+ if (sa.sa_handler != SIG_IGN)
+ {
+ puts ("SIGUSR1 not ignored");
+ return 1;
+ }
+
+ sigset_t ss;
+ if (pthread_sigmask (SIG_SETMASK, NULL, &ss) != 0)
+ {
+ puts ("2nd run: sigmask failed");
+ return 1;
+ }
+ if (! sigismember (&ss, SIGUSR2))
+ {
+ puts ("SIGUSR2 not blocked");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, argv) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ /* This call should never return. */
+ pthread_join (th, NULL);
+
+ puts ("join returned");
+
+ return 1;
+}
+
+#define TEST_FUNCTION do_test (argc, argv)
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-execstack-mod.c
@@ -0,0 +1 @@
+#include "../elf/tst-execstack-mod.c"
--- /dev/null
+++ b/fbtl/tst-execstack.c
@@ -0,0 +1,2 @@
+#define USE_PTHREADS 1
+#include "../elf/tst-execstack.c"
--- /dev/null
+++ b/fbtl/tst-exit1.c
@@ -0,0 +1,78 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* NOTE: this tests functionality beyond POSIX. POSIX does not allow
+ exit to be called more than once. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static pthread_barrier_t b;
+
+
+static void *
+tf (void *arg)
+{
+ int r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ exit (0);
+}
+
+
+static int
+do_test (void)
+{
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ /* Do nothing. */
+ if (pthread_join (th, NULL) == 0)
+ {
+ puts ("join succeeded!?");
+ exit (1);
+ }
+
+ puts ("join returned!?");
+ exit (1);
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-exit2.c
@@ -0,0 +1,42 @@
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+static void *
+tf (void *arg)
+{
+ while (1)
+ sleep (100);
+
+ /* NOTREACHED */
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+
+ int e = pthread_create (&th, NULL, tf, NULL);
+ if (e != 0)
+ {
+ printf ("create failed: %s\n", strerror (e));
+ return 1;
+ }
+
+ delayed_exit (1);
+
+ /* Terminate only this thread. */
+ pthread_exit (NULL);
+
+ /* NOTREACHED */
+ return 1;
+}
--- /dev/null
+++ b/fbtl/tst-exit3.c
@@ -0,0 +1,83 @@
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+static pthread_barrier_t b;
+
+
+static void *
+tf2 (void *arg)
+{
+ while (1)
+ sleep (100);
+
+ /* NOTREACHED */
+ return NULL;
+}
+
+
+static void *
+tf (void *arg)
+{
+ pthread_t th;
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ e = pthread_create (&th, NULL, tf2, NULL);
+ if (e != 0)
+ {
+ printf ("create failed: %s\n", strerror (e));
+ exit (1);
+ }
+
+ /* Terminate only this thread. */
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ int e = pthread_create (&th, NULL, tf, NULL);
+ if (e != 0)
+ {
+ printf ("create failed: %s\n", strerror (e));
+ exit (1);
+ }
+
+ e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ delayed_exit (3);
+
+ /* Terminate only this thread. */
+ pthread_exit (NULL);
+
+ /* NOTREACHED */
+ return 1;
+}
--- /dev/null
+++ b/fbtl/tst-fini1.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 2004-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <unistd.h>
+
+extern void m (void);
+
+int
+main (void)
+{
+ alarm (5);
+
+ m ();
+
+ /* The destructor is supposed to run now. Make sure that if it is
+ not we will notice it by using 42 as the exit code. In case the
+ destructor is run it will terminate with status zero. */
+ return 42;
+}
--- /dev/null
+++ b/fbtl/tst-fini1mod.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 2004-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static void *
+tf (void *arg)
+{
+ int fds[2];
+ if (pipe (fds) != 0)
+ {
+ puts ("pipe failed");
+ exit (1);
+ }
+
+ char buf[10];
+ read (fds[0], buf, sizeof (buf));
+
+ puts ("read returned");
+ exit (1);
+}
+
+static pthread_t th;
+
+static void
+__attribute ((destructor))
+dest (void)
+{
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cancel failed");
+ _exit (1);
+ }
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ _exit (1);
+ }
+ /* Exit successfully. */
+ _exit (0);
+}
+
+void
+m (void)
+{
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ _exit (1);
+ }
+}
--- /dev/null
+++ b/fbtl/tst-flock1.c
@@ -0,0 +1,92 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/file.h>
+
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+static int fd;
+
+
+static void *
+tf (void *arg)
+{
+ if (flock (fd, LOCK_SH | LOCK_NB) != 0)
+ {
+ puts ("second flock failed");
+ exit (1);
+ }
+
+ pthread_mutex_unlock (&lock);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ char tmp[] = "/tmp/tst-flock1-XXXXXX";
+
+ fd = mkstemp (tmp);
+ if (fd == -1)
+ {
+ puts ("mkstemp failed");
+ exit (1);
+ }
+
+ unlink (tmp);
+
+ write (fd, "foobar xyzzy", 12);
+
+ if (flock (fd, LOCK_EX | LOCK_NB) != 0)
+ {
+ puts ("first flock failed");
+ exit (1);
+ }
+
+ pthread_mutex_lock (&lock);
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("pthread_create failed");
+ exit (1);
+ }
+
+ pthread_mutex_lock (&lock);
+
+ void *result;
+ if (pthread_join (th, &result) != 0)
+ {
+ puts ("pthread_join failed");
+ exit (1);
+ }
+
+ close (fd);
+
+ return result != NULL;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-flock2.c
@@ -0,0 +1,259 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/file.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t lock2 = PTHREAD_MUTEX_INITIALIZER;
+static int fd;
+
+
+static void *
+tf (void *arg)
+{
+ struct flock fl =
+ {
+ .l_type = F_WRLCK,
+ .l_start = 0,
+ .l_whence = SEEK_SET,
+ .l_len = 10
+ };
+ if (TEMP_FAILURE_RETRY (fcntl (fd, F_SETLKW, &fl)) != 0)
+ {
+ puts ("fourth fcntl failed");
+ exit (1);
+ }
+
+ pthread_mutex_unlock (&lock);
+
+ pthread_mutex_lock (&lock2);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ char tmp[] = "/tmp/tst-flock2-XXXXXX";
+
+ fd = mkstemp (tmp);
+ if (fd == -1)
+ {
+ puts ("mkstemp failed");
+ return 1;
+ }
+
+ unlink (tmp);
+
+ int i;
+ for (i = 0; i < 20; ++i)
+ write (fd, "foobar xyzzy", 12);
+
+ pthread_barrier_t *b;
+ b = mmap (NULL, sizeof (pthread_barrier_t), PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ if (b == MAP_FAILED)
+ {
+ puts ("mmap failed");
+ return 1;
+ }
+
+ pthread_barrierattr_t ba;
+ if (pthread_barrierattr_init (&ba) != 0)
+ {
+ puts ("barrierattr_init failed");
+ return 1;
+ }
+
+ if (pthread_barrierattr_setpshared (&ba, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("barrierattr_setpshared failed");
+ return 1;
+ }
+
+ if (pthread_barrier_init (b, &ba, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ if (pthread_barrierattr_destroy (&ba) != 0)
+ {
+ puts ("barrierattr_destroy failed");
+ return 1;
+ }
+
+ struct flock fl =
+ {
+ .l_type = F_WRLCK,
+ .l_start = 0,
+ .l_whence = SEEK_SET,
+ .l_len = 10
+ };
+ if (TEMP_FAILURE_RETRY (fcntl (fd, F_SETLKW, &fl)) != 0)
+ {
+ puts ("first fcntl failed");
+ return 1;
+ }
+
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ return 1;
+ }
+
+ if (pid == 0)
+ {
+ /* Make sure the child does not stay around indefinitely. */
+ alarm (10);
+
+ /* Try to get the lock. */
+ if (TEMP_FAILURE_RETRY (fcntl (fd, F_SETLK, &fl)) == 0)
+ {
+ puts ("child: second flock succeeded");
+ return 1;
+ }
+ }
+
+ pthread_barrier_wait (b);
+
+ if (pid != 0)
+ {
+ fl.l_type = F_UNLCK;
+ if (TEMP_FAILURE_RETRY (fcntl (fd, F_SETLKW, &fl)) != 0)
+ {
+ puts ("third fcntl failed");
+ return 1;
+ }
+ }
+
+ pthread_barrier_wait (b);
+
+ pthread_t th;
+ if (pid == 0)
+ {
+ if (pthread_mutex_lock (&lock) != 0)
+ {
+ puts ("1st locking of lock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&lock2) != 0)
+ {
+ puts ("1st locking of lock2 failed");
+ return 1;
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("pthread_create failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&lock) != 0)
+ {
+ puts ("2nd locking of lock failed");
+ return 1;
+ }
+
+ puts ("child locked file");
+ }
+
+ pthread_barrier_wait (b);
+
+ if (pid != 0)
+ {
+ fl.l_type = F_WRLCK;
+ if (TEMP_FAILURE_RETRY (fcntl (fd, F_SETLK, &fl)) == 0)
+ {
+ puts ("fifth fcntl succeeded");
+ return 1;
+ }
+
+ puts ("file locked by child");
+ }
+
+ pthread_barrier_wait (b);
+
+ if (pid == 0)
+ {
+ if (pthread_mutex_unlock (&lock2) != 0)
+ {
+ puts ("unlock of lock2 failed");
+ return 1;
+ }
+
+ if (pthread_join (th, NULL) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ puts ("child's thread terminated");
+ }
+
+ pthread_barrier_wait (b);
+
+ if (pid != 0)
+ {
+ fl.l_type = F_WRLCK;
+ if (TEMP_FAILURE_RETRY (fcntl (fd, F_SETLK, &fl)) == 0)
+ {
+ puts ("fifth fcntl succeeded");
+ return 1;
+ }
+
+ puts ("file still locked");
+ }
+
+ pthread_barrier_wait (b);
+
+ if (pid == 0)
+ {
+ _exit (0);
+ }
+
+ int status;
+ if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+ {
+ puts ("waitpid failed");
+ return 1;
+ }
+ puts ("child terminated");
+
+ if (TEMP_FAILURE_RETRY (fcntl (fd, F_SETLKW, &fl)) != 0)
+ {
+ puts ("sixth fcntl failed");
+ return 1;
+ }
+
+ return status;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-fork1.c
@@ -0,0 +1,119 @@
+/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Roland McGrath <roland@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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+static void *
+thread_function (void * arg)
+{
+ int i = (intptr_t) arg;
+ int status;
+ pid_t pid;
+ pid_t pid2;
+
+ pid = fork ();
+ switch (pid)
+ {
+ case 0:
+ printf ("%ld for %d\n", (long int) getpid (), i);
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 * i };
+ nanosleep (&ts, NULL);
+ _exit (i);
+ break;
+ case -1:
+ printf ("fork: %m\n");
+ return (void *) 1l;
+ break;
+ }
+
+ pid2 = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
+ if (pid2 != pid)
+ {
+ printf ("waitpid returned %ld, expected %ld\n",
+ (long int) pid2, (long int) pid);
+ return (void *) 1l;
+ }
+
+ printf ("%ld with %d, expected %d\n",
+ (long int) pid, WEXITSTATUS (status), i);
+
+ return WEXITSTATUS (status) == i ? NULL : (void *) 1l;
+}
+
+#define N 5
+static const int t[N] = { 7, 6, 5, 4, 3 };
+
+int
+main (void)
+{
+ pthread_t th[N];
+ int i;
+ int result = 0;
+ pthread_attr_t at;
+
+ if (pthread_attr_init (&at) != 0)
+ {
+ puts ("attr_init failed");
+ return 1;
+ }
+
+ if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+ for (i = 0; i < N; ++i)
+ if (pthread_create (&th[i], NULL, thread_function,
+ (void *) (intptr_t) t[i]) != 0)
+ {
+ printf ("creation of thread %d failed\n", i);
+ exit (1);
+ }
+
+ if (pthread_attr_destroy (&at) != 0)
+ {
+ puts ("attr_destroy failed");
+ return 1;
+ }
+
+ for (i = 0; i < N; ++i)
+ {
+ void *v;
+ if (pthread_join (th[i], &v) != 0)
+ {
+ printf ("join of thread %d failed\n", i);
+ result = 1;
+ }
+ else if (v != NULL)
+ {
+ printf ("join %d successful, but child failed\n", i);
+ result = 1;
+ }
+ else
+ printf ("join %d successful\n", i);
+ }
+
+ return result;
+}
--- /dev/null
+++ b/fbtl/tst-fork2.c
@@ -0,0 +1,89 @@
+/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Roland McGrath <roland@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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+
+static pid_t initial_pid;
+
+
+static void *
+tf (void *arg)
+{
+ if (getppid () != initial_pid)
+ {
+ printf ("getppid in thread returned %ld, expected %ld\n",
+ (long int) getppid (), (long int) initial_pid);
+ return (void *) -1;
+ }
+
+ return NULL;
+}
+
+
+int
+main (void)
+{
+ initial_pid = getpid ();
+
+ pid_t child = fork ();
+ if (child == 0)
+ {
+ if (getppid () != initial_pid)
+ {
+ printf ("first getppid returned %ld, expected %ld\n",
+ (long int) getppid (), (long int) initial_pid);
+ exit (1);
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("pthread_create failed");
+ exit (1);
+ }
+
+ void *result;
+ if (pthread_join (th, &result) != 0)
+ {
+ puts ("pthread_join failed");
+ exit (1);
+ }
+
+ exit (result == NULL ? 0 : 1);
+ }
+ else if (child == -1)
+ {
+ puts ("initial fork failed");
+ return 1;
+ }
+
+ int status;
+ if (TEMP_FAILURE_RETRY (waitpid (child, &status, 0)) != child)
+ {
+ printf ("waitpid failed: %m\n");
+ return 1;
+ }
+
+ return status;
+}
--- /dev/null
+++ b/fbtl/tst-fork3.c
@@ -0,0 +1,106 @@
+/* Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Roland McGrath <roland@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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+
+static pid_t initial_pid;
+
+
+static void *
+tf2 (void *arg)
+{
+ if (getppid () != initial_pid)
+ {
+ printf ("getppid in thread returned %ld, expected %ld\n",
+ (long int) getppid (), (long int) initial_pid);
+ return (void *) -1;
+ }
+
+ return NULL;
+}
+
+
+static void *
+tf1 (void *arg)
+{
+ pid_t child = fork ();
+ if (child == 0)
+ {
+ if (getppid () != initial_pid)
+ {
+ printf ("first getppid returned %ld, expected %ld\n",
+ (long int) getppid (), (long int) initial_pid);
+ exit (1);
+ }
+
+ pthread_t th2;
+ if (pthread_create (&th2, NULL, tf2, NULL) != 0)
+ {
+ puts ("child: pthread_create failed");
+ exit (1);
+ }
+
+ void *result;
+ if (pthread_join (th2, &result) != 0)
+ {
+ puts ("pthread_join failed");
+ exit (1);
+ }
+
+ exit (result == NULL ? 0 : 1);
+ }
+ else if (child == -1)
+ {
+ puts ("initial fork failed");
+ exit (1);
+ }
+
+ int status;
+ if (TEMP_FAILURE_RETRY (waitpid (child, &status, 0)) != child)
+ {
+ printf ("waitpid failed: %m\n");
+ exit (1);
+ }
+
+ exit (status);
+}
+
+
+int
+main (void)
+{
+ initial_pid = getpid ();
+
+ pthread_t th1;
+ if (pthread_create (&th1, NULL, tf1, NULL) != 0)
+ {
+ puts ("parent: pthread_create failed");
+ exit (1);
+ }
+
+ /* This call should never return. */
+ pthread_join (th1, NULL);
+
+ return 1;
+}
--- /dev/null
+++ b/fbtl/tst-fork4.c
@@ -0,0 +1,64 @@
+/* Test of fork updating child universe's pthread structures.
+ Copyright (C) 2003-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <string.h>
+
+
+static int
+do_test (void)
+{
+ pthread_t me = pthread_self ();
+
+ pid_t pid = fork ();
+
+ if (pid < 0)
+ {
+ printf ("fork: %m\n");
+ return 1;
+ }
+
+ if (pid == 0)
+ {
+ int err = pthread_kill (me, SIGTERM);
+ printf ("pthread_kill returned: %s\n", strerror (err));
+ return 3;
+ }
+
+ int status;
+ errno = 0;
+ if (wait (&status) != pid)
+ printf ("wait failed: %m\n");
+ else if (WIFSIGNALED (status) && WTERMSIG (status) == SIGTERM)
+ {
+ printf ("child correctly died with SIGTERM\n");
+ return 0;
+ }
+ else
+ printf ("child died with bad status %#x\n", status);
+
+ return 1;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-getpid1.c
@@ -0,0 +1,122 @@
+#include <sched.h>
+#include <signal.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stackinfo.h>
+
+#ifndef TEST_CLONE_FLAGS
+#define TEST_CLONE_FLAGS 0
+#endif
+
+static int sig;
+
+static int
+f (void *a)
+{
+ puts ("in f");
+ union sigval sival;
+ sival.sival_int = getpid ();
+ printf ("pid = %d\n", sival.sival_int);
+ if (sigqueue (getppid (), sig, sival) != 0)
+ return 1;
+ return 0;
+}
+
+
+static int
+do_test (void)
+{
+ int mypid = getpid ();
+
+ sig = SIGRTMIN;
+ sigset_t ss;
+ sigemptyset (&ss);
+ sigaddset (&ss, sig);
+ if (sigprocmask (SIG_BLOCK, &ss, NULL) != 0)
+ {
+ printf ("sigprocmask failed: %m\n");
+ return 1;
+ }
+
+#ifdef __ia64__
+ extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base,
+ size_t __child_stack_size, int __flags,
+ void *__arg, ...);
+ char st[256 * 1024] __attribute__ ((aligned));
+ pid_t p = __clone2 (f, st, sizeof (st), TEST_CLONE_FLAGS, 0);
+#else
+ char st[128 * 1024] __attribute__ ((aligned));
+# if _STACK_GROWS_DOWN
+ pid_t p = clone (f, st + sizeof (st), TEST_CLONE_FLAGS, 0);
+# elif _STACK_GROWS_UP
+ pid_t p = clone (f, st, TEST_CLONE_FLAGS, 0);
+# else
+# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
+# endif
+#endif
+ if (p == -1)
+ {
+ printf("clone failed: %m\n");
+ return 1;
+ }
+ printf ("new thread: %d\n", (int) p);
+
+ siginfo_t si;
+ do
+ if (sigwaitinfo (&ss, &si) < 0)
+ {
+ printf("sigwaitinfo failed: %m\n");
+ kill (p, SIGKILL);
+ return 1;
+ }
+ while (si.si_signo != sig || si.si_code != SI_QUEUE);
+
+ int e;
+ if (waitpid (p, &e, __WCLONE) != p)
+ {
+ puts ("waitpid failed");
+ kill (p, SIGKILL);
+ return 1;
+ }
+ if (!WIFEXITED (e))
+ {
+ if (WIFSIGNALED (e))
+ printf ("died from signal %s\n", strsignal (WTERMSIG (e)));
+ else
+ puts ("did not terminate correctly");
+ return 1;
+ }
+ if (WEXITSTATUS (e) != 0)
+ {
+ printf ("exit code %d\n", WEXITSTATUS (e));
+ return 1;
+ }
+
+ if (si.si_int != (int) p)
+ {
+ printf ("expected PID %d, got si_int %d\n", (int) p, si.si_int);
+ kill (p, SIGKILL);
+ return 1;
+ }
+
+ if (si.si_pid != p)
+ {
+ printf ("expected PID %d, got si_pid %d\n", (int) p, (int) si.si_pid);
+ kill (p, SIGKILL);
+ return 1;
+ }
+
+ if (getpid () != mypid)
+ {
+ puts ("my PID changed");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-getpid2.c
@@ -0,0 +1,2 @@
+#define TEST_CLONE_FLAGS CLONE_VM
+#include "tst-getpid1.c"
--- /dev/null
+++ b/fbtl/tst-getpid3.c
@@ -0,0 +1,114 @@
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+
+static pid_t pid;
+
+static void *
+pid_thread (void *arg)
+{
+ if (pid != getpid ())
+ {
+ printf ("pid wrong in thread: should be %d, is %d\n",
+ (int) pid, (int) getpid ());
+ return (void *) 1L;
+ }
+
+ return NULL;
+}
+
+static int
+do_test (void)
+{
+ pid = getpid ();
+
+ pthread_t thr;
+ int ret = pthread_create (&thr, NULL, pid_thread, NULL);
+ if (ret)
+ {
+ printf ("pthread_create failed: %d\n", ret);
+ return 1;
+ }
+
+ void *thr_ret;
+ ret = pthread_join (thr, &thr_ret);
+ if (ret)
+ {
+ printf ("pthread_create failed: %d\n", ret);
+ return 1;
+ }
+ else if (thr_ret)
+ {
+ printf ("thread getpid failed\n");
+ return 1;
+ }
+
+ pid_t child = fork ();
+ if (child == -1)
+ {
+ printf ("fork failed: %m\n");
+ return 1;
+ }
+ else if (child == 0)
+ {
+ if (pid == getpid ())
+ {
+ puts ("pid did not change after fork");
+ exit (1);
+ }
+
+ pid = getpid ();
+ ret = pthread_create (&thr, NULL, pid_thread, NULL);
+ if (ret)
+ {
+ printf ("pthread_create failed: %d\n", ret);
+ return 1;
+ }
+
+ ret = pthread_join (thr, &thr_ret);
+ if (ret)
+ {
+ printf ("pthread_create failed: %d\n", ret);
+ return 1;
+ }
+ else if (thr_ret)
+ {
+ printf ("thread getpid failed\n");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ int status;
+ if (TEMP_FAILURE_RETRY (waitpid (child, &status, 0)) != child)
+ {
+ puts ("waitpid failed");
+ kill (child, SIGKILL);
+ return 1;
+ }
+
+ if (!WIFEXITED (status))
+ {
+ if (WIFSIGNALED (status))
+ printf ("died from signal %s\n", strsignal (WTERMSIG (status)));
+ else
+ puts ("did not terminate correctly");
+ return 1;
+ }
+ if (WEXITSTATUS (status) != 0)
+ {
+ printf ("exit code %d\n", WEXITSTATUS (status));
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-initializers1-c89.c
@@ -0,0 +1 @@
+#include "tst-initializers1.c"
--- /dev/null
+++ b/fbtl/tst-initializers1-c99.c
@@ -0,0 +1 @@
+#include "tst-initializers1.c"
--- /dev/null
+++ b/fbtl/tst-initializers1-gnu89.c
@@ -0,0 +1 @@
+#include "tst-initializers1.c"
--- /dev/null
+++ b/fbtl/tst-initializers1-gnu99.c
@@ -0,0 +1 @@
+#include "tst-initializers1.c"
--- /dev/null
+++ b/fbtl/tst-initializers1.c
@@ -0,0 +1,57 @@
+/* Copyright (C) 2005-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* We test the code undef conditions outside of glibc. */
+#undef _LIBC
+
+#include <pthread.h>
+
+pthread_mutex_t mtx_normal = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t mtx_recursive = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+pthread_mutex_t mtx_errorchk = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
+pthread_mutex_t mtx_adaptive = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
+pthread_rwlock_t rwl_normal = PTHREAD_RWLOCK_INITIALIZER;
+pthread_rwlock_t rwl_writer
+ = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP;
+pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+
+int
+main (void)
+{
+ if (mtx_normal.__data.__kind != PTHREAD_MUTEX_TIMED_NP)
+ return 1;
+ if (mtx_recursive.__data.__kind != PTHREAD_MUTEX_RECURSIVE_NP)
+ return 2;
+ if (mtx_errorchk.__data.__kind != PTHREAD_MUTEX_ERRORCHECK_NP)
+ return 3;
+ if (mtx_adaptive.__data.__kind != PTHREAD_MUTEX_ADAPTIVE_NP)
+ return 4;
+ if (rwl_normal.__data.__flags != PTHREAD_RWLOCK_PREFER_READER_NP)
+ return 5;
+ if (rwl_writer.__data.__flags
+ != PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP)
+ return 6;
+ /* <libc-lock.h> __libc_rwlock_init definition for libc.so
+ relies on PTHREAD_RWLOCK_INITIALIZER being all zeros. If
+ that ever changes, <libc-lock.h> needs updating. */
+ size_t i;
+ for (i = 0; i < sizeof (rwl_normal); i++)
+ if (((char *) &rwl_normal)[i] != '\0')
+ return 7;
+ return 0;
+}
--- /dev/null
+++ b/fbtl/tst-join1.c
@@ -0,0 +1,82 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void *
+tf (void *arg)
+{
+ pthread_t mh = (pthread_t) arg;
+ void *result;
+
+ if (pthread_mutex_unlock (&lock) != 0)
+ {
+ puts ("unlock failed");
+ exit (1);
+ }
+
+ if (pthread_join (mh, &result) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ if (result != (void *) 42l)
+ {
+ printf ("result wrong: expected %p, got %p\n", (void *) 42, result);
+ exit (1);
+ }
+
+ exit (0);
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_mutex_lock (&lock) != 0)
+ {
+ puts ("1st lock failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_lock (&lock) != 0)
+ {
+ puts ("2nd lock failed");
+ exit (1);
+ }
+
+ pthread_exit ((void *) 42);
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-join2.c
@@ -0,0 +1,103 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void *
+tf (void *arg)
+{
+ if (pthread_mutex_lock (&lock) != 0)
+ {
+ puts ("child: mutex_lock failed");
+ return NULL;
+ }
+
+ return (void *) 42l;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_mutex_lock (&lock) != 0)
+ {
+ puts ("mutex_lock failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("mutex_create failed");
+ exit (1);
+ }
+
+ void *status;
+ int val = pthread_tryjoin_np (th, &status);
+ if (val == 0)
+ {
+ puts ("1st tryjoin succeeded");
+ exit (1);
+ }
+ else if (val != EBUSY)
+ {
+ puts ("1st tryjoin didn't return EBUSY");
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&lock) != 0)
+ {
+ puts ("mutex_unlock failed");
+ exit (1);
+ }
+
+ while ((val = pthread_tryjoin_np (th, &status)) != 0)
+ {
+ if (val != EBUSY)
+ {
+ printf ("tryjoin returned %s (%d), expected only 0 or EBUSY\n",
+ strerror (val), val);
+ exit (1);
+ }
+
+ /* Delay minimally. */
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
+ nanosleep (&ts, NULL);
+ }
+
+ if (status != (void *) 42l)
+ {
+ printf ("return value %p, expected %p\n", status, (void *) 42l);
+ exit (1);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-join3.c
@@ -0,0 +1,122 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void *
+tf (void *arg)
+{
+ if (pthread_mutex_lock (&lock) != 0)
+ {
+ puts ("child: mutex_lock failed");
+ return NULL;
+ }
+
+ return (void *) 42l;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_mutex_lock (&lock) != 0)
+ {
+ puts ("mutex_lock failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("mutex_create failed");
+ exit (1);
+ }
+
+ void *status;
+ struct timespec ts;
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_nsec += 200000000;
+ if (ts.tv_nsec >= 1000000000)
+ {
+ ts.tv_nsec -= 1000000000;
+ ++ts.tv_sec;
+ }
+ int val = pthread_timedjoin_np (th, &status, &ts);
+ if (val == 0)
+ {
+ puts ("1st timedjoin succeeded");
+ exit (1);
+ }
+ else if (val != ETIMEDOUT)
+ {
+ puts ("1st timedjoin didn't return ETIMEDOUT");
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&lock) != 0)
+ {
+ puts ("mutex_unlock failed");
+ exit (1);
+ }
+
+ while (1)
+ {
+ (void) gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_nsec += 200000000;
+ if (ts.tv_nsec >= 1000000000)
+ {
+ ts.tv_nsec -= 1000000000;
+ ++ts.tv_sec;
+ }
+
+ val = pthread_timedjoin_np (th, &status, &ts);
+ if (val == 0)
+ break;
+
+ if (val != ETIMEDOUT)
+ {
+ printf ("timedjoin returned %s (%d), expected only 0 or ETIMEDOUT\n",
+ strerror (val), val);
+ exit (1);
+ }
+ }
+
+ if (status != (void *) 42l)
+ {
+ printf ("return value %p, expected %p\n", status, (void *) 42l);
+ exit (1);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-join4.c
@@ -0,0 +1,124 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_barrier_t bar;
+
+
+static void *
+tf (void *arg)
+{
+ if (pthread_barrier_wait (&bar) != 0)
+ {
+ puts ("tf: barrier_wait failed");
+ exit (1);
+ }
+
+ return (void *) 1l;
+}
+
+
+static int
+do_test (void)
+{
+ if (pthread_barrier_init (&bar, NULL, 3) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ pthread_attr_t a;
+
+ if (pthread_attr_init (&a) != 0)
+ {
+ puts ("attr_init failed");
+ exit (1);
+ }
+
+ if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+ pthread_t th[2];
+
+ if (pthread_create (&th[0], &a, tf, NULL) != 0)
+ {
+ puts ("1st create failed");
+ exit (1);
+ }
+
+ if (pthread_attr_setdetachstate (&a, PTHREAD_CREATE_DETACHED) != 0)
+ {
+ puts ("attr_setdetachstate failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th[1], &a, tf, NULL) != 0)
+ {
+ puts ("1st create failed");
+ exit (1);
+ }
+
+ if (pthread_attr_destroy (&a) != 0)
+ {
+ puts ("attr_destroy failed");
+ exit (1);
+ }
+
+ if (pthread_detach (th[0]) != 0)
+ {
+ puts ("could not detach 1st thread");
+ exit (1);
+ }
+
+ int err = pthread_detach (th[0]);
+ if (err == 0)
+ {
+ puts ("second detach of 1st thread succeeded");
+ exit (1);
+ }
+ if (err != EINVAL)
+ {
+ printf ("second detach of 1st thread returned %d, not EINVAL\n", err);
+ exit (1);
+ }
+
+ err = pthread_detach (th[1]);
+ if (err == 0)
+ {
+ puts ("detach of 2nd thread succeeded");
+ exit (1);
+ }
+ if (err != EINVAL)
+ {
+ printf ("detach of 2nd thread returned %d, not EINVAL\n", err);
+ exit (1);
+ }
+
+ exit (0);
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-join5.c
@@ -0,0 +1,210 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+#if !defined(__NR_nanosleep) && defined(SYS_nanosleep)
+# define __NR_nanosleep SYS_nanosleep
+#endif
+
+#define wait_code() \
+ do { \
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 200000000 }; \
+ while (syscall (__NR_nanosleep, &ts, &ts) < 0) \
+ /* nothing */; \
+ } while (0)
+
+
+#ifdef WAIT_IN_CHILD
+static pthread_barrier_t b;
+#endif
+
+
+static void *
+tf1 (void *arg)
+{
+#ifdef WAIT_IN_CHILD
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __func__);
+ exit (1);
+ }
+
+ wait_code ();
+#endif
+
+ pthread_join ((pthread_t) arg, NULL);
+
+ exit (42);
+}
+
+
+static void *
+tf2 (void *arg)
+{
+#ifdef WAIT_IN_CHILD
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __func__);
+ exit (1);
+ }
+
+ wait_code ();
+#endif
+ pthread_join ((pthread_t) arg, NULL);
+
+ exit (43);
+}
+
+
+static int
+do_test (void)
+{
+#ifdef WAIT_IN_CHILD
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+#endif
+
+ pthread_t th;
+
+ int err = pthread_join (pthread_self (), NULL);
+ if (err == 0)
+ {
+ puts ("1st circular join succeeded");
+ return 1;
+ }
+ if (err != EDEADLK)
+ {
+ printf ("1st circular join %d, not EDEADLK\n", err);
+ return 1;
+ }
+
+ if (pthread_create (&th, NULL, tf1, (void *) pthread_self ()) != 0)
+ {
+ puts ("1st create failed");
+ return 1;
+ }
+
+#ifndef WAIT_IN_CHILD
+ wait_code ();
+#endif
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cannot cancel 1st thread");
+ return 1;
+ }
+
+#ifdef WAIT_IN_CHILD
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __func__);
+ return 1;
+ }
+#endif
+
+ void *r;
+ err = pthread_join (th, &r);
+ if (err != 0)
+ {
+ printf ("cannot join 1st thread: %d\n", err);
+ return 1;
+ }
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("1st thread not canceled");
+ return 1;
+ }
+
+ err = pthread_join (pthread_self (), NULL);
+ if (err == 0)
+ {
+ puts ("2nd circular join succeeded");
+ return 1;
+ }
+ if (err != EDEADLK)
+ {
+ printf ("2nd circular join %d, not EDEADLK\n", err);
+ return 1;
+ }
+
+ if (pthread_create (&th, NULL, tf2, (void *) pthread_self ()) != 0)
+ {
+ puts ("2nd create failed");
+ return 1;
+ }
+
+#ifndef WAIT_IN_CHILD
+ wait_code ();
+#endif
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cannot cancel 2nd thread");
+ return 1;
+ }
+
+#ifdef WAIT_IN_CHILD
+ e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __func__);
+ return 1;
+ }
+#endif
+
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("cannot join 2nd thread");
+ return 1;
+ }
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("2nd thread not canceled");
+ return 1;
+ }
+
+ err = pthread_join (pthread_self (), NULL);
+ if (err == 0)
+ {
+ puts ("3rd circular join succeeded");
+ return 1;
+ }
+ if (err != EDEADLK)
+ {
+ printf ("3rd circular join %d, not EDEADLK\n", err);
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-join6.c
@@ -0,0 +1,2 @@
+#define WAIT_IN_CHILD 1
+#include "tst-join5.c"
--- /dev/null
+++ b/fbtl/tst-key1.c
@@ -0,0 +1,88 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <limits.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+int
+do_test (void)
+{
+ int max;
+#ifdef PTHREAD_KEYS_MAX
+ max = PTHREAD_KEYS_MAX;
+#else
+ max = _POSIX_THREAD_KEYS_MAX;
+#endif
+ pthread_key_t *keys = alloca (max * sizeof (pthread_key_t));
+
+ int i;
+ for (i = 0; i < max; ++i)
+ if (pthread_key_create (&keys[i], NULL) != 0)
+ {
+ write (2, "key_create failed\n", 18);
+ _exit (1);
+ }
+ else
+ {
+ printf ("created key %d\n", i);
+
+ if (pthread_setspecific (keys[i], (const void *) (i + 100l)) != 0)
+ {
+ write (2, "setspecific failed\n", 19);
+ _exit (1);
+ }
+ }
+
+ for (i = 0; i < max; ++i)
+ {
+ if (pthread_getspecific (keys[i]) != (void *) (i + 100l))
+ {
+ write (2, "getspecific failed\n", 19);
+ _exit (1);
+ }
+
+ if (pthread_key_delete (keys[i]) != 0)
+ {
+ write (2, "key_delete failed\n", 18);
+ _exit (1);
+ }
+ }
+
+ /* Now it must be once again possible to allocate keys. */
+ if (pthread_key_create (&keys[0], NULL) != 0)
+ {
+ write (2, "2nd key_create failed\n", 22);
+ _exit (1);
+ }
+
+ if (pthread_key_delete (keys[0]) != 0)
+ {
+ write (2, "2nd key_delete failed\n", 22);
+ _exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-key2.c
@@ -0,0 +1,114 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#define N 2
+
+
+static int cnt0;
+static void
+f0 (void *p)
+{
+ ++cnt0;
+}
+
+
+static int cnt1;
+static void
+f1 (void *p)
+{
+ ++cnt1;
+}
+
+
+static void (*fcts[N]) (void *) =
+{
+ f0,
+ f1
+};
+
+
+static void *
+tf (void *arg)
+{
+ pthread_key_t *key = (pthread_key_t *) arg;
+
+ if (pthread_setspecific (*key, (void *) -1l) != 0)
+ {
+ write (2, "setspecific failed\n", 19);
+ _exit (1);
+ }
+
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+ pthread_key_t keys[N];
+
+ int i;
+ for (i = 0; i < N; ++i)
+ if (pthread_key_create (&keys[i], fcts[i]) != 0)
+ {
+ write (2, "key_create failed\n", 18);
+ _exit (1);
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, &keys[1]) != 0)
+ {
+ write (2, "create failed\n", 14);
+ _exit (1);
+ }
+
+ if (pthread_join (th, NULL) != 0)
+ {
+ write (2, "join failed\n", 12);
+ _exit (1);
+ }
+
+ if (cnt0 != 0)
+ {
+ write (2, "cnt0 != 0\n", 10);
+ _exit (1);
+ }
+
+ if (cnt1 != 1)
+ {
+ write (2, "cnt1 != 1\n", 10);
+ _exit (1);
+ }
+
+ for (i = 0; i < N; ++i)
+ if (pthread_key_delete (keys[i]) != 0)
+ {
+ write (2, "key_delete failed\n", 18);
+ _exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-key3.c
@@ -0,0 +1,155 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#define N 2
+
+
+static int cnt0;
+static void
+f0 (void *p)
+{
+ ++cnt0;
+}
+
+
+static int cnt1;
+static void
+f1 (void *p)
+{
+ ++cnt1;
+}
+
+
+static void (*fcts[N]) (void *) =
+{
+ f0,
+ f1
+};
+
+
+static pthread_barrier_t b;
+
+
+static void *
+tf (void *arg)
+{
+ pthread_key_t *key = (pthread_key_t *) arg;
+
+ if (pthread_setspecific (*key, (void *) -1l) != 0)
+ {
+ write (2, "setspecific failed\n", 19);
+ _exit (1);
+ }
+
+ pthread_barrier_wait (&b);
+
+ const struct timespec t = { .tv_sec = 1000, .tv_nsec = 0 };
+ while (1)
+ nanosleep (&t, NULL);
+
+ /* NOTREACHED */
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+ pthread_key_t keys[N];
+
+ int i;
+ for (i = 0; i < N; ++i)
+ if (pthread_key_create (&keys[i], fcts[i]) != 0)
+ {
+ write (2, "key_create failed\n", 18);
+ _exit (1);
+ }
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ write (2, "barrier_init failed\n", 20);
+ _exit (1);
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, &keys[1]) != 0)
+ {
+ write (2, "create failed\n", 14);
+ _exit (1);
+ }
+
+ pthread_barrier_wait (&b);
+
+ if (pthread_cancel (th) != 0)
+ {
+ write (2, "cancel failed\n", 14);
+ _exit (1);
+ }
+
+ void *status;
+ if (pthread_join (th, &status) != 0)
+ {
+ write (2, "join failed\n", 12);
+ _exit (1);
+ }
+
+ if (status != PTHREAD_CANCELED)
+ {
+ write (2, "thread not canceled\n", 20);
+ _exit (1);
+ }
+
+ /* Note that the TSD destructors not necessarily have to have
+ finished by the time pthread_join returns. At least according to
+ POSIX. We implement the stronger requirement that they indeed
+ have run and therefore these tests succeed. */
+ if (cnt0 != 0)
+ {
+ write (2, "cnt0 != 0\n", 10);
+ _exit (1);
+ }
+
+ if (cnt1 != 1)
+ {
+ write (2, "cnt1 != 1\n", 10);
+ _exit (1);
+ }
+
+ for (i = 0; i < N; ++i)
+ if (pthread_key_delete (keys[i]) != 0)
+ {
+ write (2, "key_delete failed\n", 18);
+ _exit (1);
+ }
+
+ if (pthread_barrier_destroy (&b) != 0)
+ {
+ write (2, "barrier_destroy failed\n", 23);
+ _exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-key4.c
@@ -0,0 +1,136 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <limits.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+#ifdef PTHREAD_KEYS_MAX
+const int max = PTHREAD_KEYS_MAX;
+#else
+const int max = _POSIX_THREAD_KEYS_MAX;
+#endif
+static pthread_key_t *keys;
+
+
+static void *
+tf1 (void *arg)
+{
+ int i;
+ for (i = 0; i < max; ++i)
+ if (pthread_setspecific (keys[i], (void *) (long int) (i + 1)) != 0)
+ {
+ puts ("setspecific failed");
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+static void *
+tf2 (void *arg)
+{
+ int i;
+ for (i = 0; i < max; ++i)
+ if (pthread_getspecific (keys[i]) != NULL)
+ {
+ printf ("getspecific for key %d not NULL\n", i);
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ keys = alloca (max * sizeof (pthread_key_t));
+
+ int i;
+ for (i = 0; i < max; ++i)
+ if (pthread_key_create (&keys[i], NULL) != 0)
+ {
+ puts ("key_create failed");
+ exit (1);
+ }
+
+ pthread_attr_t a;
+
+ if (pthread_attr_init (&a) != 0)
+ {
+ puts ("attr_init failed");
+ exit (1);
+ }
+
+ if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+ for (i = 0; i < 10; ++i)
+ {
+ int j;
+#define N 2
+ pthread_t th[N];
+ for (j = 0; j < N; ++j)
+ if (pthread_create (&th[j], NULL, tf1, NULL) != 0)
+ {
+ puts ("1st create failed");
+ exit (1);
+ }
+
+ for (j = 0; j < N; ++j)
+ if (pthread_join (th[j], NULL) != 0)
+ {
+ puts ("1st join failed");
+ exit (1);
+ }
+
+ for (j = 0; j < N; ++j)
+ if (pthread_create (&th[j], NULL, tf2, NULL) != 0)
+ {
+ puts ("2nd create failed");
+ exit (1);
+ }
+
+ for (j = 0; j < N; ++j)
+ if (pthread_join (th[j], NULL) != 0)
+ {
+ puts ("2nd join failed");
+ exit (1);
+ }
+ }
+
+ if (pthread_attr_destroy (&a) != 0)
+ {
+ puts ("attr_destroy failed");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-kill1.c
@@ -0,0 +1,99 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+static pthread_barrier_t b;
+
+static void *
+tf (void *a)
+{
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("child: mutex_lock failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child: barrier_wait failed");
+ exit (1);
+ }
+
+ /* This call should never return. */
+ pthread_cond_wait (&c, &m);
+
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("mutex_lock failed");
+ exit (1);
+ }
+
+ /* Send the thread a signal which it doesn't catch and which will
+ cause the process to terminate. */
+ if (pthread_kill (th, SIGUSR1) != 0)
+ {
+ puts ("kill failed");
+ exit (1);
+ }
+
+ /* This call should never return. */
+ pthread_join (th, NULL);
+
+ return 0;
+}
+
+
+#define EXPECTED_SIGNAL SIGUSR1
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-kill2.c
@@ -0,0 +1,138 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+
+static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+static pthread_barrier_t b;
+
+static void *
+tf (void *a)
+{
+ /* Block SIGUSR1. */
+ sigset_t ss;
+
+ sigemptyset (&ss);
+ sigaddset (&ss, SIGUSR1);
+ if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+ {
+ puts ("child: sigmask failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("child: mutex_lock failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child: barrier_wait failed");
+ exit (1);
+ }
+
+ /* Compute timeout. */
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ /* Timeout: 1sec. */
+ ts.tv_sec += 1;
+
+ /* This call should never return. */
+ if (pthread_cond_timedwait (&c, &m, &ts) != ETIMEDOUT)
+ {
+ puts ("cond_timedwait didn't time out");
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("mutex_lock failed");
+ exit (1);
+ }
+
+ /* Send the thread a signal which it has blocked. */
+ if (pthread_kill (th, SIGUSR1) != 0)
+ {
+ puts ("kill failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&m) != 0)
+ {
+ puts ("mutex_unlock failed");
+ exit (1);
+ }
+
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+ if (r != NULL)
+ {
+ puts ("return value wrong");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TIMEOUT 5
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-kill3.c
@@ -0,0 +1,158 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+
+static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+static pthread_barrier_t b;
+
+
+static void
+handler (int sig)
+{
+ write (1, "handler called\n", 15);
+ _exit (1);
+}
+
+
+static void *
+tf (void *a)
+{
+ /* Block SIGUSR1. */
+ sigset_t ss;
+
+ sigemptyset (&ss);
+ sigaddset (&ss, SIGUSR1);
+ if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+ {
+ puts ("child: sigmask failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("child: mutex_lock failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child: barrier_wait failed");
+ exit (1);
+ }
+
+ /* Compute timeout. */
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ /* Timeout: 1sec. */
+ ts.tv_sec += 1;
+
+ /* This call should never return. */
+ if (pthread_cond_timedwait (&c, &m, &ts) != ETIMEDOUT)
+ {
+ puts ("cond_timedwait didn't time out");
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+ pthread_t th;
+
+ struct sigaction sa;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = handler;
+ if (sigaction (SIGUSR1, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ exit (1);
+ }
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("mutex_lock failed");
+ exit (1);
+ }
+
+ /* Send the thread a signal which it has blocked. */
+ if (pthread_kill (th, SIGUSR1) != 0)
+ {
+ puts ("kill failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&m) != 0)
+ {
+ puts ("mutex_unlock failed");
+ exit (1);
+ }
+
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+ if (r != NULL)
+ {
+ puts ("return value wrong");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TIMEOUT 5
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-kill4.c
@@ -0,0 +1,90 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static void *
+tf (void *a)
+{
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+ pthread_attr_t at;
+ if (pthread_attr_init (&at) != 0)
+ {
+ puts ("attr_create failed");
+ exit (1);
+ }
+
+ /* Limit thread stack size, because if it is too large, pthread_join
+ will free it immediately rather than put it into stack cache. */
+ if (pthread_attr_setstacksize (&at, 2 * 1024 * 1024) != 0)
+ {
+ puts ("setstacksize failed");
+ exit (1);
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, &at, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ pthread_attr_destroy (&at);
+
+ if (pthread_join (th, NULL) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ /* The following only works because we assume here something about
+ the implementation. Namely, that the memory allocated for the
+ thread descriptor is not going away, that the TID field is
+ cleared and therefore the signal is sent to process 0, and that
+ we can savely assume there is no other process with this ID at
+ that time. */
+ int e = pthread_kill (th, 0);
+ if (e == 0)
+ {
+ puts ("pthread_kill succeeded");
+ exit (1);
+ }
+ if (e != ESRCH)
+ {
+ puts ("pthread_kill didn't return ESRCH");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-kill5.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+int
+do_test (void)
+{
+ /* XXX This test might require architecture and system specific changes.
+ There is no guarantee that this signal number is invalid. */
+ int e = pthread_kill (pthread_self (), SIGRTMAX + 10);
+ if (e == 0)
+ {
+ puts ("kill didn't failed");
+ exit (1);
+ }
+ if (e != EINVAL)
+ {
+ puts ("error not EINVAL");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-kill6.c
@@ -0,0 +1,161 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static pthread_t receiver;
+static sem_t sem;
+static pthread_barrier_t b;
+
+static void
+handler (int sig)
+{
+ if (sig != SIGUSR1)
+ {
+ write (STDOUT_FILENO, "wrong signal\n", 13);
+ _exit (1);
+ }
+
+ if (pthread_self () != receiver)
+ {
+ write (STDOUT_FILENO, "not the intended receiver\n", 26);
+ _exit (1);
+ }
+
+ if (sem_post (&sem) != 0)
+ {
+ write (STDOUT_FILENO, "sem_post failed\n", 16);
+ _exit (1);
+ }
+}
+
+
+static void *
+tf (void *a)
+{
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child: barrier_wait failed");
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+ struct sigaction sa;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = handler;
+ if (sigaction (SIGUSR1, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ exit (1);
+ }
+
+#define N 20
+
+ if (pthread_barrier_init (&b, NULL, N + 1) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ pthread_attr_t a;
+
+ if (pthread_attr_init (&a) != 0)
+ {
+ puts ("attr_init failed");
+ exit (1);
+ }
+
+ if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+ pthread_t th[N];
+ int i;
+ for (i = 0; i < N; ++i)
+ if (pthread_create (&th[i], &a, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ if (pthread_attr_destroy (&a) != 0)
+ {
+ puts ("attr_destroy failed");
+ exit (1);
+ }
+
+ if (sem_init (&sem, 0, 0) != 0)
+ {
+ puts ("sem_init failed");
+ exit (1);
+ }
+
+ for (i = 0; i < N * 10; ++i)
+ {
+ receiver = th[i % N];
+
+ if (pthread_kill (receiver, SIGUSR1) != 0)
+ {
+ puts ("kill failed");
+ exit (1);
+ }
+
+ if (TEMP_FAILURE_RETRY (sem_wait (&sem)) != 0)
+ {
+ puts ("sem_wait failed");
+ exit (1);
+ }
+ }
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ for (i = 0; i < N; ++i)
+ if (pthread_join (th[i], NULL) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-locale1.c
@@ -0,0 +1,18 @@
+/* Test that the thread-local locale works right in the main thread
+ when statically linked. */
+
+#include "../locale/tst-C-locale.c"
+
+#include <pthread.h>
+#include <signal.h>
+
+/* This is never called, just here to get pthreads linked in. */
+int
+useless (void)
+{
+ pthread_t th;
+ pthread_create (&th, 0, (void *(*) (void *)) useless, 0);
+ /* This is to check __libc_current_sigrt* can be used in statically
+ linked apps. */
+ return SIGRTMIN;
+}
--- /dev/null
+++ b/fbtl/tst-locale2.c
@@ -0,0 +1,15 @@
+/* Test that the thread-local locale works right in the main thread
+ when statically linked. */
+
+#include "../argp/tst-argp1.c"
+
+#include <pthread.h>
+
+/* This is never called, just here to get pthreads linked in. */
+void *
+useless (void *a)
+{
+ pthread_t th;
+ pthread_create (&th, 0, useless, a);
+ return NULL;
+}
--- /dev/null
+++ b/fbtl/tst-mutex1.c
@@ -0,0 +1,76 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <errno.h>
+
+
+#ifndef ATTR
+# define ATTR NULL
+#endif
+
+
+static int
+do_test (void)
+{
+ pthread_mutex_t m;
+
+ int e = pthread_mutex_init (&m, ATTR);
+ if (ATTR != NULL && e == ENOTSUP)
+ {
+ puts ("cannot support selected type of mutexes");
+ return 0;
+ }
+ else if (e != 0)
+ {
+ puts ("mutex_init failed");
+ return 1;
+ }
+
+ if (ATTR != NULL && pthread_mutexattr_destroy (ATTR) != 0)
+ {
+ puts ("mutexattr_destroy failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("mutex_lock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_unlock (&m) != 0)
+ {
+ puts ("mutex_unlock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_destroy (&m) != 0)
+ {
+ puts ("mutex_destroy failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+#ifndef TEST_FUNCTION
+# define TEST_FUNCTION do_test ()
+#endif
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-mutex2.c
@@ -0,0 +1,241 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_mutex_t m;
+static pthread_barrier_t b;
+
+
+static void *
+tf (void *arg)
+{
+ int e = pthread_mutex_unlock (&m);
+ if (e == 0)
+ {
+ puts ("child: 1st mutex_unlock succeeded");
+ exit (1);
+ }
+ else if (e != EPERM)
+ {
+ puts ("child: 1st mutex_unlock error != EPERM");
+ exit (1);
+ }
+
+ e = pthread_mutex_trylock (&m);
+ if (e == 0)
+ {
+ puts ("child: 1st trylock suceeded");
+ exit (1);
+ }
+ if (e != EBUSY)
+ {
+ puts ("child: 1st trylock didn't return EBUSY");
+ exit (1);
+ }
+
+ e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child: 1st barrier_wait failed");
+ exit (1);
+ }
+
+ e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child: 2nd barrier_wait failed");
+ exit (1);
+ }
+
+ e = pthread_mutex_unlock (&m);
+ if (e == 0)
+ {
+ puts ("child: 2nd mutex_unlock succeeded");
+ exit (1);
+ }
+ else if (e != EPERM)
+ {
+ puts ("child: 2nd mutex_unlock error != EPERM");
+ exit (1);
+ }
+
+ if (pthread_mutex_trylock (&m) != 0)
+ {
+ puts ("child: 2nd trylock failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&m) != 0)
+ {
+ puts ("child: 3rd mutex_unlock failed");
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_mutexattr_t a;
+ int e;
+
+ if (pthread_mutexattr_init (&a) != 0)
+ {
+ puts ("mutexattr_init failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_settype (&a, PTHREAD_MUTEX_ERRORCHECK) != 0)
+ {
+ puts ("mutexattr_settype failed");
+ return 1;
+ }
+
+#ifdef ENABLE_PI
+ if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
+ {
+ puts ("pthread_mutexattr_setprotocol failed");
+ return 1;
+ }
+#endif
+
+ e = pthread_mutex_init (&m, &a);
+ if (e != 0)
+ {
+#ifdef ENABLE_PI
+ if (e == ENOTSUP)
+ {
+ puts ("PI mutexes unsupported");
+ return 0;
+ }
+#endif
+ puts ("mutex_init failed");
+ return 1;
+ }
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ e = pthread_mutex_unlock (&m);
+ if (e == 0)
+ {
+ puts ("1st mutex_unlock succeeded");
+ return 1;
+ }
+ else if (e != EPERM)
+ {
+ puts ("1st mutex_unlock error != EPERM");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("mutex_lock failed");
+ return 1;
+ }
+
+ e = pthread_mutex_lock (&m);
+ if (e == 0)
+ {
+ puts ("2nd mutex_lock succeeded");
+ return 1;
+ }
+ else if (e != EDEADLK)
+ {
+ puts ("2nd mutex_lock error != EDEADLK");
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("1st barrier_wait failed");
+ return 1;
+ }
+
+ if (pthread_mutex_unlock (&m) != 0)
+ {
+ puts ("2nd mutex_unlock failed");
+ return 1;
+ }
+
+ e = pthread_mutex_unlock (&m);
+ if (e == 0)
+ {
+ puts ("3rd mutex_unlock succeeded");
+ return 1;
+ }
+ else if (e != EPERM)
+ {
+ puts ("3rd mutex_unlock error != EPERM");
+ return 1;
+ }
+
+ e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("2nd barrier_wait failed");
+ return 1;
+ }
+
+ if (pthread_join (th, NULL) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ if (pthread_mutex_destroy (&m) != 0)
+ {
+ puts ("mutex_destroy failed");
+ return 1;
+ }
+
+ if (pthread_barrier_destroy (&b) != 0)
+ {
+ puts ("barrier_destroy failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_destroy (&a) != 0)
+ {
+ puts ("mutexattr_destroy failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-mutex3.c
@@ -0,0 +1,241 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_mutex_t m;
+static pthread_barrier_t b;
+
+
+static void *
+tf (void *arg)
+{
+ int e = pthread_mutex_unlock (&m);
+ if (e == 0)
+ {
+ puts ("1st mutex_unlock in child succeeded");
+ exit (1);
+ }
+ if (e != EPERM)
+ {
+ puts ("1st mutex_unlock in child didn't return EPERM");
+ exit (1);
+ }
+
+ e = pthread_mutex_trylock (&m);
+ if (e == 0)
+ {
+ puts ("mutex_trylock in second thread succeeded");
+ exit (1);
+ }
+ if (e != EBUSY)
+ {
+ puts ("mutex_trylock returned wrong value");
+ exit (1);
+ }
+
+ e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ e = pthread_mutex_unlock (&m);
+ if (e == 0)
+ {
+ puts ("2nd mutex_unlock in child succeeded");
+ exit (1);
+ }
+ if (e != EPERM)
+ {
+ puts ("2nd mutex_unlock in child didn't return EPERM");
+ exit (1);
+ }
+
+ if (pthread_mutex_trylock (&m) != 0)
+ {
+ puts ("2nd mutex_trylock in second thread failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&m) != 0)
+ {
+ puts ("3rd mutex_unlock in second thread failed");
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_mutexattr_t a;
+
+ if (pthread_mutexattr_init (&a) != 0)
+ {
+ puts ("mutexattr_init failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_settype (&a, PTHREAD_MUTEX_RECURSIVE) != 0)
+ {
+ puts ("mutexattr_settype failed");
+ return 1;
+ }
+
+#ifdef ENABLE_PI
+ if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
+ {
+ puts ("pthread_mutexattr_setprotocol failed");
+ return 1;
+ }
+#endif
+
+ int e;
+ e = pthread_mutex_init (&m, &a);
+ if (e != 0)
+ {
+#ifdef ENABLE_PI
+ if (e == ENOTSUP)
+ {
+ puts ("PI mutexes unsupported");
+ return 0;
+ }
+#endif
+ puts ("mutex_init failed");
+ return 1;
+ }
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("mutex_lock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("2nd mutex_lock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_trylock (&m) != 0)
+ {
+ puts ("1st trylock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_unlock (&m) != 0)
+ {
+ puts ("mutex_unlock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_unlock (&m) != 0)
+ {
+ puts ("2nd mutex_unlock failed");
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ return 1;
+ }
+
+ if (pthread_mutex_unlock (&m) != 0)
+ {
+ puts ("3rd mutex_unlock failed");
+ return 1;
+ }
+
+ e = pthread_mutex_unlock (&m);
+ if (e == 0)
+ {
+ puts ("4th mutex_unlock succeeded");
+ return 1;
+ }
+ if (e != EPERM)
+ {
+ puts ("4th mutex_unlock didn't return EPERM");
+ return 1;
+ }
+
+ e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ return 1;
+ }
+
+ if (pthread_join (th, NULL) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ if (pthread_barrier_destroy (&b) != 0)
+ {
+ puts ("barrier_destroy failed");
+ return 1;
+ }
+
+ if (pthread_mutex_destroy (&m) != 0)
+ {
+ puts ("mutex_destroy failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_destroy (&a) != 0)
+ {
+ puts ("mutexattr_destroy failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-mutex4.c
@@ -0,0 +1,277 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+
+static int
+do_test (void)
+{
+ size_t ps = sysconf (_SC_PAGESIZE);
+ char tmpfname[] = "/tmp/tst-mutex4.XXXXXX";
+ char data[ps];
+ void *mem;
+ int fd;
+ pthread_mutex_t *m;
+ pthread_mutexattr_t a;
+ pid_t pid;
+ char *p;
+ int err;
+ int s;
+ pthread_barrier_t *b;
+ pthread_barrierattr_t ba;
+
+ fd = mkstemp (tmpfname);
+ if (fd == -1)
+ {
+ printf ("cannot open temporary file: %m\n");
+ return 1;
+ }
+
+ /* Make sure it is always removed. */
+ unlink (tmpfname);
+
+ /* Create one page of data. */
+ memset (data, '\0', ps);
+
+ /* Write the data to the file. */
+ if (write (fd, data, ps) != (ssize_t) ps)
+ {
+ puts ("short write");
+ return 1;
+ }
+
+ mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (mem == MAP_FAILED)
+ {
+ printf ("mmap failed: %m\n");
+ return 1;
+ }
+
+ m = (pthread_mutex_t *) (((uintptr_t) mem + __alignof (pthread_mutex_t) - 1)
+ & ~(__alignof (pthread_mutex_t) - 1));
+ b = (pthread_barrier_t *) (((uintptr_t) (m + 1)
+ + __alignof (pthread_barrier_t) - 1)
+ & ~(__alignof (pthread_barrier_t) - 1));
+ p = (char *) (b + 1);
+
+ if (pthread_mutexattr_init (&a) != 0)
+ {
+ puts ("mutexattr_init failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_getpshared (&a, &s) != 0)
+ {
+ puts ("1st mutexattr_getpshared failed");
+ return 1;
+ }
+
+ if (s != PTHREAD_PROCESS_PRIVATE)
+ {
+ puts ("default pshared value wrong");
+ return 1;
+ }
+
+ if (pthread_mutexattr_setpshared (&a, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("mutexattr_setpshared failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_getpshared (&a, &s) != 0)
+ {
+ puts ("2nd mutexattr_getpshared failed");
+ return 1;
+ }
+
+ if (s != PTHREAD_PROCESS_SHARED)
+ {
+ puts ("pshared value after setpshared call wrong");
+ return 1;
+ }
+
+#ifdef ENABLE_PI
+ if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
+ {
+ puts ("pthread_mutexattr_setprotocol failed");
+ return 1;
+ }
+#endif
+
+ if ((err = pthread_mutex_init (m, &a)) != 0)
+ {
+#ifdef ENABLE_PI
+ if (err == ENOTSUP)
+ {
+ puts ("PI mutexes unsupported");
+ return 0;
+ }
+#endif
+ puts ("mutex_init failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (m) != 0)
+ {
+ puts ("mutex_lock failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_destroy (&a) != 0)
+ {
+ puts ("mutexattr_destroy failed");
+ return 1;
+ }
+
+ if (pthread_barrierattr_init (&ba) != 0)
+ {
+ puts ("barrierattr_init failed");
+ return 1;
+ }
+
+ if (pthread_barrierattr_setpshared (&ba, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("barrierattr_setpshared failed");
+ return 1;
+ }
+
+ if (pthread_barrier_init (b, &ba, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ if (pthread_barrierattr_destroy (&ba) != 0)
+ {
+ puts ("barrierattr_destroy failed");
+ return 1;
+ }
+
+ err = pthread_mutex_trylock (m);
+ if (err == 0)
+ {
+ puts ("mutex_trylock succeeded");
+ return 1;
+ }
+ else if (err != EBUSY)
+ {
+ puts ("mutex_trylock didn't return EBUSY");
+ return 1;
+ }
+
+ *p = 0;
+
+ if (pthread_mutex_unlock (m) != 0)
+ {
+ puts ("parent: 1st mutex_unlock failed");
+ return 1;
+ }
+
+ puts ("going to fork now");
+ pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ return 1;
+ }
+ else if (pid == 0)
+ {
+ if (pthread_mutex_lock (m) != 0)
+ {
+ puts ("child: mutex_lock failed");
+ return 1;
+ }
+
+ int e = pthread_barrier_wait (b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child: barrier_wait failed");
+ return 1;
+ }
+
+ if ((*p)++ != 0)
+ {
+ puts ("child: *p != 0");
+ return 1;
+ }
+
+ if (pthread_mutex_unlock (m) != 0)
+ {
+ puts ("child: mutex_unlock failed");
+ return 1;
+ }
+
+ puts ("child done");
+ }
+ else
+ {
+ int e = pthread_barrier_wait (b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("parent: barrier_wait failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (m) != 0)
+ {
+ puts ("parent: 2nd mutex_lock failed");
+ return 1;
+ }
+
+ if (*p != 1)
+ {
+ puts ("*p != 1");
+ return 1;
+ }
+
+ if (pthread_mutex_unlock (m) != 0)
+ {
+ puts ("parent: 2nd mutex_unlock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_destroy (m) != 0)
+ {
+ puts ("mutex_destroy failed");
+ return 1;
+ }
+
+ if (pthread_barrier_destroy (b) != 0)
+ {
+ puts ("barrier_destroy failed");
+ return 1;
+ }
+
+ puts ("parent done");
+ }
+
+ return 0;
+}
+
+#define TIMEOUT 4
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-mutex5.c
@@ -0,0 +1,201 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+
+#ifndef TYPE
+# define TYPE PTHREAD_MUTEX_NORMAL
+#endif
+
+
+static int
+do_test (void)
+{
+ pthread_mutex_t m;
+ struct timespec ts;
+ struct timeval tv;
+ struct timeval tv2;
+ int err;
+ pthread_mutexattr_t a;
+
+ if (pthread_mutexattr_init (&a) != 0)
+ {
+ puts ("mutexattr_init failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_settype (&a, TYPE) != 0)
+ {
+ puts ("mutexattr_settype failed");
+ return 1;
+ }
+
+#ifdef ENABLE_PI
+ if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
+ {
+ puts ("pthread_mutexattr_setprotocol failed");
+ return 1;
+ }
+#endif
+
+ err = pthread_mutex_init (&m, &a);
+ if (err != 0)
+ {
+#ifdef ENABLE_PI
+ if (err == ENOTSUP)
+ {
+ puts ("PI mutexes unsupported");
+ return 0;
+ }
+#endif
+ puts ("mutex_init failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_destroy (&a) != 0)
+ {
+ puts ("mutexattr_destroy failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("mutex_lock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_trylock (&m) == 0)
+ {
+ puts ("mutex_trylock succeeded");
+ return 1;
+ }
+
+ gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+ ts.tv_sec += 2; /* Wait 2 seconds. */
+
+ err = pthread_mutex_timedlock (&m, &ts);
+ if (err == 0)
+ {
+ puts ("timedlock succeeded");
+ return 1;
+ }
+ else if (err != ETIMEDOUT)
+ {
+ printf ("timedlock error != ETIMEDOUT: %d\n", err);
+ return 1;
+ }
+ else
+ {
+ int clk_tck = sysconf (_SC_CLK_TCK);
+
+ gettimeofday (&tv2, NULL);
+
+ tv2.tv_sec -= tv.tv_sec;
+ tv2.tv_usec -= tv.tv_usec;
+ if (tv2.tv_usec < 0)
+ {
+ tv2.tv_usec += 1000000;
+ tv2.tv_sec -= 1;
+ }
+
+ /* Be a bit tolerant, add one CLK_TCK. */
+ tv2.tv_usec += 1000000 / clk_tck;
+ if (tv2.tv_usec >= 1000000)
+ {
+ tv2.tv_usec -= 1000000;
+ ++tv2.tv_sec;
+ }
+
+ if (tv2.tv_sec < 2)
+ {
+ printf ("premature timeout: %ld.%06ld difference\n",
+ tv2.tv_sec, tv2.tv_usec);
+ return 1;
+ }
+ }
+
+ (void) gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+ ts.tv_sec += 2; /* Wait 2 seconds. */
+ /* The following makes the ts value invalid. */
+ ts.tv_nsec += 1000000000;
+
+ err = pthread_mutex_timedlock (&m, &ts);
+ if (err == 0)
+ {
+ puts ("2nd timedlock succeeded");
+ return 1;
+ }
+ else if (err != EINVAL)
+ {
+ printf ("2nd timedlock error != EINVAL: %d\n", err);
+ return 1;
+ }
+
+ if (pthread_mutex_unlock (&m) != 0)
+ {
+ puts ("mutex_unlock failed");
+ return 1;
+ }
+
+ (void) gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+ ts.tv_sec += 2; /* Wait 2 seconds. */
+ if (pthread_mutex_timedlock (&m, &ts) != 0)
+ {
+ puts ("3rd timedlock failed");
+ }
+
+ (void) gettimeofday (&tv2, NULL);
+
+ /* Check that timedlock didn't delay. We use a limit of 0.1 secs. */
+ timersub (&tv2, &tv, &tv2);
+ if (tv2.tv_sec > 0 || tv2.tv_usec > 100000)
+ {
+ puts ("3rd timedlock didn't return right away");
+ return 1;
+ }
+
+ if (pthread_mutex_unlock (&m) != 0)
+ {
+ puts ("final mutex_unlock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_destroy (&m) != 0)
+ {
+ puts ("mutex_destroy failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TIMEOUT 4
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-mutex5a.c
@@ -0,0 +1,2 @@
+#define TYPE PTHREAD_MUTEX_ADAPTIVE_NP
+#include "tst-mutex5.c"
--- /dev/null
+++ b/fbtl/tst-mutex6.c
@@ -0,0 +1,72 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#ifndef TEST_FUNCTION
+static int do_test (void);
+# define TEST_FUNCTION do_test ()
+#endif
+#include "../test-skeleton.c"
+
+#ifndef ATTR
+pthread_mutexattr_t *attr;
+# define ATTR attr
+#endif
+
+
+static int
+do_test (void)
+{
+ pthread_mutex_t m;
+
+ int e = pthread_mutex_init (&m, ATTR);
+ if (ATTR != NULL && e == ENOTSUP)
+ {
+ puts ("cannot support selected type of mutexes");
+ e = pthread_mutex_init (&m, NULL);
+ }
+ if (e != 0)
+ {
+ puts ("mutex_init failed");
+ return 1;
+ }
+
+ if (ATTR != NULL && pthread_mutexattr_destroy (ATTR) != 0)
+ {
+ puts ("mutexattr_destroy failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("1st mutex_lock failed");
+ return 1;
+ }
+
+ delayed_exit (1);
+ /* This call should never return. */
+ xpthread_mutex_lock (&m);
+
+ puts ("2nd mutex_lock returned");
+ return 1;
+}
--- /dev/null
+++ b/fbtl/tst-mutex7.c
@@ -0,0 +1,164 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+
+#ifndef TYPE
+# define TYPE PTHREAD_MUTEX_DEFAULT
+#endif
+
+
+static pthread_mutex_t lock;
+
+
+#define ROUNDS 1000
+#define N 100
+
+
+static void *
+tf (void *arg)
+{
+ int nr = (long int) arg;
+ int cnt;
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 11000 };
+
+ for (cnt = 0; cnt < ROUNDS; ++cnt)
+ {
+ if (pthread_mutex_lock (&lock) != 0)
+ {
+ printf ("thread %d: failed to get the lock\n", nr);
+ return (void *) 1l;
+ }
+
+ if (pthread_mutex_unlock (&lock) != 0)
+ {
+ printf ("thread %d: failed to release the lock\n", nr);
+ return (void *) 1l;
+ }
+
+ nanosleep (&ts, NULL);
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_mutexattr_t a;
+
+ if (pthread_mutexattr_init (&a) != 0)
+ {
+ puts ("mutexattr_init failed");
+ exit (1);
+ }
+
+ if (pthread_mutexattr_settype (&a, TYPE) != 0)
+ {
+ puts ("mutexattr_settype failed");
+ exit (1);
+ }
+
+#ifdef ENABLE_PI
+ if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
+ {
+ puts ("pthread_mutexattr_setprotocol failed");
+ return 1;
+ }
+#endif
+
+ int e = pthread_mutex_init (&lock, &a);
+ if (e != 0)
+ {
+#ifdef ENABLE_PI
+ if (e == ENOTSUP)
+ {
+ puts ("PI mutexes unsupported");
+ return 0;
+ }
+#endif
+ puts ("mutex_init failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_destroy (&a) != 0)
+ {
+ puts ("mutexattr_destroy failed");
+ return 1;
+ }
+
+ pthread_attr_t at;
+ pthread_t th[N];
+ int cnt;
+
+ if (pthread_attr_init (&at) != 0)
+ {
+ puts ("attr_init failed");
+ return 1;
+ }
+
+ if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&lock) != 0)
+ {
+ puts ("locking in parent failed");
+ return 1;
+ }
+
+ for (cnt = 0; cnt < N; ++cnt)
+ if (pthread_create (&th[cnt], &at, tf, (void *) (long int) cnt) != 0)
+ {
+ printf ("creating thread %d failed\n", cnt);
+ return 1;
+ }
+
+ if (pthread_attr_destroy (&at) != 0)
+ {
+ puts ("attr_destroy failed");
+ return 1;
+ }
+
+ if (pthread_mutex_unlock (&lock) != 0)
+ {
+ puts ("unlocking in parent failed");
+ return 1;
+ }
+
+ for (cnt = 0; cnt < N; ++cnt)
+ if (pthread_join (th[cnt], NULL) != 0)
+ {
+ printf ("joining thread %d failed\n", cnt);
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TIMEOUT 60
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-mutex7a.c
@@ -0,0 +1,2 @@
+#define TYPE PTHREAD_MUTEX_ADAPTIVE_NP
+#include "tst-mutex7.c"
--- /dev/null
+++ b/fbtl/tst-mutex8-static.c
@@ -0,0 +1 @@
+#include "tst-mutex8.c"
--- /dev/null
+++ b/fbtl/tst-mutex8.c
@@ -0,0 +1,380 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* This test checks behavior not required by POSIX. */
+#include <errno.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_mutex_t *m;
+static pthread_barrier_t b;
+static pthread_cond_t c;
+static bool done;
+
+
+static void
+cl (void *arg)
+{
+ if (pthread_mutex_unlock (m) != 0)
+ {
+ puts ("cl: mutex_unlocked failed");
+ exit (1);
+ }
+}
+
+
+static void *
+tf (void *arg)
+{
+ if (pthread_mutex_lock (m) != 0)
+ {
+ puts ("tf: mutex_lock failed");
+ return (void *) 1l;
+ }
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ return (void *) 1l;
+ }
+
+ if (arg == NULL)
+ do
+ if (pthread_cond_wait (&c, m) != 0)
+ {
+ puts ("tf: cond_wait failed");
+ return (void *) 1l;
+ }
+ while (! done);
+ else
+ do
+ {
+ pthread_cleanup_push (cl, NULL);
+
+ if (pthread_cond_wait (&c, m) != 0)
+ {
+ puts ("tf: cond_wait failed");
+ return (void *) 1l;
+ }
+
+ pthread_cleanup_pop (0);
+ }
+ while (! done);
+
+ if (pthread_mutex_unlock (m) != 0)
+ {
+ puts ("tf: mutex_unlock failed");
+ return (void *) 1l;
+ }
+
+ return NULL;
+}
+
+
+static int
+check_type (const char *mas, pthread_mutexattr_t *ma)
+{
+ if (pthread_mutex_init (m, ma) != 0)
+ {
+ printf ("1st mutex_init failed for %s\n", mas);
+ return 1;
+ }
+
+ if (pthread_mutex_destroy (m) != 0)
+ {
+ printf ("immediate mutex_destroy failed for %s\n", mas);
+ return 1;
+ }
+
+ if (pthread_mutex_init (m, ma) != 0)
+ {
+ printf ("2nd mutex_init failed for %s\n", mas);
+ return 1;
+ }
+
+ if (pthread_mutex_lock (m) != 0)
+ {
+ printf ("1st mutex_lock failed for %s\n", mas);
+ return 1;
+ }
+
+ int e = pthread_mutex_destroy (m);
+ if (e == 0)
+ {
+ printf ("mutex_destroy of self-locked mutex succeeded for %s\n", mas);
+ return 1;
+ }
+ if (e != EBUSY)
+ {
+ printf ("mutex_destroy of self-locked mutex did not return EBUSY %s\n",
+ mas);
+ return 1;
+ }
+
+ if (pthread_mutex_unlock (m) != 0)
+ {
+ printf ("1st mutex_unlock failed for %s\n", mas);
+ return 1;
+ }
+
+ if (pthread_mutex_trylock (m) != 0)
+ {
+ printf ("mutex_trylock failed for %s\n", mas);
+ return 1;
+ }
+
+ e = pthread_mutex_destroy (m);
+ if (e == 0)
+ {
+ printf ("mutex_destroy of self-trylocked mutex succeeded for %s\n", mas);
+ return 1;
+ }
+ if (e != EBUSY)
+ {
+ printf ("\
+mutex_destroy of self-trylocked mutex did not return EBUSY %s\n",
+ mas);
+ return 1;
+ }
+
+ if (pthread_mutex_unlock (m) != 0)
+ {
+ printf ("2nd mutex_unlock failed for %s\n", mas);
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("1st create failed");
+ return 1;
+ }
+ done = false;
+
+ e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("1st barrier_wait failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (m) != 0)
+ {
+ printf ("2nd mutex_lock failed for %s\n", mas);
+ return 1;
+ }
+
+ if (pthread_mutex_unlock (m) != 0)
+ {
+ printf ("3rd mutex_unlock failed for %s\n", mas);
+ return 1;
+ }
+
+ e = pthread_mutex_destroy (m);
+ if (e == 0)
+ {
+ printf ("mutex_destroy of condvar-used mutex succeeded for %s\n", mas);
+ return 1;
+ }
+ if (e != EBUSY)
+ {
+ printf ("\
+mutex_destroy of condvar-used mutex did not return EBUSY for %s\n", mas);
+ return 1;
+ }
+
+ done = true;
+ if (pthread_cond_signal (&c) != 0)
+ {
+ puts ("cond_signal failed");
+ return 1;
+ }
+
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+ if (r != NULL)
+ {
+ puts ("thread didn't return NULL");
+ return 1;
+ }
+
+ if (pthread_mutex_destroy (m) != 0)
+ {
+ printf ("mutex_destroy after condvar-use failed for %s\n", mas);
+ return 1;
+ }
+
+ if (pthread_mutex_init (m, ma) != 0)
+ {
+ printf ("3rd mutex_init failed for %s\n", mas);
+ return 1;
+ }
+
+ if (pthread_create (&th, NULL, tf, (void *) 1) != 0)
+ {
+ puts ("2nd create failed");
+ return 1;
+ }
+ done = false;
+
+ e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("2nd barrier_wait failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (m) != 0)
+ {
+ printf ("3rd mutex_lock failed for %s\n", mas);
+ return 1;
+ }
+
+ if (pthread_mutex_unlock (m) != 0)
+ {
+ printf ("4th mutex_unlock failed for %s\n", mas);
+ return 1;
+ }
+
+ e = pthread_mutex_destroy (m);
+ if (e == 0)
+ {
+ printf ("2nd mutex_destroy of condvar-used mutex succeeded for %s\n",
+ mas);
+ return 1;
+ }
+ if (e != EBUSY)
+ {
+ printf ("\
+2nd mutex_destroy of condvar-used mutex did not return EBUSY for %s\n",
+ mas);
+ return 1;
+ }
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cond_cancel failed");
+ return 1;
+ }
+
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("thread not canceled");
+ return 1;
+ }
+
+ if (pthread_mutex_destroy (m) != 0)
+ {
+ printf ("mutex_destroy after condvar-canceled failed for %s\n", mas);
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_mutex_t mm;
+ m = &mm;
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ if (pthread_cond_init (&c, NULL) != 0)
+ {
+ puts ("cond_init failed");
+ return 1;
+ }
+
+ puts ("check normal mutex");
+ int res = check_type ("normal", NULL);
+
+ pthread_mutexattr_t ma;
+ if (pthread_mutexattr_init (&ma) != 0)
+ {
+ puts ("1st mutexattr_init failed");
+ return 1;
+ }
+ if (pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_RECURSIVE) != 0)
+ {
+ puts ("1st mutexattr_settype failed");
+ return 1;
+ }
+#ifdef ENABLE_PI
+ if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT))
+ {
+ puts ("1st pthread_mutexattr_setprotocol failed");
+ return 1;
+ }
+#endif
+ puts ("check recursive mutex");
+ res |= check_type ("recursive", &ma);
+ if (pthread_mutexattr_destroy (&ma) != 0)
+ {
+ puts ("1st mutexattr_destroy failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_init (&ma) != 0)
+ {
+ puts ("2nd mutexattr_init failed");
+ return 1;
+ }
+ if (pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_ERRORCHECK) != 0)
+ {
+ puts ("2nd mutexattr_settype failed");
+ return 1;
+ }
+#ifdef ENABLE_PI
+ if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT))
+ {
+ puts ("2nd pthread_mutexattr_setprotocol failed");
+ return 1;
+ }
+#endif
+ puts ("check error-checking mutex");
+ res |= check_type ("error-checking", &ma);
+ if (pthread_mutexattr_destroy (&ma) != 0)
+ {
+ puts ("2nd mutexattr_destroy failed");
+ return 1;
+ }
+
+ return res;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-mutex9.c
@@ -0,0 +1,202 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+
+
+static int
+do_test (void)
+{
+ size_t ps = sysconf (_SC_PAGESIZE);
+ char tmpfname[] = "/tmp/tst-mutex9.XXXXXX";
+ char data[ps];
+ void *mem;
+ int fd;
+ pthread_mutex_t *m;
+ pthread_mutexattr_t a;
+ pid_t pid;
+
+ fd = mkstemp (tmpfname);
+ if (fd == -1)
+ {
+ printf ("cannot open temporary file: %m\n");
+ return 1;
+ }
+
+ /* Make sure it is always removed. */
+ unlink (tmpfname);
+
+ /* Create one page of data. */
+ memset (data, '\0', ps);
+
+ /* Write the data to the file. */
+ if (write (fd, data, ps) != (ssize_t) ps)
+ {
+ puts ("short write");
+ return 1;
+ }
+
+ mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (mem == MAP_FAILED)
+ {
+ printf ("mmap failed: %m\n");
+ return 1;
+ }
+
+ m = (pthread_mutex_t *) (((uintptr_t) mem + __alignof (pthread_mutex_t))
+ & ~(__alignof (pthread_mutex_t) - 1));
+
+ if (pthread_mutexattr_init (&a) != 0)
+ {
+ puts ("mutexattr_init failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_setpshared (&a, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("mutexattr_setpshared failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_settype (&a, PTHREAD_MUTEX_RECURSIVE) != 0)
+ {
+ puts ("mutexattr_settype failed");
+ return 1;
+ }
+
+#ifdef ENABLE_PI
+ if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
+ {
+ puts ("pthread_mutexattr_setprotocol failed");
+ return 1;
+ }
+#endif
+
+ int e;
+ if ((e = pthread_mutex_init (m, &a)) != 0)
+ {
+#ifdef ENABLE_PI
+ if (e == ENOTSUP)
+ {
+ puts ("PI mutexes unsupported");
+ return 0;
+ }
+#endif
+ puts ("mutex_init failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (m) != 0)
+ {
+ puts ("mutex_lock failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_destroy (&a) != 0)
+ {
+ puts ("mutexattr_destroy failed");
+ return 1;
+ }
+
+ puts ("going to fork now");
+ pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ return 1;
+ }
+ else if (pid == 0)
+ {
+ if (pthread_mutex_trylock (m) == 0)
+ {
+ puts ("child: mutex_trylock succeeded");
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (m) == 0)
+ {
+ puts ("child: mutex_unlock succeeded");
+ exit (1);
+ }
+
+ struct timeval tv;
+ gettimeofday (&tv, NULL);
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_nsec += 500000000;
+ if (ts.tv_nsec >= 1000000000)
+ {
+ ++ts.tv_sec;
+ ts.tv_nsec -= 1000000000;
+ }
+
+ e = pthread_mutex_timedlock (m, &ts);
+ if (e == 0)
+ {
+ puts ("child: mutex_timedlock succeeded");
+ exit (1);
+ }
+ if (e != ETIMEDOUT)
+ {
+ puts ("child: mutex_timedlock didn't time out");
+ exit (1);
+ }
+
+ alarm (1);
+
+ pthread_mutex_lock (m);
+
+ puts ("child: mutex_lock returned");
+
+ exit (0);
+ }
+
+ sleep (2);
+
+ int status;
+ if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+ {
+ puts ("waitpid failed");
+ return 1;
+ }
+ if (! WIFSIGNALED (status))
+ {
+ puts ("child not killed by signal");
+ return 1;
+ }
+ if (WTERMSIG (status) != SIGALRM)
+ {
+ puts ("child not killed by SIGALRM");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TIMEOUT 3
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-mutexpi1.c
@@ -0,0 +1,27 @@
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_mutexattr_t a;
+
+static void
+prepare (void)
+{
+ if (pthread_mutexattr_init (&a) != 0)
+ {
+ puts ("mutexattr_init failed");
+ exit (1);
+ }
+
+ if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
+ {
+ puts ("mutexattr_setprotocol failed");
+ exit (1);
+ }
+}
+#define PREPARE(argc, argv) prepare ()
+
+
+#define ATTR &a
+#include "tst-mutex1.c"
--- /dev/null
+++ b/fbtl/tst-mutexpi2.c
@@ -0,0 +1,2 @@
+#define ENABLE_PI 1
+#include "tst-mutex2.c"
--- /dev/null
+++ b/fbtl/tst-mutexpi3.c
@@ -0,0 +1,2 @@
+#define ENABLE_PI 1
+#include "tst-mutex3.c"
--- /dev/null
+++ b/fbtl/tst-mutexpi4.c
@@ -0,0 +1,2 @@
+#define ENABLE_PI 1
+#include "tst-mutex4.c"
--- /dev/null
+++ b/fbtl/tst-mutexpi5.c
@@ -0,0 +1,2 @@
+#define ENABLE_PI 1
+#include "tst-mutex5.c"
--- /dev/null
+++ b/fbtl/tst-mutexpi5a.c
@@ -0,0 +1,2 @@
+#define ENABLE_PI 1
+#include "tst-mutex5a.c"
--- /dev/null
+++ b/fbtl/tst-mutexpi6.c
@@ -0,0 +1,29 @@
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+pthread_mutexattr_t a;
+pthread_mutexattr_t *attr;
+
+static void
+prepare (void)
+{
+ attr = &a;
+ if (pthread_mutexattr_init (&a) != 0)
+ {
+ puts ("mutexattr_init failed");
+ exit (1);
+ }
+
+ if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
+ {
+ puts ("mutexattr_setprotocol failed");
+ exit (1);
+ }
+}
+#define PREPARE(argc, argv) prepare ()
+
+
+#define ATTR attr
+#include "tst-mutex6.c"
--- /dev/null
+++ b/fbtl/tst-mutexpi7.c
@@ -0,0 +1,2 @@
+#define ENABLE_PI 1
+#include "tst-mutex7.c"
--- /dev/null
+++ b/fbtl/tst-mutexpi7a.c
@@ -0,0 +1,2 @@
+#define ENABLE_PI 1
+#include "tst-mutex7a.c"
--- /dev/null
+++ b/fbtl/tst-mutexpi8-static.c
@@ -0,0 +1 @@
+#include "tst-mutexpi8.c"
--- /dev/null
+++ b/fbtl/tst-mutexpi8.c
@@ -0,0 +1,2 @@
+#define ENABLE_PI 1
+#include "tst-mutex8.c"
--- /dev/null
+++ b/fbtl/tst-mutexpi9.c
@@ -0,0 +1,2 @@
+#define ENABLE_PI 1
+#include "tst-mutex9.c"
--- /dev/null
+++ b/fbtl/tst-mutexpp1.c
@@ -0,0 +1,45 @@
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "tst-tpp.h"
+
+static pthread_mutexattr_t a;
+
+static void
+prepare (void)
+{
+ init_tpp_test ();
+
+ if (pthread_mutexattr_init (&a) != 0)
+ {
+ puts ("mutexattr_init failed");
+ exit (1);
+ }
+
+ if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_PROTECT) != 0)
+ {
+ puts ("mutexattr_setprotocol failed");
+ exit (1);
+ }
+
+ if (pthread_mutexattr_setprioceiling (&a, 6) != 0)
+ {
+ puts ("mutexattr_setprioceiling failed");
+ exit (1);
+ }
+}
+#define PREPARE(argc, argv) prepare ()
+
+static int do_test (void);
+
+static int
+do_test_wrapper (void)
+{
+ init_tpp_test ();
+ return do_test ();
+}
+#define TEST_FUNCTION do_test_wrapper ()
+
+#define ATTR &a
+#include "tst-mutex1.c"
--- /dev/null
+++ b/fbtl/tst-mutexpp10.c
@@ -0,0 +1,333 @@
+/* Copyright (C) 2006-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <limits.h>
+#include <pthread.h>
+#include <sched.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "tst-tpp.h"
+
+static int
+do_test (void)
+{
+ int ret = 0;
+
+ init_tpp_test ();
+
+ pthread_mutexattr_t ma;
+ if (pthread_mutexattr_init (&ma))
+ {
+ puts ("mutexattr_init failed");
+ return 1;
+ }
+ if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_PROTECT))
+ {
+ puts ("mutexattr_setprotocol failed");
+ return 1;
+ }
+
+ int prioceiling;
+ if (pthread_mutexattr_getprioceiling (&ma, &prioceiling))
+ {
+ puts ("mutexattr_getprioceiling failed");
+ return 1;
+ }
+
+ if (prioceiling < fifo_min || prioceiling > fifo_max)
+ {
+ printf ("prioceiling %d not in %d..%d range\n",
+ prioceiling, fifo_min, fifo_max);
+ return 1;
+ }
+
+ if (fifo_max < INT_MAX
+ && pthread_mutexattr_setprioceiling (&ma, fifo_max + 1) != EINVAL)
+ {
+ printf ("mutexattr_setprioceiling %d did not fail with EINVAL\n",
+ fifo_max + 1);
+ return 1;
+ }
+
+ if (fifo_min > 0
+ && pthread_mutexattr_setprioceiling (&ma, fifo_min - 1) != EINVAL)
+ {
+ printf ("mutexattr_setprioceiling %d did not fail with EINVAL\n",
+ fifo_min - 1);
+ return 1;
+ }
+
+ if (pthread_mutexattr_setprioceiling (&ma, fifo_min))
+ {
+ puts ("mutexattr_setprioceiling failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_setprioceiling (&ma, fifo_max))
+ {
+ puts ("mutexattr_setprioceiling failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_setprioceiling (&ma, 6))
+ {
+ puts ("mutexattr_setprioceiling failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_getprioceiling (&ma, &prioceiling))
+ {
+ puts ("mutexattr_getprioceiling failed");
+ return 1;
+ }
+
+ if (prioceiling != 6)
+ {
+ printf ("mutexattr_getprioceiling returned %d != 6\n",
+ prioceiling);
+ return 1;
+ }
+
+ pthread_mutex_t m1, m2, m3;
+ int e = pthread_mutex_init (&m1, &ma);
+ if (e == ENOTSUP)
+ {
+ puts ("cannot support selected type of mutexes");
+ return 0;
+ }
+ else if (e != 0)
+ {
+ puts ("mutex_init failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_setprioceiling (&ma, 8))
+ {
+ puts ("mutexattr_setprioceiling failed");
+ return 1;
+ }
+
+ if (pthread_mutex_init (&m2, &ma))
+ {
+ puts ("mutex_init failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_setprioceiling (&ma, 5))
+ {
+ puts ("mutexattr_setprioceiling failed");
+ return 1;
+ }
+
+ if (pthread_mutex_init (&m3, &ma))
+ {
+ puts ("mutex_init failed");
+ return 1;
+ }
+
+ CHECK_TPP_PRIORITY (4, 4);
+
+ if (pthread_mutex_lock (&m1) != 0)
+ {
+ puts ("mutex_lock failed");
+ return 1;
+ }
+
+ CHECK_TPP_PRIORITY (4, 6);
+
+ if (pthread_mutex_trylock (&m2) != 0)
+ {
+ puts ("mutex_lock failed");
+ return 1;
+ }
+
+ CHECK_TPP_PRIORITY (4, 8);
+
+ if (pthread_mutex_lock (&m3) != 0)
+ {
+ puts ("mutex_lock failed");
+ return 1;
+ }
+
+ CHECK_TPP_PRIORITY (4, 8);
+
+ if (pthread_mutex_unlock (&m2) != 0)
+ {
+ puts ("mutex_unlock failed");
+ return 1;
+ }
+
+ CHECK_TPP_PRIORITY (4, 6);
+
+ if (pthread_mutex_unlock (&m1) != 0)
+ {
+ puts ("mutex_unlock failed");
+ return 1;
+ }
+
+ CHECK_TPP_PRIORITY (4, 5);
+
+ if (pthread_mutex_lock (&m2) != 0)
+ {
+ puts ("mutex_lock failed");
+ return 1;
+ }
+
+ CHECK_TPP_PRIORITY (4, 8);
+
+ if (pthread_mutex_unlock (&m2) != 0)
+ {
+ puts ("mutex_unlock failed");
+ return 1;
+ }
+
+ CHECK_TPP_PRIORITY (4, 5);
+
+ if (pthread_mutex_getprioceiling (&m1, &prioceiling))
+ {
+ puts ("mutex_getprioceiling m1 failed");
+ return 1;
+ }
+ else if (prioceiling != 6)
+ {
+ printf ("unexpected m1 prioceiling %d != 6\n", prioceiling);
+ return 1;
+ }
+
+ if (pthread_mutex_getprioceiling (&m2, &prioceiling))
+ {
+ puts ("mutex_getprioceiling m2 failed");
+ return 1;
+ }
+ else if (prioceiling != 8)
+ {
+ printf ("unexpected m2 prioceiling %d != 8\n", prioceiling);
+ return 1;
+ }
+
+ if (pthread_mutex_getprioceiling (&m3, &prioceiling))
+ {
+ puts ("mutex_getprioceiling m3 failed");
+ return 1;
+ }
+ else if (prioceiling != 5)
+ {
+ printf ("unexpected m3 prioceiling %d != 5\n", prioceiling);
+ return 1;
+ }
+
+ if (pthread_mutex_setprioceiling (&m1, 7, &prioceiling))
+ {
+ printf ("mutex_setprioceiling failed");
+ return 1;
+ }
+ else if (prioceiling != 6)
+ {
+ printf ("unexpected m1 old prioceiling %d != 6\n", prioceiling);
+ return 1;
+ }
+
+ if (pthread_mutex_getprioceiling (&m1, &prioceiling))
+ {
+ puts ("mutex_getprioceiling m1 failed");
+ return 1;
+ }
+ else if (prioceiling != 7)
+ {
+ printf ("unexpected m1 prioceiling %d != 7\n", prioceiling);
+ return 1;
+ }
+
+ CHECK_TPP_PRIORITY (4, 5);
+
+ if (pthread_mutex_unlock (&m3) != 0)
+ {
+ puts ("mutex_unlock failed");
+ return 1;
+ }
+
+ CHECK_TPP_PRIORITY (4, 4);
+
+ if (pthread_mutex_trylock (&m1) != 0)
+ {
+ puts ("mutex_lock failed");
+ return 1;
+ }
+
+ CHECK_TPP_PRIORITY (4, 7);
+
+ struct sched_param sp;
+ memset (&sp, 0, sizeof (sp));
+ sp.sched_priority = 8;
+ if (pthread_setschedparam (pthread_self (), SCHED_FIFO, &sp))
+ {
+ puts ("cannot set scheduling params");
+ return 1;
+ }
+
+ CHECK_TPP_PRIORITY (8, 8);
+
+ if (pthread_mutex_unlock (&m1) != 0)
+ {
+ puts ("mutex_unlock failed");
+ return 1;
+ }
+
+ CHECK_TPP_PRIORITY (8, 8);
+
+ if (pthread_mutex_lock (&m3) != EINVAL)
+ {
+ puts ("pthread_mutex_lock didn't fail with EINVAL");
+ return 1;
+ }
+
+ CHECK_TPP_PRIORITY (8, 8);
+
+ if (pthread_mutex_destroy (&m1) != 0)
+ {
+ puts ("mutex_destroy failed");
+ return 1;
+ }
+
+ if (pthread_mutex_destroy (&m2) != 0)
+ {
+ puts ("mutex_destroy failed");
+ return 1;
+ }
+
+ if (pthread_mutex_destroy (&m3) != 0)
+ {
+ puts ("mutex_destroy failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_destroy (&ma) != 0)
+ {
+ puts ("mutexattr_destroy failed");
+ return 1;
+ }
+
+ return ret;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-mutexpp6.c
@@ -0,0 +1,45 @@
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "tst-tpp.h"
+
+static pthread_mutexattr_t a;
+
+static void
+prepare (void)
+{
+ init_tpp_test ();
+
+ if (pthread_mutexattr_init (&a) != 0)
+ {
+ puts ("mutexattr_init failed");
+ exit (1);
+ }
+
+ if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_PROTECT) != 0)
+ {
+ puts ("mutexattr_setprotocol failed");
+ exit (1);
+ }
+
+ if (pthread_mutexattr_setprioceiling (&a, 6) != 0)
+ {
+ puts ("mutexattr_setprioceiling failed");
+ exit (1);
+ }
+}
+#define PREPARE(argc, argv) prepare ()
+
+static int do_test (void);
+
+static int
+do_test_wrapper (void)
+{
+ init_tpp_test ();
+ return do_test ();
+}
+#define TEST_FUNCTION do_test_wrapper ()
+
+#define ATTR &a
+#include "tst-mutex6.c"
--- /dev/null
+++ b/fbtl/tst-oddstacklimit.c
@@ -0,0 +1,73 @@
+/* Test NPTL with stack limit that is not a multiple of the page size.
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+
+/* This sets the stack resource limit to 1023kb, which is not a multiple
+ of the page size since every architecture's page size is > 1k. */
+#ifndef ODD_STACK_LIMIT
+# define ODD_STACK_LIMIT (1023 * 1024)
+#endif
+
+static const char *command;
+
+static int
+do_test (void)
+{
+ int ret;
+ struct rlimit rlim;
+
+ ret = getrlimit (RLIMIT_STACK, &rlim);
+ if (ret != 0)
+ {
+ printf ("getrlimit failed: %s\n", strerror (errno));
+ return 1;
+ }
+ rlim.rlim_cur = ODD_STACK_LIMIT;
+ ret = setrlimit (RLIMIT_STACK, &rlim);
+ if (ret != 0)
+ {
+ printf ("setrlimit failed: %s\n", strerror (errno));
+ return 1;
+ }
+ ret = system (command);
+ if (ret == -1)
+ {
+ printf ("system failed: %s\n", strerror (errno));
+ return 1;
+ }
+ if (WIFEXITED (ret))
+ return WEXITSTATUS (ret);
+ else
+ return 1;
+}
+
+#define OPT_COMMAND 10000
+#define CMDLINE_OPTIONS \
+ { "command", required_argument, NULL, OPT_COMMAND },
+#define CMDLINE_PROCESS \
+ case OPT_COMMAND: \
+ command = optarg; \
+ break;
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-once1.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+
+
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+
+static int global;
+
+static void
+once_handler (void)
+{
+ ++global;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_once (&once, once_handler);
+ pthread_once (&once, once_handler);
+
+ if (global != 1)
+ {
+ printf ("global = %d, expected 1\n", global);
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-once2.c
@@ -0,0 +1,103 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+
+#define N 100
+
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+
+static int global;
+
+static void
+once_handler (void)
+{
+ struct timespec ts;
+
+ ++global;
+
+ ts.tv_sec = 2;
+ ts.tv_nsec = 0;
+ nanosleep (&ts, NULL);
+}
+
+
+static void *
+tf (void *arg)
+{
+ pthread_once (&once, once_handler);
+
+ if (global != 1)
+ {
+ printf ("thread %ld: global == %d\n", (long int) arg, global);
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_attr_t at;
+ pthread_t th[N];
+ int cnt;
+
+ if (pthread_attr_init (&at) != 0)
+ {
+ puts ("attr_init failed");
+ return 1;
+ }
+
+ if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+ for (cnt = 0; cnt < N; ++cnt)
+ if (pthread_create (&th[cnt], &at, tf, (void *) (long int) cnt) != 0)
+ {
+ printf ("creation of thread %d failed\n", cnt);
+ return 1;
+ }
+
+ if (pthread_attr_destroy (&at) != 0)
+ {
+ puts ("attr_destroy failed");
+ return 1;
+ }
+
+ for (cnt = 0; cnt < N; ++cnt)
+ if (pthread_join (th[cnt], NULL) != 0)
+ {
+ printf ("join of thread %d failed\n", cnt);
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 4
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-once3.c
@@ -0,0 +1,166 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+
+#define N 100
+
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+
+static pthread_barrier_t bar;
+
+static int global;
+static int cl_called;
+
+static void
+once_handler1 (void)
+{
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ puts ("once_handler1: mutex_lock failed");
+ exit (1);
+ }
+ puts ("once_handler1: locked");
+
+ int r = pthread_barrier_wait (&bar);
+ if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("once_handler1: barrier_wait failed");
+ exit (1);
+ }
+
+ puts ("once_handler1: going to wait on cond");
+
+ pthread_cond_wait (&cond, &mut);
+
+ /* We should never get here. */
+ exit (42);
+}
+
+static void
+once_handler2 (void)
+{
+ global = 1;
+}
+
+
+static void
+cl (void *arg)
+{
+ cl_called = 1;
+}
+
+
+static void *
+tf (void *arg)
+{
+ pthread_cleanup_push (cl, NULL)
+
+ pthread_once (&once, once_handler1);
+
+ pthread_cleanup_pop (0);
+
+ /* We should never get here. */
+ puts ("pthread_once in tf returned");
+ exit (1);
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_barrier_init (&bar, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("first create failed");
+ return 1;
+ }
+
+ int r = pthread_barrier_wait (&bar);
+ if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ puts ("mutex_lock failed");
+ return 1;
+ }
+ /* We unlock the mutex so that we catch the case where the pthread_cond_wait
+ call incorrectly resumes and tries to get the mutex. */
+ if (pthread_mutex_unlock (&mut) != 0)
+ {
+ puts ("mutex_unlock failed");
+ return 1;
+ }
+
+ /* Cancel the thread. */
+ puts ("going to cancel");
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cancel failed");
+ return 1;
+ }
+
+ void *result;
+ pthread_join (th, &result);
+ if (result != PTHREAD_CANCELED)
+ {
+ puts ("join didn't return PTHREAD_CANCELED");
+ return 1;
+ }
+ puts ("joined successfully");
+
+ printf ("once = %d\n", *(int *) &once);
+
+ if (cl_called != 1)
+ {
+ puts ("cleanup handler not called");
+ return 1;
+ }
+
+ pthread_once (&once, once_handler2);
+
+ if (global != 1)
+ {
+ puts ("global still 0");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 4
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-once4.c
@@ -0,0 +1,201 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+
+static pthread_barrier_t bar;
+
+static int global;
+static int cl_called;
+
+static void
+once_handler1 (void)
+{
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ puts ("once_handler1: mutex_lock failed");
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&bar);
+ if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("once_handler1: barrier_wait failed");
+ exit (1);
+ }
+
+ pthread_cond_wait (&cond, &mut);
+
+ /* We should never get here. */
+}
+
+
+static void
+once_handler2 (void)
+{
+ global = 1;
+}
+
+
+static void
+cl (void *arg)
+{
+ ++cl_called;
+}
+
+
+static void *
+tf1 (void *arg)
+{
+ pthread_cleanup_push (cl, NULL);
+
+ pthread_once (&once, once_handler1);
+
+ pthread_cleanup_pop (0);
+
+ /* We should never get here. */
+ puts ("pthread_once in tf returned");
+ exit (1);
+}
+
+
+static void *
+tf2 (void *arg)
+{
+ pthread_cleanup_push (cl, NULL);
+
+ int r = pthread_barrier_wait (&bar);
+ if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("once_handler2: barrier_wait failed");
+ exit (1);
+ }
+
+ pthread_cleanup_pop (0);
+
+ pthread_once (&once, once_handler2);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th[2];
+
+ if (pthread_barrier_init (&bar, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ if (pthread_create (&th[0], NULL, tf1, NULL) != 0)
+ {
+ puts ("first create failed");
+ return 1;
+ }
+
+ int r = pthread_barrier_wait (&bar);
+ if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("first barrier_wait failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ puts ("mutex_lock failed");
+ return 1;
+ }
+ /* We unlock the mutex so that we catch the case where the pthread_cond_wait
+ call incorrectly resumes and tries to get the mutex. */
+ if (pthread_mutex_unlock (&mut) != 0)
+ {
+ puts ("mutex_unlock failed");
+ return 1;
+ }
+
+ if (pthread_create (&th[1], NULL, tf2, NULL) != 0)
+ {
+ puts ("second create failed");
+ return 1;
+ }
+
+ r = pthread_barrier_wait (&bar);
+ if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("second barrier_wait failed");
+ return 1;
+ }
+
+ /* Give the second thread a chance to reach the pthread_once call. */
+ sleep (2);
+
+ /* Cancel the thread. */
+ if (pthread_cancel (th[0]) != 0)
+ {
+ puts ("cancel failed");
+ return 1;
+ }
+
+ void *result;
+ pthread_join (th[0], &result);
+ if (result != PTHREAD_CANCELED)
+ {
+ puts ("first join didn't return PTHREAD_CANCELED");
+ return 1;
+ }
+
+ puts ("joined first thread");
+
+ pthread_join (th[1], &result);
+ if (result != NULL)
+ {
+ puts ("second join didn't return PTHREAD_CANCELED");
+ return 1;
+ }
+
+ if (global != 1)
+ {
+ puts ("global still 0");
+ return 1;
+ }
+
+ if (cl_called != 1)
+ {
+ printf ("cl_called = %d\n", cl_called);
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 4
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-oncex3.c
@@ -0,0 +1 @@
+#include "tst-once3.c"
--- /dev/null
+++ b/fbtl/tst-oncex4.c
@@ -0,0 +1 @@
+#include "tst-once4.c"
--- /dev/null
+++ b/fbtl/tst-popen1.c
@@ -0,0 +1,59 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <error.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void *
+dummy (void *x)
+{
+ return NULL;
+}
+
+static char buf[sizeof "something\n"];
+
+static int
+do_test (void)
+{
+ FILE *f;
+ pthread_t p;
+ int err;
+
+ f = popen ("echo something", "r");
+ if (f == NULL)
+ error (EXIT_FAILURE, errno, "popen failed");
+ if (fgets (buf, sizeof (buf), f) == NULL)
+ error (EXIT_FAILURE, 0, "fgets failed");
+ if (strcmp (buf, "something\n"))
+ error (EXIT_FAILURE, 0, "read wrong data");
+ if (pclose (f))
+ error (EXIT_FAILURE, errno, "pclose returned non-zero");
+ if ((err = pthread_create (&p, NULL, dummy, NULL)))
+ error (EXIT_FAILURE, err, "pthread_create failed");
+ if ((err = pthread_join (p, NULL)))
+ error (EXIT_FAILURE, err, "pthread_join failed");
+ exit (0);
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-pthread-attr-affinity.c
@@ -0,0 +1,63 @@
+/* Make sure that pthread_attr_getaffinity_np does not crash when the input
+ cpuset size is smaller than that in the attribute structure.
+
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <sched.h>
+#include <errno.h>
+#include <sys/param.h>
+
+
+#define RETURN_IF_FAIL(f, ...) \
+ ({ \
+ int ret = f (__VA_ARGS__); \
+ if (ret != 0) \
+ { \
+ printf ("%s:%d: %s returned %d (errno = %d)\n", __FILE__, __LINE__, \
+ #f, ret, errno); \
+ return ret; \
+ } \
+ })
+
+static int
+do_test (void)
+{
+ for (int i = 0; i < 10; i++)
+ {
+ pthread_attr_t attr;
+ cpu_set_t *cpuset = CPU_ALLOC (512);
+ size_t cpusetsize = CPU_ALLOC_SIZE (512);
+ CPU_ZERO_S (cpusetsize, cpuset);
+
+ RETURN_IF_FAIL (pthread_attr_init, &attr);
+ RETURN_IF_FAIL (pthread_attr_setaffinity_np, &attr, cpusetsize, cpuset);
+ CPU_FREE (cpuset);
+
+ cpuset = CPU_ALLOC (1);
+ cpusetsize = CPU_ALLOC_SIZE (1);
+ RETURN_IF_FAIL (pthread_attr_getaffinity_np, &attr, cpusetsize, cpuset);
+ CPU_FREE (cpuset);
+ }
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-pthread-getattr.c
@@ -0,0 +1,161 @@
+/* Make sure that the stackaddr returned by pthread_getattr_np is
+ reachable.
+
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/resource.h>
+#include <sys/param.h>
+#include <pthread.h>
+#include <alloca.h>
+#include <assert.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+/* There is an obscure bug in the kernel due to which RLIMIT_STACK is sometimes
+ returned as unlimited when it is not, which may cause this test to fail.
+ There is also the other case where RLIMIT_STACK is intentionally set as
+ unlimited or very high, which may result in a vma that is too large and again
+ results in a test case failure. To avoid these problems, we cap the stack
+ size to one less than 8M. See the following mailing list threads for more
+ information about this problem:
+ <http://sourceware.org/ml/libc-alpha/2012-06/msg00599.html>
+ <http://sourceware.org/ml/libc-alpha/2012-06/msg00713.html>. */
+#define MAX_STACK_SIZE (8192 * 1024 - 1)
+
+static size_t pagesize;
+
+/* Check if the page in which TARGET lies is accessible. This will segfault
+ if it fails. */
+static volatile char *
+allocate_and_test (char *target)
+{
+ volatile char *mem = (char *) &mem;
+ /* FIXME: mem >= target for _STACK_GROWSUP. */
+ mem = alloca ((size_t) (mem - target));
+
+ *mem = 42;
+ return mem;
+}
+
+static int
+get_self_pthread_attr (const char *id, void **stackaddr, size_t *stacksize)
+{
+ pthread_attr_t attr;
+ int ret;
+ pthread_t me = pthread_self ();
+
+ if ((ret = pthread_getattr_np (me, &attr)) < 0)
+ {
+ printf ("%s: pthread_getattr_np failed: %s\n", id, strerror (ret));
+ return 1;
+ }
+
+ if ((ret = pthread_attr_getstack (&attr, stackaddr, stacksize)) < 0)
+ {
+ printf ("%s: pthread_attr_getstack returned error: %s\n", id,
+ strerror (ret));
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Verify that the stack size returned by pthread_getattr_np is usable when
+ the returned value is subject to rlimit. */
+static int
+check_stack_top (void)
+{
+ struct rlimit stack_limit;
+ void *stackaddr;
+ volatile void *mem;
+ size_t stacksize = 0;
+ int ret;
+ uintptr_t pagemask = ~(pagesize - 1);
+
+ puts ("Verifying that stack top is accessible");
+
+ ret = getrlimit (RLIMIT_STACK, &stack_limit);
+ if (ret)
+ {
+ perror ("getrlimit failed");
+ return 1;
+ }
+
+ printf ("current rlimit_stack is %zu\n", (size_t) stack_limit.rlim_cur);
+
+ if (get_self_pthread_attr ("check_stack_top", &stackaddr, &stacksize))
+ return 1;
+
+ /* Reduce the rlimit to a page less that what is currently being returned
+ (subject to a maximum of MAX_STACK_SIZE) so that we ensure that
+ pthread_getattr_np uses rlimit. The figure is intentionally unaligned so
+ to verify that pthread_getattr_np returns an aligned stacksize that
+ correctly fits into the rlimit. We don't bother about the case where the
+ stack is limited by the vma below it and not by the rlimit because the
+ stacksize returned in that case is computed from the end of that vma and is
+ hence safe. */
+ stack_limit.rlim_cur = MIN (stacksize - pagesize + 1, MAX_STACK_SIZE);
+ printf ("Adjusting RLIMIT_STACK to %zu\n", (size_t) stack_limit.rlim_cur);
+ if ((ret = setrlimit (RLIMIT_STACK, &stack_limit)) < 0)
+ {
+ perror ("setrlimit failed");
+ return 1;
+ }
+
+ if (get_self_pthread_attr ("check_stack_top2", &stackaddr, &stacksize))
+ return 1;
+
+ printf ("Adjusted rlimit: stacksize=%zu, stackaddr=%p\n", stacksize,
+ stackaddr);
+
+ /* A lot of targets tend to write stuff on top of the user stack during
+ context switches, so we cannot possibly safely go up to the very top of
+ stack and test access there. It is however sufficient to simply check if
+ the top page is accessible, so we target our access halfway up the top
+ page. Thanks Chris Metcalf for this idea. */
+ mem = allocate_and_test (stackaddr + pagesize / 2);
+
+ /* Before we celebrate, make sure we actually did test the same page. */
+ if (((uintptr_t) stackaddr & pagemask) != ((uintptr_t) mem & pagemask))
+ {
+ printf ("We successfully wrote into the wrong page.\n"
+ "Expected %#" PRIxPTR ", but got %#" PRIxPTR "\n",
+ (uintptr_t) stackaddr & pagemask, (uintptr_t) mem & pagemask);
+
+ return 1;
+ }
+
+ puts ("Stack top tests done");
+
+ return 0;
+}
+
+/* TODO: Similar check for thread stacks once the thread stack sizes are
+ fixed. */
+static int
+do_test (void)
+{
+ pagesize = sysconf (_SC_PAGESIZE);
+ return check_stack_top ();
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-raise1.c
@@ -0,0 +1,61 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <error.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+volatile int count;
+
+void
+sh (int sig)
+{
+ ++count;
+}
+
+int
+main (void)
+{
+ struct sigaction sa;
+ sa.sa_handler = sh;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+ if (sigaction (SIGUSR1, &sa, NULL) < 0)
+ {
+ printf ("sigaction failed: %m\n");
+ exit (1);
+ }
+ if (raise (SIGUSR1) < 0)
+ {
+ printf ("first raise failed: %m\n");
+ exit (1);
+ }
+ if (raise (SIGUSR1) < 0)
+ {
+ printf ("second raise failed: %m\n");
+ exit (1);
+ }
+ if (count != 2)
+ {
+ printf ("signal handler not called 2 times\n");
+ exit (1);
+ }
+ exit (0);
+}
--- /dev/null
+++ b/fbtl/tst-robust1.c
@@ -0,0 +1,338 @@
+/* Copyright (C) 2005-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_mutex_t m1;
+static pthread_mutex_t m2;
+static pthread_barrier_t b;
+
+
+#ifndef LOCK
+# define LOCK(m) pthread_mutex_lock (m)
+#endif
+
+
+static void *
+tf (void *arg)
+{
+ long int round = (long int) arg;
+
+ if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0)
+ {
+ printf ("%ld: setcancelstate failed\n", round);
+ exit (1);
+ }
+
+ int e = LOCK (&m1);
+ if (e != 0)
+ {
+ printf ("%ld: child: mutex_lock m1 failed with error %d\n", round, e);
+ exit (1);
+ }
+
+ e = LOCK (&m2);
+ if (e != 0)
+ {
+ printf ("%ld: child: mutex_lock m2 failed with error %d\n", round, e);
+ exit (1);
+ }
+
+ e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%ld: child: 1st barrier_wait failed\n", round);
+ exit (1);
+ }
+
+ e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%ld: child: 2nd barrier_wait failed\n", round);
+ exit (1);
+ }
+
+ pthread_testcancel ();
+
+ printf ("%ld: testcancel returned\n", round);
+ exit (1);
+}
+
+
+static int
+do_test (void)
+{
+#ifdef PREPARE_TMO
+ PREPARE_TMO;
+#endif
+
+ pthread_mutexattr_t a;
+ if (pthread_mutexattr_init (&a) != 0)
+ {
+ puts ("mutexattr_init failed");
+ return 1;
+ }
+ if (pthread_mutexattr_setrobust_np (&a, PTHREAD_MUTEX_ROBUST_NP) != 0)
+ {
+ puts ("mutexattr_setrobust failed");
+ return 1;
+ }
+
+#ifdef ENABLE_PI
+ if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
+ {
+ puts ("pthread_mutexattr_setprotocol failed");
+ return 1;
+ }
+ else
+ {
+ int e = pthread_mutex_init (&m1, &a);
+ if (e == ENOTSUP)
+ {
+ puts ("PI robust mutexes not supported");
+ return 0;
+ }
+ else if (e != 0)
+ {
+ puts ("mutex_init m1 failed");
+ return 1;
+ }
+ pthread_mutex_destroy (&m1);
+ }
+#endif
+
+#ifndef NOT_CONSISTENT
+ if (pthread_mutex_init (&m1, &a) != 0)
+ {
+ puts ("mutex_init m1 failed");
+ return 1;
+ }
+
+ if (pthread_mutex_init (&m2, &a) != 0)
+ {
+ puts ("mutex_init m2 failed");
+ return 1;
+ }
+#endif
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ for (long int round = 1; round < 5; ++round)
+ {
+#ifdef NOT_CONSISTENT
+ if (pthread_mutex_init (&m1 , &a) != 0)
+ {
+ puts ("mutex_init m1 failed");
+ return 1;
+ }
+ if (pthread_mutex_init (&m2 , &a) != 0)
+ {
+ puts ("mutex_init m2 failed");
+ return 1;
+ }
+#endif
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, (void *) round) != 0)
+ {
+ printf ("%ld: create failed\n", round);
+ return 1;
+ }
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%ld: parent: 1st barrier_wait failed\n", round);
+ return 1;
+ }
+
+ if (pthread_cancel (th) != 0)
+ {
+ printf ("%ld: cancel failed\n", round);
+ return 1;
+ }
+
+ e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%ld: parent: 2nd barrier_wait failed\n", round);
+ return 1;
+ }
+
+#ifndef AFTER_JOIN
+ if (round & 1)
+#endif
+ {
+ void *res;
+ if (pthread_join (th, &res) != 0)
+ {
+ printf ("%ld: join failed\n", round);
+ return 1;
+ }
+ if (res != PTHREAD_CANCELED)
+ {
+ printf ("%ld: thread not canceled\n", round);
+ return 1;
+ }
+ }
+
+ e = LOCK (&m1);
+ if (e == 0)
+ {
+ printf ("%ld: parent: mutex_lock m1 succeeded\n", round);
+ return 1;
+ }
+ if (e != EOWNERDEAD)
+ {
+ printf ("%ld: parent: mutex_lock m1 returned wrong code\n", round);
+ return 1;
+ }
+
+ e = LOCK (&m2);
+ if (e == 0)
+ {
+ printf ("%ld: parent: mutex_lock m2 succeeded\n", round);
+ return 1;
+ }
+ if (e != EOWNERDEAD)
+ {
+ printf ("%ld: parent: mutex_lock m2 returned wrong code\n", round);
+ return 1;
+ }
+
+#ifndef AFTER_JOIN
+ if ((round & 1) == 0)
+ {
+ void *res;
+ if (pthread_join (th, &res) != 0)
+ {
+ printf ("%ld: join failed\n", round);
+ return 1;
+ }
+ if (res != PTHREAD_CANCELED)
+ {
+ printf ("%ld: thread not canceled\n", round);
+ return 1;
+ }
+ }
+#endif
+
+#ifndef NOT_CONSISTENT
+ e = pthread_mutex_consistent_np (&m1);
+ if (e != 0)
+ {
+ printf ("%ld: mutex_consistent m1 failed with error %d\n", round, e);
+ return 1;
+ }
+
+ e = pthread_mutex_consistent_np (&m2);
+ if (e != 0)
+ {
+ printf ("%ld: mutex_consistent m2 failed with error %d\n", round, e);
+ return 1;
+ }
+#endif
+
+ e = pthread_mutex_unlock (&m1);
+ if (e != 0)
+ {
+ printf ("%ld: mutex_unlock m1 failed with %d\n", round, e);
+ return 1;
+ }
+
+ e = pthread_mutex_unlock (&m2);
+ if (e != 0)
+ {
+ printf ("%ld: mutex_unlock m2 failed with %d\n", round, e);
+ return 1;
+ }
+
+#ifdef NOT_CONSISTENT
+ e = LOCK (&m1);
+ if (e == 0)
+ {
+ printf ("%ld: locking inconsistent mutex m1 succeeded\n", round);
+ return 1;
+ }
+ if (e != ENOTRECOVERABLE)
+ {
+ printf ("%ld: locking inconsistent mutex m1 failed with error %d\n",
+ round, e);
+ return 1;
+ }
+
+ if (pthread_mutex_destroy (&m1) != 0)
+ {
+ puts ("mutex_destroy m1 failed");
+ return 1;
+ }
+
+ e = LOCK (&m2);
+ if (e == 0)
+ {
+ printf ("%ld: locking inconsistent mutex m2 succeeded\n", round);
+ return 1;
+ }
+ if (e != ENOTRECOVERABLE)
+ {
+ printf ("%ld: locking inconsistent mutex m2 failed with error %d\n",
+ round, e);
+ return 1;
+ }
+
+ if (pthread_mutex_destroy (&m2) != 0)
+ {
+ puts ("mutex_destroy m2 failed");
+ return 1;
+ }
+#endif
+ }
+
+#ifndef NOT_CONSISTENT
+ if (pthread_mutex_destroy (&m1) != 0)
+ {
+ puts ("mutex_destroy m1 failed");
+ return 1;
+ }
+
+ if (pthread_mutex_destroy (&m2) != 0)
+ {
+ puts ("mutex_destroy m2 failed");
+ return 1;
+ }
+#endif
+
+ if (pthread_mutexattr_destroy (&a) != 0)
+ {
+ puts ("mutexattr_destroy failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-robust2.c
@@ -0,0 +1,3 @@
+#define AFTER_JOIN 1
+#define LOCK(m) pthread_mutex_trylock (m)
+#include "tst-robust1.c"
--- /dev/null
+++ b/fbtl/tst-robust3.c
@@ -0,0 +1,20 @@
+#include <time.h>
+#include <sys/time.h>
+
+
+static struct timespec tmo;
+
+
+#define PREPARE_TMO \
+ do { \
+ struct timeval tv; \
+ gettimeofday (&tv, NULL); \
+ \
+ /* Define the timeout as one hour in the future. */ \
+ tmo.tv_sec = tv.tv_sec + 3600; \
+ tmo.tv_nsec = 0; \
+ } while (0)
+
+
+#define LOCK(m) pthread_mutex_timedlock (m, &tmo)
+#include "tst-robust1.c"
--- /dev/null
+++ b/fbtl/tst-robust4.c
@@ -0,0 +1,2 @@
+#define NOT_CONSISTENT 1
+#include "tst-robust1.c"
--- /dev/null
+++ b/fbtl/tst-robust5.c
@@ -0,0 +1,2 @@
+#define NOT_CONSISTENT 1
+#include "tst-robust2.c"
--- /dev/null
+++ b/fbtl/tst-robust6.c
@@ -0,0 +1,2 @@
+#define NOT_CONSISTENT 1
+#include "tst-robust3.c"
--- /dev/null
+++ b/fbtl/tst-robust7.c
@@ -0,0 +1,212 @@
+/* Copyright (C) 2005-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_barrier_t b;
+static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t m;
+static bool first = true;
+
+
+static void *
+tf (void *arg)
+{
+ long int n = (long int) arg;
+
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ printf ("thread %ld: mutex_lock failed\n", n + 1);
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("thread %ld: barrier_wait failed\n", n + 1);
+ exit (1);
+ }
+
+ e = pthread_cond_wait (&c, &m);
+ if (first)
+ {
+ if (e != 0)
+ {
+ printf ("thread %ld: cond_wait failed\n", n + 1);
+ exit (1);
+ }
+ first = false;
+ }
+ else
+ {
+ if (e != EOWNERDEAD)
+ {
+ printf ("thread %ld: cond_wait did not return EOWNERDEAD\n", n + 1);
+ exit (1);
+ }
+ }
+
+ if (pthread_cancel (pthread_self ()) != 0)
+ {
+ printf ("thread %ld: cancel failed\n", n + 1);
+ exit (1);
+ }
+
+ pthread_testcancel ();
+
+ printf ("thread %ld: testcancel returned\n", n + 1);
+ exit (1);
+}
+
+
+static int
+do_test (void)
+{
+ pthread_mutexattr_t a;
+ if (pthread_mutexattr_init (&a) != 0)
+ {
+ puts ("mutexattr_init failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_setrobust_np (&a, PTHREAD_MUTEX_ROBUST_NP) != 0)
+ {
+ puts ("mutexattr_setrobust failed");
+ return 1;
+ }
+
+#ifdef ENABLE_PI
+ if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
+ {
+ puts ("pthread_mutexattr_setprotocol failed");
+ return 1;
+ }
+#endif
+
+ int e;
+ e = pthread_mutex_init (&m, &a);
+ if (e != 0)
+ {
+#ifdef ENABLE_PI
+ if (e == ENOTSUP)
+ {
+ puts ("PI robust mutexes not supported");
+ return 0;
+ }
+#endif
+ puts ("mutex_init failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_destroy (&a) != 0)
+ {
+ puts ("mutexattr_destroy failed");
+ return 1;
+ }
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+#define N 5
+ pthread_t th[N];
+ for (long int n = 0; n < N; ++n)
+ {
+ if (pthread_create (&th[n], NULL, tf, (void *) n) != 0)
+ {
+ printf ("pthread_create loop %ld failed\n", n + 1);
+ return 1;
+ }
+
+ e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("parent: barrier_wait failed in round %ld\n", n + 1);
+ return 1;
+ }
+ }
+
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("parent: mutex_lock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_unlock (&m) != 0)
+ {
+ puts ("parent: mutex_unlock failed");
+ return 1;
+ }
+
+ if (pthread_cond_broadcast (&c) != 0)
+ {
+ puts ("cond_broadcast failed");
+ return 1;
+ }
+
+ for (int n = 0; n < N; ++n)
+ {
+ void *res;
+ if (pthread_join (th[n], &res) != 0)
+ {
+ printf ("join round %d failed\n", n + 1);
+ return 1;
+ }
+ if (res != PTHREAD_CANCELED)
+ {
+ printf ("thread %d not canceled\n", n + 1);
+ return 1;
+ }
+ }
+
+ e = pthread_mutex_lock (&m);
+ if (e == 0)
+ {
+ puts ("parent: 2nd mutex_lock succeeded");
+ return 1;
+ }
+ if (e != EOWNERDEAD)
+ {
+ puts ("parent: mutex_lock did not return EOWNERDEAD");
+ return 1;
+ }
+
+ if (pthread_mutex_unlock (&m) != 0)
+ {
+ puts ("parent: 2nd mutex_unlock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_destroy (&m) != 0)
+ {
+ puts ("mutex_destroy failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-robust8.c
@@ -0,0 +1,275 @@
+#include <pthread.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+
+
+
+static void prepare (void);
+#define PREPARE(argc, argv) prepare ()
+static int do_test (void);
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 5
+#include "../test-skeleton.c"
+
+
+static int fd;
+#define N 100
+
+static void
+prepare (void)
+{
+ fd = create_temp_file ("tst-robust8", NULL);
+ if (fd == -1)
+ exit (1);
+}
+
+
+#define THESIGNAL SIGKILL
+#define ROUNDS 5
+#define THREADS 9
+
+
+static const struct timespec before = { 0, 0 };
+
+
+static pthread_mutex_t *map;
+
+
+static void *
+tf (void *arg)
+{
+ long int nr = (long int) arg;
+ int fct = nr % 3;
+
+ uint8_t state[N];
+ memset (state, '\0', sizeof (state));
+
+ while (1)
+ {
+ int r = random () % N;
+ if (state[r] == 0)
+ {
+ int e;
+
+ switch (fct)
+ {
+ case 0:
+ e = pthread_mutex_lock (&map[r]);
+ if (e != 0)
+ {
+ printf ("mutex_lock of %d in thread %ld failed with %d\n",
+ r, nr, e);
+ exit (1);
+ }
+ state[r] = 1;
+ break;
+ case 1:
+ e = pthread_mutex_timedlock (&map[r], &before);
+ if (e != 0 && e != ETIMEDOUT)
+ {
+ printf ("\
+mutex_timedlock of %d in thread %ld failed with %d\n",
+ r, nr, e);
+ exit (1);
+ }
+ break;
+ default:
+ e = pthread_mutex_trylock (&map[r]);
+ if (e != 0 && e != EBUSY)
+ {
+ printf ("mutex_trylock of %d in thread %ld failed with %d\n",
+ r, nr, e);
+ exit (1);
+ }
+ break;
+ }
+
+ if (e == EOWNERDEAD)
+ pthread_mutex_consistent_np (&map[r]);
+
+ if (e == 0 || e == EOWNERDEAD)
+ state[r] = 1;
+ }
+ else
+ {
+ int e = pthread_mutex_unlock (&map[r]);
+ if (e != 0)
+ {
+ printf ("mutex_unlock of %d in thread %ld failed with %d\n",
+ r, nr, e);
+ exit (1);
+ }
+
+ state[r] = 0;
+ }
+ }
+}
+
+
+static void
+child (int round)
+{
+ for (int thread = 1; thread <= THREADS; ++thread)
+ {
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, (void *) (long int) thread) != 0)
+ {
+ printf ("cannot create thread %d in round %d\n", thread, round);
+ exit (1);
+ }
+ }
+
+ struct timespec ts;
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1000000000 / ROUNDS;
+ while (nanosleep (&ts, &ts) != 0)
+ /* nothing */;
+
+ /* Time to die. */
+ kill (getpid (), THESIGNAL);
+
+ /* We better never get here. */
+ abort ();
+}
+
+
+static int
+do_test (void)
+{
+ if (ftruncate (fd, N * sizeof (pthread_mutex_t)) != 0)
+ {
+ puts ("cannot size new file");
+ return 1;
+ }
+
+ map = mmap (NULL, N * sizeof (pthread_mutex_t), PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ if (map == MAP_FAILED)
+ {
+ puts ("mapping failed");
+ return 1;
+ }
+
+ pthread_mutexattr_t ma;
+ if (pthread_mutexattr_init (&ma) != 0)
+ {
+ puts ("mutexattr_init failed");
+ return 0;
+ }
+ if (pthread_mutexattr_setrobust_np (&ma, PTHREAD_MUTEX_ROBUST_NP) != 0)
+ {
+ puts ("mutexattr_setrobust failed");
+ return 1;
+ }
+ if (pthread_mutexattr_setpshared (&ma, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("mutexattr_setpshared failed");
+ return 1;
+ }
+#ifdef ENABLE_PI
+ if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT) != 0)
+ {
+ puts ("pthread_mutexattr_setprotocol failed");
+ return 1;
+ }
+#endif
+
+ for (int round = 1; round <= ROUNDS; ++round)
+ {
+ for (int n = 0; n < N; ++n)
+ {
+ int e = pthread_mutex_init (&map[n], &ma);
+ if (e == ENOTSUP)
+ {
+#ifdef ENABLE_PI
+ puts ("cannot support pshared robust PI mutexes");
+#else
+ puts ("cannot support pshared robust mutexes");
+#endif
+ return 0;
+ }
+ if (e != 0)
+ {
+ printf ("mutex_init %d in round %d failed\n", n + 1, round);
+ return 1;
+ }
+ }
+
+ pid_t p = fork ();
+ if (p == -1)
+ {
+ printf ("fork in round %d failed\n", round);
+ return 1;
+ }
+ if (p == 0)
+ child (round);
+
+ int status;
+ if (TEMP_FAILURE_RETRY (waitpid (p, &status, 0)) != p)
+ {
+ printf ("waitpid in round %d failed\n", round);
+ return 1;
+ }
+ if (!WIFSIGNALED (status))
+ {
+ printf ("child did not die of a signal in round %d\n", round);
+ return 1;
+ }
+ if (WTERMSIG (status) != THESIGNAL)
+ {
+ printf ("child did not die of signal %d in round %d\n",
+ THESIGNAL, round);
+ return 1;
+ }
+
+ for (int n = 0; n < N; ++n)
+ {
+ int e = pthread_mutex_lock (&map[n]);
+ if (e != 0 && e != EOWNERDEAD)
+ {
+ printf ("mutex_lock %d failed in round %d\n", n + 1, round);
+ return 1;
+ }
+ }
+
+ for (int n = 0; n < N; ++n)
+ if (pthread_mutex_unlock (&map[n]) != 0)
+ {
+ printf ("mutex_unlock %d failed in round %d\n", n + 1, round);
+ return 1;
+ }
+
+ for (int n = 0; n < N; ++n)
+ {
+ int e = pthread_mutex_destroy (&map[n]);
+ if (e != 0)
+ {
+ printf ("mutex_destroy %d in round %d failed with %d\n",
+ n + 1, round, e);
+ printf("nusers = %d\n", (int) map[n].__data.__nusers);
+ return 1;
+ }
+ }
+ }
+
+ if (pthread_mutexattr_destroy (&ma) != 0)
+ {
+ puts ("mutexattr_destroy failed");
+ return 1;
+ }
+
+ if (munmap (map, N * sizeof (pthread_mutex_t)) != 0)
+ {
+ puts ("munmap failed");
+ return 1;
+ }
+
+ return 0;
+}
--- /dev/null
+++ b/fbtl/tst-robust9.c
@@ -0,0 +1,94 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+
+static pthread_mutex_t m;
+
+static void *
+tf (void *data)
+{
+ int err = pthread_mutex_lock (&m);
+ if (err == EOWNERDEAD)
+ {
+ err = pthread_mutex_consistent_np (&m);
+ if (err)
+ {
+ puts ("pthread_mutex_consistent_np");
+ exit (1);
+ }
+ }
+ else if (err)
+ {
+ puts ("pthread_mutex_lock");
+ exit (1);
+ }
+ printf ("thread%ld got the lock.\n", (long int) data);
+ sleep (1);
+ /* exit without unlock */
+ return NULL;
+}
+
+static int
+do_test (void)
+{
+ int err, i;
+ pthread_t t[3];
+ pthread_mutexattr_t ma;
+
+ pthread_mutexattr_init (&ma);
+ err = pthread_mutexattr_setrobust_np (&ma, PTHREAD_MUTEX_ROBUST_NP);
+ if (err)
+ {
+ puts ("pthread_mutexattr_setrobust_np");
+ return 1;
+ }
+#ifdef ENABLE_PI
+ if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT) != 0)
+ {
+ puts ("pthread_mutexattr_setprotocol failed");
+ return 1;
+ }
+#endif
+ err = pthread_mutex_init (&m, &ma);
+#ifdef ENABLE_PI
+ if (err == ENOTSUP)
+ {
+ puts ("PI robust mutexes not supported");
+ return 0;
+ }
+#endif
+ if (err)
+ {
+ puts ("pthread_mutex_init");
+ return 1;
+ }
+
+ for (i = 0; i < sizeof (t) / sizeof (t[0]); i++)
+ {
+ err = pthread_create (&t[i], NULL, tf, (void *) (long int) i);
+ if (err)
+ {
+ puts ("pthread_create");
+ return 1;
+ }
+ }
+
+ for (i = 0; i < sizeof (t) / sizeof (t[0]); i++)
+ {
+ err = pthread_join (t[i], NULL);
+ if (err)
+ {
+ puts ("pthread_join");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#define TIMEOUT 5
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-robustpi1.c
@@ -0,0 +1,2 @@
+#define ENABLE_PI 1
+#include "tst-robust1.c"
--- /dev/null
+++ b/fbtl/tst-robustpi2.c
@@ -0,0 +1,2 @@
+#define ENABLE_PI 1
+#include "tst-robust2.c"
--- /dev/null
+++ b/fbtl/tst-robustpi3.c
@@ -0,0 +1,2 @@
+#define ENABLE_PI 1
+#include "tst-robust3.c"
--- /dev/null
+++ b/fbtl/tst-robustpi4.c
@@ -0,0 +1,2 @@
+#define ENABLE_PI 1
+#include "tst-robust4.c"
--- /dev/null
+++ b/fbtl/tst-robustpi5.c
@@ -0,0 +1,2 @@
+#define ENABLE_PI 1
+#include "tst-robust5.c"
--- /dev/null
+++ b/fbtl/tst-robustpi6.c
@@ -0,0 +1,2 @@
+#define ENABLE_PI 1
+#include "tst-robust6.c"
--- /dev/null
+++ b/fbtl/tst-robustpi7.c
@@ -0,0 +1,2 @@
+#define ENABLE_PI 1
+#include "tst-robust7.c"
--- /dev/null
+++ b/fbtl/tst-robustpi8.c
@@ -0,0 +1,2 @@
+#define ENABLE_PI 1
+#include "tst-robust8.c"
--- /dev/null
+++ b/fbtl/tst-robustpi9.c
@@ -0,0 +1,2 @@
+#define ENABLE_PI 1
+#include "tst-robust9.c"
--- /dev/null
+++ b/fbtl/tst-rwlock1.c
@@ -0,0 +1,116 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+
+
+static int
+do_test (void)
+{
+ pthread_rwlock_t r;
+
+ if (pthread_rwlock_init (&r, NULL) != 0)
+ {
+ puts ("rwlock_init failed");
+ return 1;
+ }
+ puts ("rwlock_init succeeded");
+
+ if (pthread_rwlock_rdlock (&r) != 0)
+ {
+ puts ("1st rwlock_rdlock failed");
+ return 1;
+ }
+ puts ("1st rwlock_rdlock succeeded");
+
+ if (pthread_rwlock_rdlock (&r) != 0)
+ {
+ puts ("2nd rwlock_rdlock failed");
+ return 1;
+ }
+ puts ("2nd rwlock_rdlock succeeded");
+
+ if (pthread_rwlock_unlock (&r) != 0)
+ {
+ puts ("1st rwlock_unlock failed");
+ return 1;
+ }
+ puts ("1st rwlock_unlock succeeded");
+
+ if (pthread_rwlock_unlock (&r) != 0)
+ {
+ puts ("2nd rwlock_unlock failed");
+ return 1;
+ }
+ puts ("2nd rwlock_unlock succeeded");
+
+ if (pthread_rwlock_wrlock (&r) != 0)
+ {
+ puts ("1st rwlock_wrlock failed");
+ return 1;
+ }
+ puts ("1st rwlock_wrlock succeeded");
+
+ if (pthread_rwlock_unlock (&r) != 0)
+ {
+ puts ("3rd rwlock_unlock failed");
+ return 1;
+ }
+ puts ("3rd rwlock_unlock succeeded");
+
+ if (pthread_rwlock_wrlock (&r) != 0)
+ {
+ puts ("2nd rwlock_wrlock failed");
+ return 1;
+ }
+ puts ("2nd rwlock_wrlock succeeded");
+
+ if (pthread_rwlock_unlock (&r) != 0)
+ {
+ puts ("4th rwlock_unlock failed");
+ return 1;
+ }
+ puts ("4th rwlock_unlock succeeded");
+
+ if (pthread_rwlock_rdlock (&r) != 0)
+ {
+ puts ("3rd rwlock_rdlock failed");
+ return 1;
+ }
+ puts ("3rd rwlock_rdlock succeeded");
+
+ if (pthread_rwlock_unlock (&r) != 0)
+ {
+ puts ("5th rwlock_unlock failed");
+ return 1;
+ }
+ puts ("5th rwlock_unlock succeeded");
+
+ if (pthread_rwlock_destroy (&r) != 0)
+ {
+ puts ("rwlock_destroy failed");
+ return 1;
+ }
+ puts ("rwlock_destroy succeeded");
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-rwlock10.c
@@ -0,0 +1,20 @@
+/* Test program for timedout read/write lock functions.
+ Copyright (C) 2003-2013 Free Software Foundation, Inc.
+ 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, see <http://www.gnu.org/licenses/>. */
+
+#define INIT PTHREAD_RWLOCK_INITIALIZER
+#include "tst-rwlock8.c"
--- /dev/null
+++ b/fbtl/tst-rwlock11.c
@@ -0,0 +1,20 @@
+/* Test program for timedout read/write lock functions.
+ Copyright (C) 2003-2013 Free Software Foundation, Inc.
+ 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, see <http://www.gnu.org/licenses/>. */
+
+#define INIT PTHREAD_RWLOCK_INITIALIZER
+#include "tst-rwlock9.c"
--- /dev/null
+++ b/fbtl/tst-rwlock12.c
@@ -0,0 +1,207 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+
+static int
+do_test (void)
+{
+ size_t ps = sysconf (_SC_PAGESIZE);
+ char tmpfname[] = "/tmp/tst-rwlock12.XXXXXX";
+ char data[ps];
+ void *mem;
+ int fd;
+ pthread_mutex_t *m;
+ pthread_mutexattr_t ma;
+ pthread_rwlock_t *r;
+ pthread_rwlockattr_t ra;
+ pid_t pid;
+ int status = 0;
+
+ fd = mkstemp (tmpfname);
+ if (fd == -1)
+ {
+ printf ("cannot open temporary file: %m\n");
+ return 1;
+ }
+
+ /* Make sure it is always removed. */
+ unlink (tmpfname);
+
+ /* Create one page of data. */
+ memset (data, '\0', ps);
+
+ /* Write the data to the file. */
+ if (write (fd, data, ps) != (ssize_t) ps)
+ {
+ puts ("short write");
+ return 1;
+ }
+
+ mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (mem == MAP_FAILED)
+ {
+ printf ("mmap failed: %m\n");
+ return 1;
+ }
+
+ r = (pthread_rwlock_t *) (((uintptr_t) mem + __alignof (pthread_rwlock_t))
+ & ~(__alignof (pthread_rwlock_t) - 1));
+ /* The following assumes alignment for a mutex is at least as high
+ as that for a rwlock. Which is true in our case. */
+ m = (pthread_mutex_t *) (r + 1);
+
+ if (pthread_rwlockattr_init (&ra) != 0)
+ {
+ puts ("rwlockattr_init failed");
+ return 1;
+ }
+
+ if (pthread_rwlockattr_setpshared (&ra, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("rwlockattr_setpshared failed");
+ return 1;
+ }
+
+ if (pthread_rwlock_init (r, &ra) != 0)
+ {
+ puts ("rwlock_init failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_init (&ma) != 0)
+ {
+ puts ("rwlockattr_init failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_setpshared (&ma, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("mutexattr_setpshared failed");
+ return 1;
+ }
+
+ if (pthread_mutex_init (m, &ma) != 0)
+ {
+ puts ("mutex_init failed");
+ return 1;
+ }
+
+ /* Lock the mutex. */
+ if (pthread_mutex_lock (m) != 0)
+ {
+ puts ("mutex_lock failed");
+ return 1;
+ }
+
+ puts ("going to fork now");
+ pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ return 1;
+ }
+ else if (pid == 0)
+ {
+ /* Lock the mutex. */
+ if (pthread_mutex_lock (m) != 0)
+ {
+ puts ("child: mutex_lock failed");
+ return 1;
+ }
+
+ /* Try to get the rwlock. */
+ if (pthread_rwlock_trywrlock (r) == 0)
+ {
+ puts ("rwlock_trywrlock succeeded");
+ return 1;
+ }
+
+ /* Try again. */
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 500000000 };
+ int e = pthread_rwlock_timedwrlock (r, &ts);
+ if (e == 0)
+ {
+ puts ("rwlock_timedwrlock succeeded");
+ return 1;
+ }
+ if (e != ETIMEDOUT)
+ {
+ puts ("rwlock_timedwrlock didn't return ETIMEDOUT");
+ status = 1;
+ }
+
+ if (pthread_rwlock_tryrdlock (r) == 0)
+ {
+ puts ("rwlock_tryrdlock succeeded");
+ return 1;
+ }
+
+ e = pthread_rwlock_timedrdlock (r, &ts);
+ if (e == 0)
+ {
+ puts ("rwlock_timedrdlock succeeded");
+ return 1;
+ }
+ if (e != ETIMEDOUT)
+ {
+ puts ("rwlock_timedrdlock didn't return ETIMEDOUT");
+ status = 1;
+ }
+ }
+ else
+ {
+ /* Lock the rwlock for writing. */
+ if (pthread_rwlock_wrlock (r) != 0)
+ {
+ puts ("rwlock_wrlock failed");
+ kill (pid, SIGTERM);
+ return 1;
+ }
+
+ /* Allow the child to run. */
+ if (pthread_mutex_unlock (m) != 0)
+ {
+ puts ("mutex_unlock failed");
+ kill (pid, SIGTERM);
+ return 1;
+ }
+
+ /* Just wait for the child. */
+ if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+ {
+ puts ("waitpid failed");
+ kill (pid, SIGTERM);
+ return 1;
+ }
+ }
+
+ return status;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-rwlock13.c
@@ -0,0 +1,70 @@
+/* Copyright (C) 2004-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+
+
+static int
+do_test (void)
+{
+ pthread_rwlock_t r;
+ int ret;
+
+ memset (&r, 0xaa, sizeof (r));
+ if ((ret = pthread_rwlock_init (&r, NULL)) != 0)
+ {
+ printf ("rwlock_init failed: %d\n", ret);
+ return 1;
+ }
+
+ if ((ret = pthread_rwlock_rdlock (&r)) != 0)
+ {
+ printf ("rwlock_rdlock failed: %d\n", ret);
+ return 1;
+ }
+
+ if ((ret = pthread_rwlock_unlock (&r)) != 0)
+ {
+ printf ("rwlock_unlock failed: %d\n", ret);
+ return 1;
+ }
+
+ if ((ret = pthread_rwlock_wrlock (&r)) != 0)
+ {
+ printf ("rwlock_wrlock failed: %d\n", ret);
+ return 1;
+ }
+
+ if ((ret = pthread_rwlock_unlock (&r)) != 0)
+ {
+ printf ("second rwlock_unlock failed: %d\n", ret);
+ return 1;
+ }
+
+ if ((ret = pthread_rwlock_destroy (&r)) != 0)
+ {
+ printf ("second rwlock_destroy failed: %d\n", ret);
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-rwlock14.c
@@ -0,0 +1,168 @@
+/* Copyright (C) 2004-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+
+static pthread_barrier_t b;
+static pthread_rwlock_t r = PTHREAD_RWLOCK_INITIALIZER;
+
+
+static void *
+tf (void *arg)
+{
+ /* Lock the read-write lock. */
+ if (pthread_rwlock_wrlock (&r) != 0)
+ {
+ puts ("tf: cannot lock rwlock");
+ exit (EXIT_FAILURE);
+ }
+
+ pthread_t mt = *(pthread_t *) arg;
+
+ pthread_barrier_wait (&b);
+
+ /* This call will never return. */
+ pthread_join (mt, NULL);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ int result = 0;
+ struct timespec ts;
+
+ if (clock_gettime (CLOCK_REALTIME, &ts) != 0)
+ {
+ puts ("clock_gettime failed");
+ return 1;
+ }
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ pthread_t me = pthread_self ();
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, &me) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ /* Wait until the rwlock is locked. */
+ pthread_barrier_wait (&b);
+
+ ts.tv_nsec = -1;
+
+ int e = pthread_rwlock_timedrdlock (&r, &ts);
+ if (e == 0)
+ {
+ puts ("first rwlock_timedrdlock did not fail");
+ result = 1;
+ }
+ else if (e != EINVAL)
+ {
+ puts ("first rwlock_timedrdlock did not return EINVAL");
+ result = 1;
+ }
+
+ e = pthread_rwlock_timedwrlock (&r, &ts);
+ if (e == 0)
+ {
+ puts ("first rwlock_timedwrlock did not fail");
+ result = 1;
+ }
+ else if (e != EINVAL)
+ {
+ puts ("first rwlock_timedwrlock did not return EINVAL");
+ result = 1;
+ }
+
+ ts.tv_nsec = 1000000000;
+
+ e = pthread_rwlock_timedrdlock (&r, &ts);
+ if (e == 0)
+ {
+ puts ("second rwlock_timedrdlock did not fail");
+ result = 1;
+ }
+ else if (e != EINVAL)
+ {
+ puts ("second rwlock_timedrdlock did not return EINVAL");
+ result = 1;
+ }
+
+ e = pthread_rwlock_timedrdlock (&r, &ts);
+ if (e == 0)
+ {
+ puts ("second rwlock_timedrdlock did not fail");
+ result = 1;
+ }
+ else if (e != EINVAL)
+ {
+ puts ("second rwlock_timedrdlock did not return EINVAL");
+ result = 1;
+ }
+
+ ts.tv_nsec = (__typeof (ts.tv_nsec)) 0x100001000LL;
+ if ((__typeof (ts.tv_nsec)) 0x100001000LL != 0x100001000LL)
+ ts.tv_nsec = 2000000000;
+
+ e = pthread_rwlock_timedrdlock (&r, &ts);
+ if (e == 0)
+ {
+ puts ("third rwlock_timedrdlock did not fail");
+ result = 1;
+ }
+ else if (e != EINVAL)
+ {
+ puts ("third rwlock_timedrdlock did not return EINVAL");
+ result = 1;
+ }
+
+ e = pthread_rwlock_timedrdlock (&r, &ts);
+ if (e == 0)
+ {
+ puts ("third rwlock_timedrdlock did not fail");
+ result = 1;
+ }
+ else if (e != EINVAL)
+ {
+ puts ("third rwlock_timedrdlock did not return EINVAL");
+ result = 1;
+ }
+
+ if (result == 0)
+ puts ("no bugs");
+
+ return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-rwlock2.c
@@ -0,0 +1,168 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+
+
+static int
+do_test (void)
+{
+ pthread_rwlock_t r;
+ pthread_rwlockattr_t at;
+ int e;
+
+ if (pthread_rwlockattr_init (&at) != 0)
+ {
+ puts ("rwlockattr_init failed");
+ return 1;
+ }
+ puts ("rwlockattr_init succeeded");
+
+#ifndef TYPE
+# define TYPE PTHREAD_RWLOCK_PREFER_READER_NP
+#endif
+
+ if (pthread_rwlockattr_setkind_np (&at, TYPE) != 0)
+ {
+ puts ("rwlockattr_setkind failed");
+ return 1;
+ }
+ puts ("rwlockattr_setkind succeeded");
+
+ if (pthread_rwlock_init (&r, &at) != 0)
+ {
+ puts ("rwlock_init failed");
+ return 1;
+ }
+ puts ("rwlock_init succeeded");
+
+ if (pthread_rwlockattr_destroy (&at) != 0)
+ {
+ puts ("rwlockattr_destroy failed");
+ return 1;
+ }
+ puts ("rwlockattr_destroy succeeded");
+
+ if (pthread_rwlock_wrlock (&r) != 0)
+ {
+ puts ("1st rwlock_wrlock failed");
+ return 1;
+ }
+ puts ("1st rwlock_wrlock succeeded");
+
+ e = pthread_rwlock_tryrdlock (&r);
+ if (e == 0)
+ {
+ puts ("rwlock_tryrdlock on rwlock with writer succeeded");
+ return 1;
+ }
+ if (e != EBUSY)
+ {
+ puts ("rwlock_tryrdlock on rwlock with writer return value != EBUSY");
+ return 1;
+ }
+ puts ("rwlock_tryrdlock on rwlock with writer failed with EBUSY");
+
+ e = pthread_rwlock_trywrlock (&r);
+ if (e == 0)
+ {
+ puts ("rwlock_trywrlock on rwlock with writer succeeded");
+ return 1;
+ }
+ if (e != EBUSY)
+ {
+ puts ("rwlock_trywrlock on rwlock with writer return value != EBUSY");
+ return 1;
+ }
+ puts ("rwlock_trywrlock on rwlock with writer failed with EBUSY");
+
+ if (pthread_rwlock_unlock (&r) != 0)
+ {
+ puts ("1st rwlock_unlock failed");
+ return 1;
+ }
+ puts ("1st rwlock_unlock succeeded");
+
+ if (pthread_rwlock_tryrdlock (&r) != 0)
+ {
+ puts ("rwlock_tryrdlock on unlocked rwlock failed");
+ return 1;
+ }
+ puts ("rwlock_tryrdlock on unlocked rwlock succeeded");
+
+ e = pthread_rwlock_trywrlock (&r);
+ if (e == 0)
+ {
+ puts ("rwlock_trywrlock on rwlock with reader succeeded");
+ return 1;
+ }
+ if (e != EBUSY)
+ {
+ puts ("rwlock_trywrlock on rwlock with reader return value != EBUSY");
+ return 1;
+ }
+ puts ("rwlock_trywrlock on rwlock with reader failed with EBUSY");
+
+ if (pthread_rwlock_unlock (&r) != 0)
+ {
+ puts ("2nd rwlock_unlock failed");
+ return 1;
+ }
+ puts ("2nd rwlock_unlock succeeded");
+
+ if (pthread_rwlock_trywrlock (&r) != 0)
+ {
+ puts ("rwlock_trywrlock on unlocked rwlock failed");
+ return 1;
+ }
+ puts ("rwlock_trywrlock on unlocked rwlock succeeded");
+
+ e = pthread_rwlock_tryrdlock (&r);
+ if (e == 0)
+ {
+ puts ("rwlock_tryrdlock on rwlock with writer succeeded");
+ return 1;
+ }
+ if (e != EBUSY)
+ {
+ puts ("rwlock_tryrdlock on rwlock with writer return value != EBUSY");
+ return 1;
+ }
+ puts ("rwlock_tryrdlock on rwlock with writer failed with EBUSY");
+
+ if (pthread_rwlock_unlock (&r) != 0)
+ {
+ puts ("3rd rwlock_unlock failed");
+ return 1;
+ }
+ puts ("3rd rwlock_unlock succeeded");
+
+ if (pthread_rwlock_destroy (&r) != 0)
+ {
+ puts ("rwlock_destroy failed");
+ return 1;
+ }
+ puts ("rwlock_destroy succeeded");
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-rwlock2a.c
@@ -0,0 +1,2 @@
+#define TYPE PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP
+#include "tst-rwlock2.c"
--- /dev/null
+++ b/fbtl/tst-rwlock3.c
@@ -0,0 +1,92 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* This test case checks more than standard compliance. An
+ implementation may provide this service but it is not required to
+ do so. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+
+
+static int
+do_test (void)
+{
+ pthread_rwlock_t r;
+ int e;
+
+ if (pthread_rwlock_init (&r, NULL) != 0)
+ {
+ puts ("rwlock_init failed");
+ return 1;
+ }
+ puts ("rwlock_init succeeded");
+
+ if (pthread_rwlock_trywrlock (&r) != 0)
+ {
+ puts ("rwlock_trywrlock on unlocked rwlock failed");
+ return 1;
+ }
+ puts ("rwlock_trywrlock on unlocked rwlock succeeded");
+
+ e = pthread_rwlock_rdlock (&r);
+ if (e == 0)
+ {
+ puts ("rwlock_rdlock on rwlock with writer succeeded");
+ return 1;
+ }
+ if (e != EDEADLK)
+ {
+ puts ("rwlock_rdlock on rwlock with writer failed != EDEADLK");
+ return 1;
+ }
+ puts ("rwlock_rdlock on rwlock with writer failed with EDEADLK");
+
+ e = pthread_rwlock_wrlock (&r);
+ if (e == 0)
+ {
+ puts ("rwlock_wrlock on rwlock with writer succeeded");
+ return 1;
+ }
+ if (e != EDEADLK)
+ {
+ puts ("rwlock_wrlock on rwlock with writer failed != EDEADLK");
+ return 1;
+ }
+ puts ("rwlock_wrlock on rwlock with writer failed with EDEADLK");
+
+ if (pthread_rwlock_unlock (&r) != 0)
+ {
+ puts ("rwlock_unlock failed");
+ return 1;
+ }
+ puts ("rwlock_unlock succeeded");
+
+ if (pthread_rwlock_destroy (&r) != 0)
+ {
+ puts ("rwlock_destroy failed");
+ return 1;
+ }
+ puts ("rwlock_destroy succeeded");
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-rwlock4.c
@@ -0,0 +1,189 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+
+static int
+do_test (void)
+{
+ size_t ps = sysconf (_SC_PAGESIZE);
+ char tmpfname[] = "/tmp/tst-rwlock4.XXXXXX";
+ char data[ps];
+ void *mem;
+ int fd;
+ pthread_rwlock_t *r;
+ pthread_rwlockattr_t a;
+ pid_t pid;
+ char *p;
+ int err;
+ int s;
+
+ fd = mkstemp (tmpfname);
+ if (fd == -1)
+ {
+ printf ("cannot open temporary file: %m\n");
+ return 1;
+ }
+
+ /* Make sure it is always removed. */
+ unlink (tmpfname);
+
+ /* Create one page of data. */
+ memset (data, '\0', ps);
+
+ /* Write the data to the file. */
+ if (write (fd, data, ps) != (ssize_t) ps)
+ {
+ puts ("short write");
+ return 1;
+ }
+
+ mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (mem == MAP_FAILED)
+ {
+ printf ("mmap failed: %m\n");
+ return 1;
+ }
+
+ r = (pthread_rwlock_t *) (((uintptr_t) mem + __alignof (pthread_rwlock_t))
+ & ~(__alignof (pthread_rwlock_t) - 1));
+ p = (char *) (r + 1);
+
+ if (pthread_rwlockattr_init (&a) != 0)
+ {
+ puts ("rwlockattr_init failed");
+ return 1;
+ }
+
+ if (pthread_rwlockattr_getpshared (&a, &s) != 0)
+ {
+ puts ("1st rwlockattr_getpshared failed");
+ return 1;
+ }
+
+ if (s != PTHREAD_PROCESS_PRIVATE)
+ {
+ puts ("default pshared value wrong");
+ return 1;
+ }
+
+ if (pthread_rwlockattr_setpshared (&a, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("rwlockattr_setpshared failed");
+ return 1;
+ }
+
+ if (pthread_rwlockattr_getpshared (&a, &s) != 0)
+ {
+ puts ("2nd rwlockattr_getpshared failed");
+ return 1;
+ }
+
+ if (s != PTHREAD_PROCESS_SHARED)
+ {
+ puts ("pshared value after setpshared call wrong");
+ return 1;
+ }
+
+ if (pthread_rwlock_init (r, &a) != 0)
+ {
+ puts ("rwlock_init failed");
+ return 1;
+ }
+
+ if (pthread_rwlock_rdlock (r) != 0)
+ {
+ puts ("rwlock_rdlock failed");
+ return 1;
+ }
+
+ if (pthread_rwlockattr_destroy (&a) != 0)
+ {
+ puts ("rwlockattr_destroy failed");
+ return 1;
+ }
+
+ err = pthread_rwlock_trywrlock (r);
+ if (err == 0)
+ {
+ puts ("rwlock_trywrlock succeeded");
+ return 1;
+ }
+ else if (err != EBUSY)
+ {
+ puts ("rwlock_trywrlock didn't return EBUSY");
+ return 1;
+ }
+
+ *p = 0;
+
+ puts ("going to fork now");
+ pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ return 1;
+ }
+ else if (pid == 0)
+ {
+ /* Play some lock ping-pong. It's our turn to unlock first. */
+ if ((*p)++ != 0)
+ {
+ puts ("child: *p != 0");
+ return 1;
+ }
+
+ if (pthread_rwlock_unlock (r) != 0)
+ {
+ puts ("child: 1st rwlock_unlock failed");
+ return 1;
+ }
+
+ puts ("child done");
+ }
+ else
+ {
+ if (pthread_rwlock_wrlock (r) != 0)
+ {
+ puts ("parent: rwlock_wrlock failed");
+ return 1;
+ }
+
+ if (*p != 1)
+ {
+ puts ("*p != 1");
+ return 1;
+ }
+
+ puts ("parent done");
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-rwlock5.c
@@ -0,0 +1,84 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+static pthread_rwlock_t r;
+
+
+static void *
+tf (void *arg)
+{
+ if (pthread_rwlock_wrlock (&r) == 0)
+ {
+ puts ("child: rwlock_wrlock succeeded");
+ exit (1);
+ }
+
+ puts ("child: rwlock_wrlock returned");
+
+ exit (1);
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_rwlock_init (&r, NULL) != 0)
+ {
+ puts ("rwlock_init failed");
+ return 1;
+ }
+
+ if (pthread_rwlock_wrlock (&r) != 0)
+ {
+ puts ("rwlock_wrlock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("mutex_lock failed");
+ return 1;
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ delayed_exit (1);
+ /* This call should never return. */
+ xpthread_mutex_lock (&m);
+
+ puts ("2nd mutex_lock returned");
+ return 1;
+}
--- /dev/null
+++ b/fbtl/tst-rwlock6.c
@@ -0,0 +1,225 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+
+
+static int kind[] =
+ {
+ PTHREAD_RWLOCK_PREFER_READER_NP,
+ PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,
+ PTHREAD_RWLOCK_PREFER_WRITER_NP,
+ };
+
+
+static void *
+tf (void *arg)
+{
+ pthread_rwlock_t *r = arg;
+
+ /* Timeout: 0.3 secs. */
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_nsec += 300000000;
+ if (ts.tv_nsec >= 1000000000)
+ {
+ ts.tv_nsec -= 1000000000;
+ ++ts.tv_sec;
+ }
+
+ puts ("child calling timedrdlock");
+
+ int err = pthread_rwlock_timedrdlock (r, &ts);
+ if (err == 0)
+ {
+ puts ("rwlock_timedrdlock returned");
+ pthread_exit ((void *) 1l);
+ }
+
+ if (err != ETIMEDOUT)
+ {
+ printf ("err = %s (%d), expected %s (%d)\n",
+ strerror (err), err, strerror (ETIMEDOUT), ETIMEDOUT);
+ pthread_exit ((void *) 1l);
+ }
+
+ puts ("1st child timedrdlock done");
+
+ struct timeval tv2;
+ (void) gettimeofday (&tv2, NULL);
+
+ timersub (&tv2, &tv, &tv);
+
+ if (tv.tv_usec < 200000)
+ {
+ puts ("timeout too short");
+ pthread_exit ((void *) 1l);
+ }
+
+ (void) gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_sec += 10;
+ /* Note that the following operation makes ts invalid. */
+ ts.tv_nsec += 1000000000;
+
+ err = pthread_rwlock_timedrdlock (r, &ts);
+ if (err == 0)
+ {
+ puts ("2nd timedrdlock succeeded");
+ pthread_exit ((void *) 1l);
+ }
+ if (err != EINVAL)
+ {
+ puts ("2nd timedrdlock did not return EINVAL");
+ pthread_exit ((void *) 1l);
+ }
+
+ puts ("2nd child timedrdlock done");
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ size_t cnt;
+ for (cnt = 0; cnt < sizeof (kind) / sizeof (kind[0]); ++cnt)
+ {
+ pthread_rwlock_t r;
+ pthread_rwlockattr_t a;
+
+ if (pthread_rwlockattr_init (&a) != 0)
+ {
+ printf ("round %Zu: rwlockattr_t failed\n", cnt);
+ exit (1);
+ }
+
+ if (pthread_rwlockattr_setkind_np (&a, kind[cnt]) != 0)
+ {
+ printf ("round %Zu: rwlockattr_setkind failed\n", cnt);
+ exit (1);
+ }
+
+ if (pthread_rwlock_init (&r, &a) != 0)
+ {
+ printf ("round %Zu: rwlock_init failed\n", cnt);
+ exit (1);
+ }
+
+ if (pthread_rwlockattr_destroy (&a) != 0)
+ {
+ printf ("round %Zu: rwlockattr_destroy failed\n", cnt);
+ exit (1);
+ }
+
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+ ++ts.tv_sec;
+
+ /* Get a write lock. */
+ int e = pthread_rwlock_timedwrlock (&r, &ts);
+ if (e != 0)
+ {
+ printf ("round %Zu: rwlock_timedwrlock failed (%d)\n", cnt, e);
+ exit (1);
+ }
+
+ puts ("1st timedwrlock done");
+
+ (void) gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ++ts.tv_sec;
+ e = pthread_rwlock_timedrdlock (&r, &ts);
+ if (e == 0)
+ {
+ puts ("timedrdlock succeeded");
+ exit (1);
+ }
+ if (e != EDEADLK)
+ {
+ puts ("timedrdlock did not return EDEADLK");
+ exit (1);
+ }
+
+ puts ("1st timedrdlock done");
+
+ (void) gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ++ts.tv_sec;
+ e = pthread_rwlock_timedwrlock (&r, &ts);
+ if (e == 0)
+ {
+ puts ("2nd timedwrlock succeeded");
+ exit (1);
+ }
+ if (e != EDEADLK)
+ {
+ puts ("2nd timedwrlock did not return EDEADLK");
+ exit (1);
+ }
+
+ puts ("2nd timedwrlock done");
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, &r) != 0)
+ {
+ printf ("round %Zu: create failed\n", cnt);
+ exit (1);
+ }
+
+ puts ("started thread");
+
+ void *status;
+ if (pthread_join (th, &status) != 0)
+ {
+ printf ("round %Zu: join failed\n", cnt);
+ exit (1);
+ }
+ if (status != NULL)
+ {
+ printf ("failure in round %Zu\n", cnt);
+ exit (1);
+ }
+
+ puts ("joined thread");
+
+ if (pthread_rwlock_destroy (&r) != 0)
+ {
+ printf ("round %Zu: rwlock_destroy failed\n", cnt);
+ exit (1);
+ }
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-rwlock7.c
@@ -0,0 +1,181 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+
+
+static int kind[] =
+ {
+ PTHREAD_RWLOCK_PREFER_READER_NP,
+ PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,
+ PTHREAD_RWLOCK_PREFER_WRITER_NP,
+ };
+
+
+static void *
+tf (void *arg)
+{
+ pthread_rwlock_t *r = arg;
+
+ /* Timeout: 0.3 secs. */
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_nsec += 300000000;
+ if (ts.tv_nsec >= 1000000000)
+ {
+ ts.tv_nsec -= 1000000000;
+ ++ts.tv_sec;
+ }
+
+ int err = pthread_rwlock_timedwrlock (r, &ts);
+ if (err == 0)
+ {
+ puts ("rwlock_timedwrlock returned");
+ pthread_exit ((void *) 1l);
+ }
+
+ if (err != ETIMEDOUT)
+ {
+ printf ("err = %s (%d), expected %s (%d)\n",
+ strerror (err), err, strerror (ETIMEDOUT), ETIMEDOUT);
+ pthread_exit ((void *) 1l);
+ }
+ puts ("child: timedwrlock failed with ETIMEDOUT");
+
+ struct timeval tv2;
+ (void) gettimeofday (&tv2, NULL);
+
+ timersub (&tv2, &tv, &tv);
+
+ if (tv.tv_usec < 200000)
+ {
+ puts ("timeout too short");
+ pthread_exit ((void *) 1l);
+ }
+
+ (void) gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_sec += 10;
+ /* Note that the following operation makes ts invalid. */
+ ts.tv_nsec += 1000000000;
+
+ err = pthread_rwlock_timedwrlock (r, &ts);
+ if (err == 0)
+ {
+ puts ("2nd timedwrlock succeeded");
+ pthread_exit ((void *) 1l);
+ }
+ if (err != EINVAL)
+ {
+ puts ("2nd timedwrlock did not return EINVAL");
+ pthread_exit ((void *) 1l);
+ }
+ puts ("child: timedwrlock failed with EINVAL");
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ size_t cnt;
+ for (cnt = 0; cnt < sizeof (kind) / sizeof (kind[0]); ++cnt)
+ {
+ pthread_rwlock_t r;
+ pthread_rwlockattr_t a;
+
+ if (pthread_rwlockattr_init (&a) != 0)
+ {
+ printf ("round %Zu: rwlockattr_t failed\n", cnt);
+ exit (1);
+ }
+
+ if (pthread_rwlockattr_setkind_np (&a, kind[cnt]) != 0)
+ {
+ printf ("round %Zu: rwlockattr_setkind failed\n", cnt);
+ exit (1);
+ }
+
+ if (pthread_rwlock_init (&r, &a) != 0)
+ {
+ printf ("round %Zu: rwlock_init failed\n", cnt);
+ exit (1);
+ }
+
+ if (pthread_rwlockattr_destroy (&a) != 0)
+ {
+ printf ("round %Zu: rwlockattr_destroy failed\n", cnt);
+ exit (1);
+ }
+
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+ ++ts.tv_sec;
+
+ /* Get a read lock. */
+ if (pthread_rwlock_timedrdlock (&r, &ts) != 0)
+ {
+ printf ("round %Zu: rwlock_timedrdlock failed\n", cnt);
+ exit (1);
+ }
+ printf ("%zu: got timedrdlock\n", cnt);
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, &r) != 0)
+ {
+ printf ("round %Zu: create failed\n", cnt);
+ exit (1);
+ }
+
+ void *status;
+ if (pthread_join (th, &status) != 0)
+ {
+ printf ("round %Zu: join failed\n", cnt);
+ exit (1);
+ }
+ if (status != NULL)
+ {
+ printf ("failure in round %Zu\n", cnt);
+ exit (1);
+ }
+
+ if (pthread_rwlock_destroy (&r) != 0)
+ {
+ printf ("round %Zu: rwlock_destroy failed\n", cnt);
+ exit (1);
+ }
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-rwlock8.c
@@ -0,0 +1,163 @@
+/* Test program for timedout read/write lock functions.
+ Copyright (C) 2000-2013 Free Software Foundation, Inc.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <error.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+
+#define NWRITERS 15
+#define WRITETRIES 10
+#define NREADERS 15
+#define READTRIES 15
+
+#define DELAY 1000000
+
+#ifndef INIT
+# define INIT PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
+#endif
+
+static pthread_rwlock_t lock = INIT;
+
+
+static void *
+writer_thread (void *nr)
+{
+ struct timespec delay;
+ int n;
+
+ delay.tv_sec = 0;
+ delay.tv_nsec = DELAY;
+
+ for (n = 0; n < WRITETRIES; ++n)
+ {
+ printf ("writer thread %ld tries again\n", (long int) nr);
+
+ if (pthread_rwlock_wrlock (&lock) != 0)
+ {
+ puts ("wrlock failed");
+ exit (1);
+ }
+
+ printf ("writer thread %ld succeeded\n", (long int) nr);
+
+ nanosleep (&delay, NULL);
+
+ if (pthread_rwlock_unlock (&lock) != 0)
+ {
+ puts ("unlock for writer failed");
+ exit (1);
+ }
+
+ printf ("writer thread %ld released\n", (long int) nr);
+ }
+
+ return NULL;
+}
+
+
+static void *
+reader_thread (void *nr)
+{
+ struct timespec delay;
+ int n;
+
+ delay.tv_sec = 0;
+ delay.tv_nsec = DELAY;
+
+ for (n = 0; n < READTRIES; ++n)
+ {
+ printf ("reader thread %ld tries again\n", (long int) nr);
+
+ if (pthread_rwlock_rdlock (&lock) != 0)
+ {
+ puts ("rdlock failed");
+ exit (1);
+ }
+
+ printf ("reader thread %ld succeeded\n", (long int) nr);
+
+ nanosleep (&delay, NULL);
+
+ if (pthread_rwlock_unlock (&lock) != 0)
+ {
+ puts ("unlock for reader failed");
+ exit (1);
+ }
+
+ printf ("reader thread %ld released\n", (long int) nr);
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t thwr[NWRITERS];
+ pthread_t thrd[NREADERS];
+ int n;
+ void *res;
+
+ /* Make standard error the same as standard output. */
+ dup2 (1, 2);
+
+ /* Make sure we see all message, even those on stdout. */
+ setvbuf (stdout, NULL, _IONBF, 0);
+
+ for (n = 0; n < NWRITERS; ++n)
+ if (pthread_create (&thwr[n], NULL, writer_thread,
+ (void *) (long int) n) != 0)
+ {
+ puts ("writer create failed");
+ exit (1);
+ }
+
+ for (n = 0; n < NREADERS; ++n)
+ if (pthread_create (&thrd[n], NULL, reader_thread,
+ (void *) (long int) n) != 0)
+ {
+ puts ("reader create failed");
+ exit (1);
+ }
+
+ /* Wait for all the threads. */
+ for (n = 0; n < NWRITERS; ++n)
+ if (pthread_join (thwr[n], &res) != 0)
+ {
+ puts ("writer join failed");
+ exit (1);
+ }
+ for (n = 0; n < NREADERS; ++n)
+ if (pthread_join (thrd[n], &res) != 0)
+ {
+ puts ("reader join failed");
+ exit (1);
+ }
+
+ return 0;
+}
+
+#define TIMEOUT 30
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-rwlock9.c
@@ -0,0 +1,202 @@
+/* Test program for timedout read/write lock functions.
+ Copyright (C) 2000-2013 Free Software Foundation, Inc.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <error.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+
+#define NWRITERS 15
+#define WRITETRIES 10
+#define NREADERS 15
+#define READTRIES 15
+
+#define TIMEOUT 1000000
+#define DELAY 1000000
+
+#ifndef INIT
+# define INIT PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
+#endif
+
+static pthread_rwlock_t lock = INIT;
+
+
+static void *
+writer_thread (void *nr)
+{
+ struct timespec ts;
+ struct timespec delay;
+ int n;
+
+ delay.tv_sec = 0;
+ delay.tv_nsec = DELAY;
+
+ for (n = 0; n < WRITETRIES; ++n)
+ {
+ int e;
+ do
+ {
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+ ts.tv_nsec += 2 * TIMEOUT;
+ if (ts.tv_nsec >= 1000000000)
+ {
+ ts.tv_nsec -= 1000000000;
+ ++ts.tv_sec;
+ }
+
+ printf ("writer thread %ld tries again\n", (long int) nr);
+
+ e = pthread_rwlock_timedwrlock (&lock, &ts);
+ if (e != 0 && e != ETIMEDOUT)
+ {
+ puts ("timedwrlock failed");
+ exit (1);
+ }
+ }
+ while (e == ETIMEDOUT);
+
+ printf ("writer thread %ld succeeded\n", (long int) nr);
+
+ nanosleep (&delay, NULL);
+
+ if (pthread_rwlock_unlock (&lock) != 0)
+ {
+ puts ("unlock for writer failed");
+ exit (1);
+ }
+
+ printf ("writer thread %ld released\n", (long int) nr);
+ }
+
+ return NULL;
+}
+
+
+static void *
+reader_thread (void *nr)
+{
+ struct timespec ts;
+ struct timespec delay;
+ int n;
+
+ delay.tv_sec = 0;
+ delay.tv_nsec = DELAY;
+
+ for (n = 0; n < READTRIES; ++n)
+ {
+ int e;
+ do
+ {
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+ ts.tv_nsec += TIMEOUT;
+ if (ts.tv_nsec >= 1000000000)
+ {
+ ts.tv_nsec -= 1000000000;
+ ++ts.tv_sec;
+ }
+
+ printf ("reader thread %ld tries again\n", (long int) nr);
+
+ e = pthread_rwlock_timedrdlock (&lock, &ts);
+ if (e != 0 && e != ETIMEDOUT)
+ {
+ puts ("timedrdlock failed");
+ exit (1);
+ }
+ }
+ while (e == ETIMEDOUT);
+
+ printf ("reader thread %ld succeeded\n", (long int) nr);
+
+ nanosleep (&delay, NULL);
+
+ if (pthread_rwlock_unlock (&lock) != 0)
+ {
+ puts ("unlock for reader failed");
+ exit (1);
+ }
+
+ printf ("reader thread %ld released\n", (long int) nr);
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t thwr[NWRITERS];
+ pthread_t thrd[NREADERS];
+ int n;
+ void *res;
+
+ /* Make standard error the same as standard output. */
+ dup2 (1, 2);
+
+ /* Make sure we see all message, even those on stdout. */
+ setvbuf (stdout, NULL, _IONBF, 0);
+
+ for (n = 0; n < NWRITERS; ++n)
+ if (pthread_create (&thwr[n], NULL, writer_thread,
+ (void *) (long int) n) != 0)
+ {
+ puts ("writer create failed");
+ exit (1);
+ }
+
+ for (n = 0; n < NREADERS; ++n)
+ if (pthread_create (&thrd[n], NULL, reader_thread,
+ (void *) (long int) n) != 0)
+ {
+ puts ("reader create failed");
+ exit (1);
+ }
+
+ /* Wait for all the threads. */
+ for (n = 0; n < NWRITERS; ++n)
+ if (pthread_join (thwr[n], &res) != 0)
+ {
+ puts ("writer join failed");
+ exit (1);
+ }
+ for (n = 0; n < NREADERS; ++n)
+ if (pthread_join (thrd[n], &res) != 0)
+ {
+ puts ("reader join failed");
+ exit (1);
+ }
+
+ return 0;
+}
+
+#undef TIMEOUT
+#define TIMEOUT 30
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-sched1.c
@@ -0,0 +1,97 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+
+static int global;
+
+static void *
+tf (void *a)
+{
+ global = 1;
+
+ return 0;
+}
+
+
+int
+do_test (void)
+{
+ pthread_t th;
+ pthread_attr_t at;
+
+ if (pthread_attr_init (&at) != 0)
+ {
+ puts ("attr_init failed");
+ return 1;
+ }
+
+ if (pthread_attr_setschedpolicy (&at, SCHED_OTHER) != 0)
+ {
+ puts ("attr_setschedpolicy failed");
+ return 1;
+ }
+
+ struct sched_param pa;
+ if (sched_getparam (getpid (), &pa) != 0)
+ {
+ puts ("sched_getschedparam failed");
+ return 1;
+ }
+
+ if (pthread_attr_setschedparam (&at, &pa) != 0)
+ {
+ puts ("attr_setschedparam failed");
+ return 1;
+ }
+
+ if (pthread_attr_setinheritsched (&at, PTHREAD_EXPLICIT_SCHED) != 0)
+ {
+ puts ("attr_setinheritsched failed");
+ return 1;
+ }
+
+ if (pthread_create (&th, &at, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ int e = pthread_join (th, NULL);
+ if (e != 0)
+ {
+ printf ("join failed: %d\n", e);
+ return 1;
+ }
+
+ if (global == 0)
+ {
+ puts ("thread didn't run");
+ return 1;
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-sem1.c
@@ -0,0 +1,88 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+static int
+do_test (void)
+{
+ sem_t s;
+
+ if (sem_init (&s, 0, 1) == -1)
+ {
+ puts ("init failed");
+ return 1;
+ }
+
+ if (TEMP_FAILURE_RETRY (sem_wait (&s)) == -1)
+ {
+ puts ("1st wait failed");
+ return 1;
+ }
+
+ if (sem_post (&s) == -1)
+ {
+ puts ("1st post failed");
+ return 1;
+ }
+
+ if (TEMP_FAILURE_RETRY (sem_trywait (&s)) == -1)
+ {
+ puts ("1st trywait failed");
+ return 1;
+ }
+
+ errno = 0;
+ if (TEMP_FAILURE_RETRY (sem_trywait (&s)) != -1)
+ {
+ puts ("2nd trywait succeeded");
+ return 1;
+ }
+ else if (errno != EAGAIN)
+ {
+ puts ("2nd trywait did not set errno to EAGAIN");
+ return 1;
+ }
+
+ if (sem_post (&s) == -1)
+ {
+ puts ("2nd post failed");
+ return 1;
+ }
+
+ if (TEMP_FAILURE_RETRY (sem_wait (&s)) == -1)
+ {
+ puts ("2nd wait failed");
+ return 1;
+ }
+
+ if (sem_destroy (&s) == -1)
+ {
+ puts ("destroy failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-sem10.c
@@ -0,0 +1,87 @@
+/* Copyright (C) 2007-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@redhat.com>, 2007.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+
+static int
+do_test (void)
+{
+ sem_t s;
+ if (sem_init (&s, 0, 0) == -1)
+ {
+ puts ("sem_init failed");
+ return 1;
+ }
+
+ struct timeval tv;
+ if (gettimeofday (&tv, NULL) != 0)
+ {
+ puts ("gettimeofday failed");
+ return 1;
+ }
+
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+ /* Set ts to yesterday. */
+ ts.tv_sec -= 86400;
+
+ int type_before;
+ if (pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &type_before) != 0)
+ {
+ puts ("first pthread_setcanceltype failed");
+ return 1;
+ }
+
+ errno = 0;
+ if (TEMP_FAILURE_RETRY (sem_timedwait (&s, &ts)) != -1)
+ {
+ puts ("sem_timedwait succeeded");
+ return 1;
+ }
+ if (errno != ETIMEDOUT)
+ {
+ printf ("sem_timedwait return errno = %d instead of ETIMEDOUT\n",
+ errno);
+ return 1;
+ }
+
+ int type_after;
+ if (pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &type_after) != 0)
+ {
+ puts ("second pthread_setcanceltype failed");
+ return 1;
+ }
+ if (type_after != PTHREAD_CANCEL_DEFERRED)
+ {
+ puts ("sem_timedwait changed cancellation type");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-sem11-static.c
@@ -0,0 +1 @@
+#include "tst-sem11.c"
--- /dev/null
+++ b/fbtl/tst-sem11.c
@@ -0,0 +1,78 @@
+#include <semaphore.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <internaltypes.h>
+
+#ifndef SEM_WAIT
+# define SEM_WAIT(s) sem_wait (s)
+#endif
+
+static void *
+tf (void *arg)
+{
+#ifdef PREPARE
+ PREPARE
+#endif
+ SEM_WAIT (arg);
+ return NULL;
+}
+
+int
+main (void)
+{
+ int tries = 5;
+ pthread_t th;
+ union
+ {
+ sem_t s;
+ struct new_sem ns;
+ } u;
+ again:
+ if (sem_init (&u.s, 0, 0) != 0)
+ {
+ puts ("sem_init failed");
+ return 1;
+ }
+
+ if (u.ns.nwaiters != 0)
+ {
+ puts ("nwaiters not initialized");
+ return 1;
+ }
+
+ if (pthread_create (&th, NULL, tf, &u.s) != 0)
+ {
+ puts ("pthread_create failed");
+ return 1;
+ }
+
+ sleep (1);
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("pthread_cancel failed");
+ return 1;
+ }
+
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("pthread_join failed");
+ return 1;
+ }
+ if (r != PTHREAD_CANCELED && --tries > 0)
+ {
+ /* Maybe we get the scheduling right the next time. */
+ sem_destroy (&u.s);
+ goto again;
+ }
+
+ if (u.ns.nwaiters != 0)
+ {
+ puts ("nwaiters not reset");
+ return 1;
+ }
+
+ return 0;
+}
--- /dev/null
+++ b/fbtl/tst-sem12-static.c
@@ -0,0 +1 @@
+#include "tst-sem12.c"
--- /dev/null
+++ b/fbtl/tst-sem12.c
@@ -0,0 +1,14 @@
+#include <time.h>
+#include <sys/time.h>
+
+
+#define PREPARE \
+ struct timespec ts; \
+ struct timeval tv; \
+ gettimeofday (&tv, NULL); \
+ TIMEVAL_TO_TIMESPEC (&tv, &ts); \
+ ts.tv_sec += 60;
+
+#define SEM_WAIT(s) sem_timedwait (s, &ts)
+
+#include "tst-sem11.c"
--- /dev/null
+++ b/fbtl/tst-sem13.c
@@ -0,0 +1,65 @@
+#include <errno.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <internaltypes.h>
+
+
+static int
+do_test (void)
+{
+ union
+ {
+ sem_t s;
+ struct new_sem ns;
+ } u;
+
+ if (sem_init (&u.s, 0, 0) != 0)
+ {
+ puts ("sem_init failed");
+ return 1;
+ }
+
+ struct timespec ts = { 0, 1000000001 }; /* Invalid. */
+ errno = 0;
+ if (sem_timedwait (&u.s, &ts) >= 0)
+ {
+ puts ("sem_timedwait did not fail");
+ return 1;
+ }
+ if (errno != EINVAL)
+ {
+ perror ("sem_timedwait did not fail with EINVAL");
+ return 1;
+ }
+ if (u.ns.nwaiters != 0)
+ {
+ printf ("sem_timedwait modified nwaiters: %ld\n", u.ns.nwaiters);
+ return 1;
+ }
+
+ ts.tv_sec = /* Invalid. */ -2;
+ ts.tv_nsec = 0;
+ errno = 0;
+ if (sem_timedwait (&u.s, &ts) >= 0)
+ {
+ puts ("2nd sem_timedwait did not fail");
+ return 1;
+ }
+ if (errno != ETIMEDOUT)
+ {
+ perror ("2nd sem_timedwait did not fail with ETIMEDOUT");
+ return 1;
+ }
+ if (u.ns.nwaiters != 0)
+ {
+ printf ("2nd sem_timedwait modified nwaiters: %ld\n", u.ns.nwaiters);
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-sem14.c
@@ -0,0 +1,92 @@
+/* Test for sem_post race: bug 14532.
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+
+#define NTHREADS 10
+#define NITER 100000
+
+sem_t sem;
+int c;
+volatile int thread_fail;
+
+static void *
+tf (void *arg)
+{
+ for (int i = 0; i < NITER; i++)
+ {
+ if (sem_wait (&sem) != 0)
+ {
+ perror ("sem_wait");
+ thread_fail = 1;
+ }
+ ++c;
+ if (sem_post (&sem) != 0)
+ {
+ perror ("sem_post");
+ thread_fail = 1;
+ }
+ }
+ return NULL;
+}
+
+static int
+do_test (void)
+{
+ if (sem_init (&sem, 0, 0) != 0)
+ {
+ perror ("sem_init");
+ return 1;
+ }
+
+ pthread_t th[NTHREADS];
+ for (int i = 0; i < NTHREADS; i++)
+ {
+ if (pthread_create (&th[i], NULL, tf, NULL) != 0)
+ {
+ puts ("pthread_create failed");
+ return 1;
+ }
+ }
+
+ if (sem_post (&sem) != 0)
+ {
+ perror ("sem_post");
+ return 1;
+ }
+
+ for (int i = 0; i < NTHREADS; i++)
+ if (pthread_join (th[i], NULL) != 0)
+ {
+ puts ("pthread_join failed");
+ return 1;
+ }
+
+ if (c != NTHREADS * NITER)
+ {
+ printf ("c = %d, should be %d\n", c, NTHREADS * NITER);
+ return 1;
+ }
+ return thread_fail;
+}
+
+#define TIMEOUT 10
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-sem2.c
@@ -0,0 +1,53 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+static int
+do_test (void)
+{
+ sem_t s;
+
+ if (sem_init (&s, 0, 0) == -1)
+ {
+ puts ("init failed");
+ return 1;
+ }
+
+ delayed_exit (1);
+
+ if (TEMP_FAILURE_RETRY (sem_wait (&s)) == -1)
+ {
+ puts ("wait failed");
+ return 1;
+ }
+
+ /* We should never get here. */
+ puts ("wait succeeded");
+ return 1;
+}
--- /dev/null
+++ b/fbtl/tst-sem3.c
@@ -0,0 +1,141 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <semaphore.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+
+int
+main (void)
+{
+ size_t ps = sysconf (_SC_PAGESIZE);
+ char tmpfname[] = "/tmp/tst-sem3.XXXXXX";
+ char data[ps];
+ void *mem;
+ int fd;
+ sem_t *s;
+ pid_t pid;
+ char *p;
+
+ fd = mkstemp (tmpfname);
+ if (fd == -1)
+ {
+ printf ("cannot open temporary file: %m\n");
+ exit (1);
+ }
+
+ /* Make sure it is always removed. */
+ unlink (tmpfname);
+
+ /* Create one page of data. */
+ memset (data, '\0', ps);
+
+ /* Write the data to the file. */
+ if (write (fd, data, ps) != (ssize_t) ps)
+ {
+ puts ("short write");
+ exit (1);
+ }
+
+ mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (mem == MAP_FAILED)
+ {
+ printf ("mmap failed: %m\n");
+ exit (1);
+ }
+
+ s = (sem_t *) (((uintptr_t) mem + __alignof (sem_t))
+ & ~(__alignof (sem_t) - 1));
+ p = (char *) (s + 1);
+
+ if (sem_init (s, 1, 1) == -1)
+ {
+ puts ("init failed");
+ exit (1);
+ }
+
+ if (TEMP_FAILURE_RETRY (sem_wait (s)) == -1)
+ {
+ puts ("1st wait failed");
+ exit (1);
+ }
+
+ errno = 0;
+ if (TEMP_FAILURE_RETRY (sem_trywait (s)) != -1)
+ {
+ puts ("trywait succeeded");
+ exit (1);
+ }
+ else if (errno != EAGAIN)
+ {
+ puts ("trywait didn't return EAGAIN");
+ exit (1);
+ }
+
+ *p = 0;
+
+ puts ("going to fork now");
+ pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+ else if (pid == 0)
+ {
+ /* Play some lock ping-pong. It's our turn to unlock first. */
+ if ((*p)++ != 0)
+ {
+ puts ("child: *p != 0");
+ exit (1);
+ }
+
+ if (sem_post (s) == -1)
+ {
+ puts ("child: 1st post failed");
+ exit (1);
+ }
+
+ puts ("child done");
+ }
+ else
+ {
+ if (TEMP_FAILURE_RETRY (sem_wait (s)) == -1)
+ {
+ printf ("parent: 2nd wait failed: %m\n");
+ exit (1);
+ }
+
+ if (*p != 1)
+ {
+ puts ("*p != 1");
+ exit (1);
+ }
+
+ puts ("parent done");
+ }
+
+ exit (0);
+}
--- /dev/null
+++ b/fbtl/tst-sem4.c
@@ -0,0 +1,146 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static void
+remove_sem (int status, void *arg)
+{
+ sem_unlink (arg);
+}
+
+
+int
+main (void)
+{
+ sem_t *s;
+ sem_t *s2;
+ pid_t pid;
+ int val;
+
+ s = sem_open ("/glibc-tst-sem4", O_CREAT, 0600, 1);
+ if (s == SEM_FAILED)
+ {
+ if (errno == ENOSYS)
+ {
+ puts ("sem_open not supported. Oh well.");
+ return 0;
+ }
+
+ /* Maybe the shm filesystem has strict permissions. */
+ if (errno == EACCES)
+ {
+ puts ("sem_open not allowed. Oh well.");
+ return 0;
+ }
+
+ printf ("sem_open: %m\n");
+ return 1;
+ }
+
+ on_exit (remove_sem, (void *) "/glibc-tst-sem4");
+
+ /* We have the semaphore object. Now try again with O_EXCL, this
+ should fail. */
+ s2 = sem_open ("/glibc-tst-sem4", O_CREAT | O_EXCL, 0600, 1);
+ if (s2 != SEM_FAILED)
+ {
+ puts ("2nd sem_open didn't fail");
+ return 1;
+ }
+ if (errno != EEXIST)
+ {
+ puts ("2nd sem_open returned wrong error");
+ return 1;
+ }
+
+ /* Check the value. */
+ if (sem_getvalue (s, &val) == -1)
+ {
+ puts ("getvalue failed");
+ return 1;
+ }
+ if (val != 1)
+ {
+ printf ("initial value wrong: got %d, expected 1\n", val);
+ return 1;
+ }
+
+ if (TEMP_FAILURE_RETRY (sem_wait (s)) == -1)
+ {
+ puts ("1st sem_wait failed");
+ return 1;
+ }
+
+ pid = fork ();
+ if (pid == -1)
+ {
+ printf ("fork failed: %m\n");
+ return 1;
+ }
+
+ if (pid == 0)
+ {
+ /* Child. */
+
+ /* Check the value. */
+ if (sem_getvalue (s, &val) == -1)
+ {
+ puts ("child: getvalue failed");
+ return 1;
+ }
+ if (val != 0)
+ {
+ printf ("child: value wrong: got %d, expect 0\n", val);
+ return 1;
+ }
+
+ if (sem_post (s) == -1)
+ {
+ puts ("child: post failed");
+ return 1;
+ }
+ }
+ else
+ {
+ if (TEMP_FAILURE_RETRY (sem_wait (s)) == -1)
+ {
+ puts ("2nd sem_wait failed");
+ return 1;
+ }
+
+ if (sem_getvalue (s, &val) == -1)
+ {
+ puts ("parent: 2nd getvalue failed");
+ return 1;
+ }
+ if (val != 0)
+ {
+ printf ("parent: value wrong: got %d, expected 0\n", val);
+ return 1;
+ }
+ }
+
+ return 0;
+}
--- /dev/null
+++ b/fbtl/tst-sem5.c
@@ -0,0 +1,93 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+
+static int
+do_test (void)
+{
+ sem_t s;
+ struct timespec ts;
+ struct timeval tv;
+
+ if (sem_init (&s, 0, 1) == -1)
+ {
+ puts ("sem_init failed");
+ return 1;
+ }
+
+ if (TEMP_FAILURE_RETRY (sem_wait (&s)) == -1)
+ {
+ puts ("sem_wait failed");
+ return 1;
+ }
+
+ if (gettimeofday (&tv, NULL) != 0)
+ {
+ puts ("gettimeofday failed");
+ return 1;
+ }
+
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+ /* We wait for half a second. */
+ ts.tv_nsec += 500000000;
+ if (ts.tv_nsec >= 1000000000)
+ {
+ ++ts.tv_sec;
+ ts.tv_nsec -= 1000000000;
+ }
+
+ errno = 0;
+ if (TEMP_FAILURE_RETRY (sem_timedwait (&s, &ts)) != -1)
+ {
+ puts ("sem_timedwait succeeded");
+ return 1;
+ }
+ if (errno != ETIMEDOUT)
+ {
+ printf ("sem_timedwait return errno = %d instead of ETIMEDOUT\n",
+ errno);
+ return 1;
+ }
+
+ struct timespec ts2;
+ if (clock_gettime (CLOCK_REALTIME, &ts2) != 0)
+ {
+ puts ("clock_gettime failed");
+ return 1;
+ }
+
+ if (ts2.tv_sec < ts.tv_sec
+ || (ts2.tv_sec == ts.tv_sec && ts2.tv_nsec < ts.tv_nsec))
+ {
+ puts ("timeout too short");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-sem6.c
@@ -0,0 +1,80 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+static void
+handler (int sig)
+{
+ struct sigaction sa;
+
+ sa.sa_handler = SIG_DFL;
+ sa.sa_flags = 0;
+ sigemptyset (&sa.sa_mask);
+
+ sigaction (SIGALRM, &sa, NULL);
+
+ /* Rearm the timer. */
+ alarm (1);
+}
+
+
+static int
+do_test (void)
+{
+ sem_t s;
+ struct sigaction sa;
+
+ sa.sa_handler = handler;
+ sa.sa_flags = 0;
+ sigemptyset (&sa.sa_mask);
+
+ sigaction (SIGALRM, &sa, NULL);
+
+ if (sem_init (&s, 0, 0) == -1)
+ {
+ puts ("init failed");
+ return 1;
+ }
+
+ /* Set an alarm for 1 second. The wrapper will expect this. */
+ alarm (1);
+
+ int res = sem_wait (&s);
+ if (res == 0)
+ {
+ puts ("wait succeeded");
+ return 1;
+ }
+ if (res != -1 || errno != EINTR)
+ {
+ puts ("wait didn't fail with EINTR");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TIMEOUT 3
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-sem7.c
@@ -0,0 +1,108 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static void
+remove_sem (int status, void *arg)
+{
+ sem_unlink (arg);
+}
+
+
+int
+main (void)
+{
+ sem_t *s;
+ sem_t *s2;
+ sem_t *s3;
+
+ s = sem_open ("/glibc-tst-sem7", O_CREAT, 0600, 1);
+ if (s == SEM_FAILED)
+ {
+ if (errno == ENOSYS)
+ {
+ puts ("sem_open not supported. Oh well.");
+ return 0;
+ }
+
+ /* Maybe the shm filesystem has strict permissions. */
+ if (errno == EACCES)
+ {
+ puts ("sem_open not allowed. Oh well.");
+ return 0;
+ }
+
+ printf ("sem_open: %m\n");
+ return 1;
+ }
+
+ on_exit (remove_sem, (void *) "/glibc-tst-sem7");
+
+ /* We have the semaphore object. Now try again. We should get the
+ same address. */
+ s2 = sem_open ("/glibc-tst-sem7", O_CREAT, 0600, 1);
+ if (s2 == SEM_FAILED)
+ {
+ puts ("2nd sem_open failed");
+ return 1;
+ }
+ if (s != s2)
+ {
+ puts ("2nd sem_open didn't return the same address");
+ return 1;
+ }
+
+ /* And again, this time without O_CREAT. */
+ s3 = sem_open ("/glibc-tst-sem7", 0);
+ if (s3 == SEM_FAILED)
+ {
+ puts ("3rd sem_open failed");
+ return 1;
+ }
+ if (s != s3)
+ {
+ puts ("3rd sem_open didn't return the same address");
+ return 1;
+ }
+
+ /* Now close the handle. Three times. */
+ if (sem_close (s2) != 0)
+ {
+ puts ("1st sem_close failed");
+ return 1;
+ }
+ if (sem_close (s) != 0)
+ {
+ puts ("2nd sem_close failed");
+ return 1;
+ }
+ if (sem_close (s3) != 0)
+ {
+ puts ("3rd sem_close failed");
+ return 1;
+ }
+
+ return 0;
+}
--- /dev/null
+++ b/fbtl/tst-sem8.c
@@ -0,0 +1,73 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static void
+remove_sem (int status, void *arg)
+{
+ sem_unlink (arg);
+}
+
+
+int
+main (void)
+{
+ sem_t *s;
+ int i;
+
+ on_exit (remove_sem, (void *) "/glibc-tst-sem8");
+
+ for (i = 0; i < 3; ++i)
+ {
+ s = sem_open ("/glibc-tst-sem8", O_CREAT, 0600, 1);
+ if (s == SEM_FAILED)
+ {
+ if (errno == ENOSYS)
+ {
+ puts ("sem_open not supported. Oh well.");
+ return 0;
+ }
+
+ /* Maybe the shm filesystem has strict permissions. */
+ if (errno == EACCES)
+ {
+ puts ("sem_open not allowed. Oh well.");
+ return 0;
+ }
+
+ printf ("sem_open: %m\n");
+ return 1;
+ }
+
+ /* Now close the handle. */
+ if (sem_close (s) != 0)
+ {
+ puts ("sem_close failed");
+ return 1;
+ }
+ }
+
+ return 0;
+}
--- /dev/null
+++ b/fbtl/tst-sem9.c
@@ -0,0 +1,80 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static void
+remove_sem (int status, void *arg)
+{
+ sem_unlink (arg);
+}
+
+
+int
+main (void)
+{
+ sem_t *s;
+ int i;
+
+ on_exit (remove_sem, (void *) "/glibc-tst-sem9");
+
+ for (i = 0; i < 3; ++i)
+ {
+ s = sem_open ("/glibc-tst-sem9", O_CREAT, 0600, 1);
+ if (s == SEM_FAILED)
+ {
+ if (errno == ENOSYS)
+ {
+ puts ("sem_open not supported. Oh well.");
+ return 0;
+ }
+
+ /* Maybe the shm filesystem has strict permissions. */
+ if (errno == EACCES)
+ {
+ puts ("sem_open not allowed. Oh well.");
+ return 0;
+ }
+
+ printf ("sem_open: %m\n");
+ return 1;
+ }
+
+ /* Now close the handle. */
+ if (sem_close (s) != 0)
+ {
+ puts ("sem_close failed");
+ return 1;
+ }
+
+ /* And remove it. */
+ if (sem_unlink ("/glibc-tst-sem9") != 0)
+ {
+ puts ("sem_unlink failed");
+ return 1;
+ }
+ }
+
+ return 0;
+}
--- /dev/null
+++ b/fbtl/tst-setuid1-static.c
@@ -0,0 +1 @@
+#include "tst-setuid1.c"
--- /dev/null
+++ b/fbtl/tst-setuid1.c
@@ -0,0 +1,1084 @@
+/* Copyright (C) 2004-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jaku@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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <pwd.h>
+#include <grp.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+
+static pthread_barrier_t b3, b4;
+static uid_t prev_ruid, prev_euid, prev_suid, nobody_uid;
+static gid_t prev_rgid, prev_egid, prev_sgid, nobody_gid;
+enum ACTION { PREPARE, SET, CHECK_BEFORE, CHECK_AFTER };
+#define TESTNO(arg) ((long int) (arg) & 0xff)
+#define THREADNO(arg) ((long int) (arg) >> 8)
+
+
+static void
+check_prev_uid (int tno)
+{
+ uid_t ruid, euid, suid;
+ if (getresuid (&ruid, &euid, &suid) < 0)
+ {
+ printf ("getresuid failed: %d %m\n", tno);
+ exit (1);
+ }
+
+ if (ruid != prev_ruid || euid != prev_euid || suid != prev_suid)
+ {
+ printf ("uids before in %d (%d %d %d) != (%d %d %d)\n", tno,
+ ruid, euid, suid, prev_ruid, prev_euid, prev_suid);
+ exit (1);
+ }
+}
+
+
+static void
+check_prev_gid (int tno)
+{
+ gid_t rgid, egid, sgid;
+ if (getresgid (&rgid, &egid, &sgid) < 0)
+ {
+ printf ("getresgid failed: %d %m\n", tno);
+ exit (1);
+ }
+
+ if (rgid != prev_rgid || egid != prev_egid || sgid != prev_sgid)
+ {
+ printf ("gids before in %d (%d %d %d) != (%d %d %d)\n", tno,
+ rgid, egid, sgid, prev_rgid, prev_egid, prev_sgid);
+ exit (1);
+ }
+}
+
+
+static void
+test_setuid1 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ return;
+
+ if (action != CHECK_AFTER)
+ check_prev_uid (tno);
+
+ if (action == SET && setuid (nobody_uid) < 0)
+ {
+ printf ("setuid failed: %m\n");
+ exit (1);
+ }
+
+ if (action != CHECK_BEFORE)
+ {
+ uid_t ruid, euid, suid;
+ if (getresuid (&ruid, &euid, &suid) < 0)
+ {
+ printf ("getresuid failed: %d %m\n", tno);
+ exit (1);
+ }
+
+ if (ruid != nobody_uid || euid != nobody_uid || suid != nobody_uid)
+ {
+ printf ("after setuid %d (%d %d %d) != (%d %d %d)\n", tno,
+ ruid, euid, suid, nobody_uid, nobody_uid, nobody_uid);
+ exit (1);
+ }
+ }
+}
+
+
+static void
+test_setuid2 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ {
+ if (setresuid (nobody_uid, nobody_uid, -1) < 0)
+ {
+ printf ("setresuid failed: %m\n");
+ exit (1);
+ }
+
+ prev_ruid = nobody_uid;
+ prev_euid = nobody_uid;
+ return;
+ }
+
+ if (action != CHECK_AFTER)
+ check_prev_uid (tno);
+
+ if (action == SET && setuid (prev_suid) < 0)
+ {
+ printf ("setuid failed: %m\n");
+ exit (1);
+ }
+
+ if (action != CHECK_BEFORE)
+ {
+ uid_t ruid, euid, suid;
+ if (getresuid (&ruid, &euid, &suid) < 0)
+ {
+ printf ("getresuid failed: %d %m\n", tno);
+ exit (1);
+ }
+
+ if (ruid != nobody_uid || euid != prev_suid || suid != prev_suid)
+ {
+ printf ("after setuid %d (%d %d %d) != (%d %d %d)\n", tno,
+ ruid, euid, suid, nobody_uid, prev_suid, prev_suid);
+ exit (1);
+ }
+ }
+}
+
+
+static void
+test_seteuid1 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ return;
+
+ if (action != CHECK_AFTER)
+ check_prev_uid (tno);
+
+ if (action == SET && seteuid (nobody_uid) < 0)
+ {
+ printf ("seteuid failed: %m\n");
+ exit (1);
+ }
+
+ if (action != CHECK_BEFORE)
+ {
+ uid_t ruid, euid, suid;
+ if (getresuid (&ruid, &euid, &suid) < 0)
+ {
+ printf ("getresuid failed: %d %m\n", tno);
+ exit (1);
+ }
+
+ if (ruid != prev_ruid || euid != nobody_uid || suid != prev_suid)
+ {
+ printf ("after seteuid %d (%d %d %d) != (%d %d %d)\n", tno,
+ ruid, euid, suid, prev_ruid, nobody_uid, prev_suid);
+ exit (1);
+ }
+ }
+}
+
+
+static void
+test_seteuid2 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ {
+ if (setresuid (nobody_uid, nobody_uid, -1) < 0)
+ {
+ printf ("setresuid failed: %m\n");
+ exit (1);
+ }
+
+ prev_ruid = nobody_uid;
+ prev_euid = nobody_uid;
+ nobody_uid = prev_suid;
+ return;
+ }
+
+ test_seteuid1 (action, tno);
+}
+
+
+static void
+test_setreuid1 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ return;
+
+ if (action != CHECK_AFTER)
+ check_prev_uid (tno);
+
+ if (action == SET && setreuid (-1, nobody_uid) < 0)
+ {
+ printf ("setreuid failed: %m\n");
+ exit (1);
+ }
+
+ if (action != CHECK_BEFORE)
+ {
+ uid_t ruid, euid, suid, esuid;
+ if (getresuid (&ruid, &euid, &suid) < 0)
+ {
+ printf ("getresuid failed: %d %m\n", tno);
+ exit (1);
+ }
+
+ if (prev_ruid != nobody_uid)
+ esuid = nobody_uid;
+ else
+ esuid = prev_suid;
+
+ if (ruid != prev_ruid || euid != nobody_uid || suid != esuid)
+ {
+ printf ("after setreuid %d (%d %d %d) != (%d %d %d)\n", tno,
+ ruid, euid, suid, prev_ruid, nobody_uid, esuid);
+ exit (1);
+ }
+ }
+}
+
+
+static void
+test_setreuid2 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ return;
+
+ if (action != CHECK_AFTER)
+ check_prev_uid (tno);
+
+ if (action == SET && setreuid (nobody_uid, -1) < 0)
+ {
+ printf ("setreuid failed: %m\n");
+ exit (1);
+ }
+
+ if (action != CHECK_BEFORE)
+ {
+ uid_t ruid, euid, suid;
+ if (getresuid (&ruid, &euid, &suid) < 0)
+ {
+ printf ("getresuid failed: %d %m\n", tno);
+ exit (1);
+ }
+
+ if (ruid != nobody_uid || euid != prev_euid || suid != prev_euid)
+ {
+ printf ("after setreuid %d (%d %d %d) != (%d %d %d)\n", tno,
+ ruid, euid, suid, nobody_uid, prev_euid, prev_euid);
+ exit (1);
+ }
+ }
+}
+
+
+static void
+test_setreuid3 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ return;
+
+ if (action != CHECK_AFTER)
+ check_prev_uid (tno);
+
+ if (action == SET && setreuid (nobody_uid, nobody_uid) < 0)
+ {
+ printf ("setreuid failed: %m\n");
+ exit (1);
+ }
+
+ if (action != CHECK_BEFORE)
+ {
+ uid_t ruid, euid, suid;
+ if (getresuid (&ruid, &euid, &suid) < 0)
+ {
+ printf ("getresuid failed: %d %m\n", tno);
+ exit (1);
+ }
+
+ if (ruid != nobody_uid || euid != nobody_uid || suid != nobody_uid)
+ {
+ printf ("after setreuid %d (%d %d %d) != (%d %d %d)\n", tno,
+ ruid, euid, suid, nobody_uid, nobody_uid, nobody_uid);
+ exit (1);
+ }
+ }
+}
+
+
+static void
+test_setreuid4 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ {
+ if (setresuid (nobody_uid, nobody_uid, -1) < 0)
+ {
+ printf ("setresuid failed: %m\n");
+ exit (1);
+ }
+
+ prev_ruid = nobody_uid;
+ prev_euid = nobody_uid;
+ nobody_uid = prev_suid;
+ return;
+ }
+
+ test_setreuid1 (action, tno);
+}
+
+
+static void
+test_setresuid1 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ return;
+
+ if (action != CHECK_AFTER)
+ check_prev_uid (tno);
+
+ if (action == SET && setresuid (-1, nobody_uid, -1) < 0)
+ {
+ printf ("setresuid failed: %m\n");
+ exit (1);
+ }
+
+ if (action != CHECK_BEFORE)
+ {
+ uid_t ruid, euid, suid;
+ if (getresuid (&ruid, &euid, &suid) < 0)
+ {
+ printf ("getresuid failed: %d %m\n", tno);
+ exit (1);
+ }
+
+ if (ruid != prev_ruid || euid != nobody_uid || suid != prev_suid)
+ {
+ printf ("after setresuid %d (%d %d %d) != (%d %d %d)\n", tno,
+ ruid, euid, suid, prev_ruid, nobody_uid, prev_suid);
+ exit (1);
+ }
+ }
+}
+
+
+static void
+test_setresuid2 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ return;
+
+ if (action != CHECK_AFTER)
+ check_prev_uid (tno);
+
+ if (action == SET && setresuid (prev_euid, nobody_uid, nobody_uid) < 0)
+ {
+ printf ("setresuid failed: %m\n");
+ exit (1);
+ }
+
+ if (action != CHECK_BEFORE)
+ {
+ uid_t ruid, euid, suid;
+ if (getresuid (&ruid, &euid, &suid) < 0)
+ {
+ printf ("getresuid failed: %d %m\n", tno);
+ exit (1);
+ }
+
+ if (ruid != prev_euid || euid != nobody_uid || suid != nobody_uid)
+ {
+ printf ("after setresuid %d (%d %d %d) != (%d %d %d)\n", tno,
+ ruid, euid, suid, prev_euid, nobody_uid, nobody_uid);
+ exit (1);
+ }
+ }
+}
+
+
+static void
+test_setresuid3 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ return;
+
+ if (action != CHECK_AFTER)
+ check_prev_uid (tno);
+
+ if (action == SET && setresuid (nobody_uid, nobody_uid, nobody_uid) < 0)
+ {
+ printf ("setresuid failed: %m\n");
+ exit (1);
+ }
+
+ if (action != CHECK_BEFORE)
+ {
+ uid_t ruid, euid, suid;
+ if (getresuid (&ruid, &euid, &suid) < 0)
+ {
+ printf ("getresuid failed: %d %m\n", tno);
+ exit (1);
+ }
+
+ if (ruid != nobody_uid || euid != nobody_uid || suid != nobody_uid)
+ {
+ printf ("after setresuid %d (%d %d %d) != (%d %d %d)\n", tno,
+ ruid, euid, suid, nobody_uid, nobody_uid, nobody_uid);
+ exit (1);
+ }
+ }
+}
+
+
+static void
+test_setresuid4 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ {
+ if (setresuid (nobody_uid, nobody_uid, -1) < 0)
+ {
+ printf ("setresuid failed: %m\n");
+ exit (1);
+ }
+
+ prev_ruid = nobody_uid;
+ prev_euid = nobody_uid;
+ nobody_uid = prev_suid;
+ return;
+ }
+
+ test_setresuid1 (action, tno);
+}
+
+
+static void
+test_setgid1 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ return;
+
+ if (action != CHECK_AFTER)
+ check_prev_gid (tno);
+
+ if (action == SET && setgid (nobody_gid) < 0)
+ {
+ printf ("setgid failed: %m\n");
+ exit (1);
+ }
+
+ if (action != CHECK_BEFORE)
+ {
+ gid_t rgid, egid, sgid;
+ if (getresgid (&rgid, &egid, &sgid) < 0)
+ {
+ printf ("getresgid failed: %d %m\n", tno);
+ exit (1);
+ }
+
+ if (rgid != nobody_gid || egid != nobody_gid || sgid != nobody_gid)
+ {
+ printf ("after setgid %d (%d %d %d) != (%d %d %d)\n", tno,
+ rgid, egid, sgid, nobody_gid, nobody_gid, nobody_gid);
+ exit (1);
+ }
+ }
+}
+
+
+static void
+test_setgid2 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ {
+ if (setresgid (nobody_gid, nobody_gid, -1) < 0)
+ {
+ printf ("setresgid failed: %m\n");
+ exit (1);
+ }
+
+ prev_rgid = nobody_gid;
+ prev_egid = nobody_gid;
+
+ if (setresuid (nobody_uid, nobody_uid, -1) < 0)
+ {
+ printf ("setresuid failed: %m\n");
+ exit (1);
+ }
+
+ prev_ruid = nobody_uid;
+ prev_euid = nobody_uid;
+ return;
+ }
+
+ if (action != CHECK_AFTER)
+ check_prev_gid (tno);
+
+ if (action == SET && setgid (prev_sgid) < 0)
+ {
+ printf ("setgid failed: %m\n");
+ exit (1);
+ }
+
+ if (action != CHECK_BEFORE)
+ {
+ gid_t rgid, egid, sgid;
+ if (getresgid (&rgid, &egid, &sgid) < 0)
+ {
+ printf ("getresgid failed: %d %m\n", tno);
+ exit (1);
+ }
+
+ if (rgid != nobody_gid || egid != prev_sgid || sgid != prev_sgid)
+ {
+ printf ("after setgid %d (%d %d %d) != (%d %d %d)\n", tno,
+ rgid, egid, sgid, nobody_gid, prev_sgid, prev_sgid);
+ exit (1);
+ }
+ }
+}
+
+
+static void
+test_setegid1 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ return;
+
+ if (action != CHECK_AFTER)
+ check_prev_gid (tno);
+
+ if (action == SET && setegid (nobody_gid) < 0)
+ {
+ printf ("setegid failed: %m\n");
+ exit (1);
+ }
+
+ if (action != CHECK_BEFORE)
+ {
+ gid_t rgid, egid, sgid;
+ if (getresgid (&rgid, &egid, &sgid) < 0)
+ {
+ printf ("getresgid failed: %d %m\n", tno);
+ exit (1);
+ }
+
+ if (rgid != prev_rgid || egid != nobody_gid || sgid != prev_sgid)
+ {
+ printf ("after setegid %d (%d %d %d) != (%d %d %d)\n", tno,
+ rgid, egid, sgid, prev_rgid, nobody_gid, prev_sgid);
+ exit (1);
+ }
+ }
+}
+
+
+static void
+test_setegid2 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ {
+ if (setresgid (nobody_gid, nobody_gid, -1) < 0)
+ {
+ printf ("setresgid failed: %m\n");
+ exit (1);
+ }
+
+ prev_rgid = nobody_gid;
+ prev_egid = nobody_gid;
+ nobody_gid = prev_sgid;
+ return;
+ }
+
+ test_setegid1 (action, tno);
+}
+
+
+static void
+test_setregid1 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ return;
+
+ if (action != CHECK_AFTER)
+ check_prev_gid (tno);
+
+ if (action == SET && setregid (-1, nobody_gid) < 0)
+ {
+ printf ("setregid failed: %m\n");
+ exit (1);
+ }
+
+ if (action != CHECK_BEFORE)
+ {
+ gid_t rgid, egid, sgid, esgid;
+ if (getresgid (&rgid, &egid, &sgid) < 0)
+ {
+ printf ("getresgid failed: %d %m\n", tno);
+ exit (1);
+ }
+
+ if (prev_rgid != nobody_gid)
+ esgid = nobody_gid;
+ else
+ esgid = prev_sgid;
+
+ if (rgid != prev_rgid || egid != nobody_gid || sgid != esgid)
+ {
+ printf ("after setregid %d (%d %d %d) != (%d %d %d)\n", tno,
+ rgid, egid, sgid, prev_rgid, nobody_gid, esgid);
+ exit (1);
+ }
+ }
+}
+
+
+static void
+test_setregid2 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ return;
+
+ if (action != CHECK_AFTER)
+ check_prev_gid (tno);
+
+ if (action == SET && setregid (nobody_gid, -1) < 0)
+ {
+ printf ("setregid failed: %m\n");
+ exit (1);
+ }
+
+ if (action != CHECK_BEFORE)
+ {
+ gid_t rgid, egid, sgid;
+ if (getresgid (&rgid, &egid, &sgid) < 0)
+ {
+ printf ("getresgid failed: %d %m\n", tno);
+ exit (1);
+ }
+
+ if (rgid != nobody_gid || egid != prev_egid || sgid != prev_egid)
+ {
+ printf ("after setregid %d (%d %d %d) != (%d %d %d)\n", tno,
+ rgid, egid, sgid, nobody_gid, prev_egid, prev_egid);
+ exit (1);
+ }
+ }
+}
+
+
+static void
+test_setregid3 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ return;
+
+ if (action != CHECK_AFTER)
+ check_prev_gid (tno);
+
+ if (action == SET && setregid (nobody_gid, nobody_gid) < 0)
+ {
+ printf ("setregid failed: %m\n");
+ exit (1);
+ }
+
+ if (action != CHECK_BEFORE)
+ {
+ gid_t rgid, egid, sgid;
+ if (getresgid (&rgid, &egid, &sgid) < 0)
+ {
+ printf ("getresgid failed: %d %m\n", tno);
+ exit (1);
+ }
+
+ if (rgid != nobody_gid || egid != nobody_gid || sgid != nobody_gid)
+ {
+ printf ("after setregid %d (%d %d %d) != (%d %d %d)\n", tno,
+ rgid, egid, sgid, nobody_gid, nobody_gid, nobody_gid);
+ exit (1);
+ }
+ }
+}
+
+
+static void
+test_setregid4 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ {
+ if (setresgid (nobody_gid, nobody_gid, -1) < 0)
+ {
+ printf ("setresgid failed: %m\n");
+ exit (1);
+ }
+
+ prev_rgid = nobody_gid;
+ prev_egid = nobody_gid;
+ nobody_gid = prev_sgid;
+ return;
+ }
+
+ test_setregid1 (action, tno);
+}
+
+
+static void
+test_setresgid1 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ return;
+
+ if (action != CHECK_AFTER)
+ check_prev_gid (tno);
+
+ if (action == SET && setresgid (-1, nobody_gid, -1) < 0)
+ {
+ printf ("setresgid failed: %m\n");
+ exit (1);
+ }
+
+ if (action != CHECK_BEFORE)
+ {
+ gid_t rgid, egid, sgid;
+ if (getresgid (&rgid, &egid, &sgid) < 0)
+ {
+ printf ("getresgid failed: %d %m\n", tno);
+ exit (1);
+ }
+
+ if (rgid != prev_rgid || egid != nobody_gid || sgid != prev_sgid)
+ {
+ printf ("after setresgid %d (%d %d %d) != (%d %d %d)\n", tno,
+ rgid, egid, sgid, prev_rgid, nobody_gid, prev_sgid);
+ exit (1);
+ }
+ }
+}
+
+
+static void
+test_setresgid2 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ return;
+
+ if (action != CHECK_AFTER)
+ check_prev_gid (tno);
+
+ if (action == SET && setresgid (prev_egid, nobody_gid, nobody_gid) < 0)
+ {
+ printf ("setresgid failed: %m\n");
+ exit (1);
+ }
+
+ if (action != CHECK_BEFORE)
+ {
+ gid_t rgid, egid, sgid;
+ if (getresgid (&rgid, &egid, &sgid) < 0)
+ {
+ printf ("getresgid failed: %d %m\n", tno);
+ exit (1);
+ }
+
+ if (rgid != prev_egid || egid != nobody_gid || sgid != nobody_gid)
+ {
+ printf ("after setresgid %d (%d %d %d) != (%d %d %d)\n", tno,
+ rgid, egid, sgid, prev_egid, nobody_gid, nobody_gid);
+ exit (1);
+ }
+ }
+}
+
+
+static void
+test_setresgid3 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ return;
+
+ if (action != CHECK_AFTER)
+ check_prev_gid (tno);
+
+ if (action == SET && setresgid (nobody_gid, nobody_gid, nobody_gid) < 0)
+ {
+ printf ("setresgid failed: %m\n");
+ exit (1);
+ }
+
+ if (action != CHECK_BEFORE)
+ {
+ gid_t rgid, egid, sgid;
+ if (getresgid (&rgid, &egid, &sgid) < 0)
+ {
+ printf ("getresgid failed: %d %m\n", tno);
+ exit (1);
+ }
+
+ if (rgid != nobody_gid || egid != nobody_gid || sgid != nobody_gid)
+ {
+ printf ("after setresgid %d (%d %d %d) != (%d %d %d)\n", tno,
+ rgid, egid, sgid, nobody_gid, nobody_gid, nobody_gid);
+ exit (1);
+ }
+ }
+}
+
+
+static void
+test_setresgid4 (enum ACTION action, int tno)
+{
+ if (action == PREPARE)
+ {
+ if (setresgid (nobody_gid, nobody_gid, -1) < 0)
+ {
+ printf ("setresgid failed: %m\n");
+ exit (1);
+ }
+
+ prev_rgid = nobody_gid;
+ prev_egid = nobody_gid;
+ nobody_gid = prev_sgid;
+ return;
+ }
+
+ test_setresgid1 (action, tno);
+}
+
+
+static struct setuid_test
+{
+ const char *name;
+ void (*test) (enum ACTION, int tno);
+} setuid_tests[] =
+{
+ { "setuid1", test_setuid1 },
+ { "setuid2", test_setuid2 },
+ { "seteuid1", test_seteuid1 },
+ { "seteuid2", test_seteuid2 },
+ { "setreuid1", test_setreuid1 },
+ { "setreuid2", test_setreuid2 },
+ { "setreuid3", test_setreuid3 },
+ { "setreuid4", test_setreuid4 },
+ { "setresuid1", test_setresuid1 },
+ { "setresuid2", test_setresuid2 },
+ { "setresuid3", test_setresuid3 },
+ { "setresuid4", test_setresuid4 },
+ { "setgid1", test_setgid1 },
+ { "setgid2", test_setgid2 },
+ { "setegid1", test_setegid1 },
+ { "setegid2", test_setegid2 },
+ { "setregid1", test_setregid1 },
+ { "setregid2", test_setregid2 },
+ { "setregid3", test_setregid3 },
+ { "setregid4", test_setregid4 },
+ { "setresgid1", test_setresgid1 },
+ { "setresgid2", test_setresgid2 },
+ { "setresgid3", test_setresgid3 },
+ { "setresgid4", test_setresgid4 }
+};
+
+
+static void *
+tf2 (void *arg)
+{
+ int e = pthread_barrier_wait (&b4);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ setuid_tests[TESTNO (arg)].test (CHECK_AFTER, THREADNO (arg));
+ return NULL;
+}
+
+
+static void *
+tf (void *arg)
+{
+ setuid_tests[TESTNO (arg)].test (CHECK_BEFORE, THREADNO (arg));
+
+ int e = pthread_barrier_wait (&b3);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ return tf2 (arg);
+}
+
+
+static int
+do_one_test (long int testno)
+{
+ printf ("%s test\n", setuid_tests[testno].name);
+
+ pid_t pid = fork ();
+ if (pid == 0)
+ {
+ setuid_tests[testno].test (PREPARE, 0);
+ setuid_tests[testno].test (SET, 0);
+ exit (0);
+ }
+
+ if (pid < 0)
+ {
+ printf ("fork failed: %m\n");
+ exit (1);
+ }
+
+ int status;
+ if (waitpid (pid, &status, 0) < 0)
+ {
+ printf ("waitpid failed: %m\n");
+ exit (1);
+ }
+
+ if (!WIFEXITED (status))
+ {
+ puts ("child did not exit");
+ exit (1);
+ }
+
+ if (WEXITSTATUS (status))
+ {
+ printf ("skipping %s test\n", setuid_tests[testno].name);
+ return 0;
+ }
+
+ pid = fork ();
+ if (pid == 0)
+ {
+ setuid_tests[testno].test (PREPARE, 0);
+
+ pthread_t th;
+ int e = pthread_create (&th, NULL, tf, (void *) (testno | 0x100L));
+ if (e != 0)
+ {
+ printf ("create failed: %m\n");
+ exit (1);
+ }
+
+ pthread_t th2;
+ e = pthread_create (&th2, NULL, tf, (void *) (testno | 0x200L));
+ if (e != 0)
+ {
+ printf ("create failed: %m\n");
+ exit (1);
+ }
+
+ e = pthread_barrier_wait (&b3);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ setuid_tests[testno].test (SET, 0);
+
+ pthread_t th3;
+ e = pthread_create (&th3, NULL, tf2, (void *) (testno | 0x300L));
+ if (e != 0)
+ {
+ printf ("create failed: %m\n");
+ exit (1);
+ }
+
+ e = pthread_barrier_wait (&b4);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ exit (0);
+ }
+
+ if (pid < 0)
+ {
+ printf ("fork failed: %m\n");
+ exit (1);
+ }
+
+ if (waitpid (pid, &status, 0) < 0)
+ {
+ printf ("waitpid failed: %m\n");
+ exit (1);
+ }
+
+ if (!WIFEXITED (status))
+ {
+ puts ("second child did not exit");
+ exit (1);
+ }
+
+ if (WEXITSTATUS (status))
+ exit (WEXITSTATUS (status));
+
+ return 0;
+}
+
+
+static int
+do_test (void)
+{
+ struct passwd *pwd = getpwnam ("nobody");
+ if (pwd == NULL)
+ {
+ puts ("User nobody doesn't exist");
+ return 0;
+ }
+ nobody_uid = pwd->pw_uid;
+ nobody_gid = pwd->pw_gid;
+
+ if (getresuid (&prev_ruid, &prev_euid, &prev_suid) < 0)
+ {
+ printf ("getresuid failed: %m\n");
+ exit (1);
+ }
+
+ if (getresgid (&prev_rgid, &prev_egid, &prev_sgid) < 0)
+ {
+ printf ("getresgid failed: %m\n");
+ exit (1);
+ }
+
+ if (prev_ruid == nobody_uid || prev_euid == nobody_uid
+ || prev_suid == nobody_uid)
+ {
+ puts ("already running as user nobody, skipping tests");
+ exit (0);
+ }
+
+ if (prev_rgid == nobody_gid || prev_egid == nobody_gid
+ || prev_sgid == nobody_gid)
+ {
+ puts ("already running as group nobody, skipping tests");
+ exit (0);
+ }
+
+ if (pthread_barrier_init (&b3, NULL, 3) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (pthread_barrier_init (&b4, NULL, 4) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ for (unsigned long int testno = 0;
+ testno < sizeof (setuid_tests) / sizeof (setuid_tests[0]);
+ ++testno)
+ do_one_test (testno);
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-signal1.c
@@ -0,0 +1,188 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+
+static sigset_t ss;
+static pthread_barrier_t *b;
+
+
+static void *
+tf (void *arg)
+{
+ sigdelset (&ss, SIGINT);
+
+ if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
+ {
+ puts ("2nd pthread_sigmask failed");
+ exit (1);
+ }
+
+ pthread_barrier_wait (b);
+
+ int sig;
+ int res = sigwait (&ss, &sig);
+ if (res == 0)
+ {
+ printf ("sigwait returned successfully with signal %d\n", sig);
+ exit (1);
+ }
+
+ printf ("sigwait returned with %s (%d)\n", strerror (res), res);
+
+ return NULL;
+}
+
+
+static void
+receiver (void)
+{
+ pthread_t th;
+
+ /* Make sure the process doesn't run forever. */
+ alarm (10);
+
+ sigfillset (&ss);
+
+ if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
+ {
+ puts ("1st pthread_sigmask failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("pthread_create failed");
+ exit (1);
+ }
+
+ if (pthread_join (th, NULL) == 0)
+ {
+ puts ("thread joined?!");
+ exit (1);
+ }
+
+ _exit (0);
+}
+
+
+static int
+do_test (void)
+{
+ char tmp[] = "/tmp/tst-signal1-XXXXXX";
+
+ int fd = mkstemp (tmp);
+ if (fd == -1)
+ {
+ puts ("mkstemp failed");
+ exit (1);
+ }
+
+ unlink (tmp);
+
+ int i;
+ for (i = 0; i < 20; ++i)
+ write (fd, "foobar xyzzy", 12);
+
+ b = mmap (NULL, sizeof (pthread_barrier_t), PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ if (b == MAP_FAILED)
+ {
+ puts ("mmap failed");
+ exit (1);
+ }
+
+ pthread_barrierattr_t ba;
+ if (pthread_barrierattr_init (&ba) != 0)
+ {
+ puts ("barrierattr_init failed");
+ exit (1);
+ }
+
+ if (pthread_barrierattr_setpshared (&ba, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("barrierattr_setpshared failed");
+ exit (1);
+ }
+
+ if (pthread_barrier_init (b, &ba, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (pthread_barrierattr_destroy (&ba) != 0)
+ {
+ puts ("barrierattr_destroy failed");
+ exit (1);
+ }
+
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+
+ if (pid == 0)
+ receiver ();
+
+ pthread_barrier_wait (b);
+
+ /* Wait a bit more. */
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
+ nanosleep (&ts, NULL);
+
+ /* Send the signal. */
+ puts ("sending the signal now");
+ kill (pid, SIGINT);
+
+ /* Wait for the process to terminate. */
+ int status;
+ if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+ {
+ puts ("wrong child reported terminated");
+ exit (1);
+ }
+
+ if (!WIFSIGNALED (status))
+ {
+ puts ("child wasn't signalled");
+ exit (1);
+ }
+
+ if (WTERMSIG (status) != SIGINT)
+ {
+ puts ("child not terminated with SIGINT");
+ exit (1);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-signal2.c
@@ -0,0 +1,197 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+#include <string.h>
+
+
+static sigset_t ss;
+static pthread_barrier_t *b;
+
+
+static void *
+tf (void *arg)
+{
+ pthread_barrier_wait (b);
+
+ puts ("child: calling sigwait now");
+
+ int sig;
+ int err;
+ err = sigwait (&ss, &sig);
+ if (err != 0)
+ {
+ printf ("sigwait returned unsuccessfully: %s (%d)\n",
+ strerror (err), err);
+ _exit (1);
+ }
+
+ puts ("sigwait returned");
+
+ if (sig != SIGINT)
+ {
+ printf ("caught signal %d, expected %d (SIGINT)\n", sig, SIGINT);
+ _exit (1);
+ }
+
+ puts ("child thread terminating now");
+
+ return NULL;
+}
+
+
+static void
+receiver (void)
+{
+ pthread_t th;
+
+ /* Make sure the process doesn't run forever. */
+ alarm (10);
+
+ sigfillset (&ss);
+
+ if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
+ {
+ puts ("1st pthread_sigmask failed");
+ _exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("pthread_create failed");
+ _exit (1);
+ }
+
+ if (pthread_join (th, NULL) != 0)
+ {
+ puts ("thread didn't join");
+ _exit (1);
+ }
+
+ puts ("join succeeded");
+
+ _exit (0);
+}
+
+
+static int
+do_test (void)
+{
+ char tmp[] = "/tmp/tst-signal1-XXXXXX";
+
+ int fd = mkstemp (tmp);
+ if (fd == -1)
+ {
+ puts ("mkstemp failed");
+ exit (1);
+ }
+
+ unlink (tmp);
+
+ int i;
+ for (i = 0; i < 20; ++i)
+ write (fd, "foobar xyzzy", 12);
+
+ b = mmap (NULL, sizeof (pthread_barrier_t), PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ if (b == MAP_FAILED)
+ {
+ puts ("mmap failed");
+ exit (1);
+ }
+
+ pthread_barrierattr_t ba;
+ if (pthread_barrierattr_init (&ba) != 0)
+ {
+ puts ("barrierattr_init failed");
+ exit (1);
+ }
+
+ if (pthread_barrierattr_setpshared (&ba, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("barrierattr_setpshared failed");
+ exit (1);
+ }
+
+ if (pthread_barrier_init (b, &ba, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (pthread_barrierattr_destroy (&ba) != 0)
+ {
+ puts ("barrierattr_destroy failed");
+ exit (1);
+ }
+
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+
+ if (pid == 0)
+ receiver ();
+
+ pthread_barrier_wait (b);
+
+ /* Wait a bit more. */
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
+ nanosleep (&ts, NULL);
+
+ /* Send the signal. */
+ puts ("sending the signal now");
+ kill (pid, SIGINT);
+
+ /* Wait for the process to terminate. */
+ int status;
+ if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+ {
+ puts ("wrong child reported terminated");
+ exit (1);
+ }
+
+ if (!WIFEXITED (status))
+ {
+ if (WIFSIGNALED (status))
+ printf ("child exited with signal %d\n", WTERMSIG (status));
+ else
+ puts ("child didn't exit normally");
+ exit (1);
+ }
+
+ if (WEXITSTATUS (status) != 0)
+ {
+ printf ("exit status %d != 0\n", WEXITSTATUS (status));
+ exit (1);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-signal3.c
@@ -0,0 +1,260 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+/* Number of different signalss to use. Also is the number of
+ threads. */
+#define N 10
+/* Maximum number of threads in flight at any one time. */
+#define INFLIGHT 5
+/* Number of signals sent in total. */
+#define ROUNDS 10000
+
+
+static int received[N][N];
+static int nsig[N];
+static pthread_t th[N];
+static sem_t sem;
+static pthread_mutex_t lock[N];
+static pthread_t th_main;
+static int sig0;
+
+static void
+handler (int sig)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ if (pthread_equal (pthread_self (), th[i]))
+ break;
+
+ if (i == N)
+ {
+ if (pthread_equal (pthread_self (), th_main))
+ puts ("signal received by main thread");
+ else
+ printf ("signal received by unknown thread (%lx)\n",
+ (unsigned long int) pthread_self ());
+ exit (1);
+ }
+
+ ++received[i][sig - sig0];
+
+ sem_post (&sem);
+}
+
+
+static void *
+tf (void *arg)
+{
+ int idx = (long int) arg;
+
+ sigset_t ss;
+ sigemptyset (&ss);
+
+ int i;
+ for (i = 0; i <= idx; ++i)
+ sigaddset (&ss, sig0 + i);
+
+ if (pthread_sigmask (SIG_UNBLOCK, &ss, NULL) != 0)
+ {
+ printf ("thread %d: pthread_sigmask failed\n", i);
+ exit (1);
+ }
+
+ pthread_mutex_lock (&lock[idx]);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ /* Block all signals. */
+ sigset_t ss;
+ sigfillset (&ss);
+
+ th_main = pthread_self ();
+
+ sig0 = SIGRTMIN;
+
+ if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
+ {
+ puts ("1st pthread_sigmask failed");
+ exit (1);
+ }
+
+ /* Install the handler. */
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ struct sigaction sa =
+ {
+ .sa_handler = handler,
+ .sa_flags = 0
+ };
+ sigfillset (&sa.sa_mask);
+
+ if (sigaction (sig0 + i, &sa, NULL) != 0)
+ {
+ printf ("sigaction for signal %d failed\n", i);
+ exit (1);
+ }
+ }
+
+ if (sem_init (&sem, 0, INFLIGHT) != 0)
+ {
+ puts ("sem_init failed");
+ exit (1);
+ }
+
+ pthread_attr_t a;
+
+ if (pthread_attr_init (&a) != 0)
+ {
+ puts ("attr_init failed");
+ exit (1);
+ }
+
+ if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+ for (i = 0; i < N; ++i)
+ {
+ if (pthread_mutex_init (&lock[i], NULL) != 0)
+ {
+ printf ("mutex_init[%d] failed\n", i);
+ }
+
+ if (pthread_mutex_lock (&lock[i]) != 0)
+ {
+ printf ("mutex_lock[%d] failed\n", i);
+ }
+
+ if (pthread_create (&th[i], &a, tf, (void *) (long int) i) != 0)
+ {
+ printf ("create of thread %d failed\n", i);
+ exit (1);
+ }
+ }
+
+ if (pthread_attr_destroy (&a) != 0)
+ {
+ puts ("attr_destroy failed");
+ exit (1);
+ }
+
+ int result = 0;
+ unsigned int r = 42;
+ pid_t pid = getpid ();
+
+ for (i = 0; i < ROUNDS; ++i)
+ {
+ if (TEMP_FAILURE_RETRY (sem_wait (&sem)) != 0)
+ {
+ printf ("sem_wait round %d failed: %m\n", i);
+ exit (1);
+ }
+
+ int s = rand_r (&r) % N;
+
+ kill (pid, sig0 + s);
+ }
+
+ void *status;
+ for (i = 0; i < N; ++i)
+ {
+ if (pthread_mutex_unlock (&lock[i]) != 0)
+ {
+ printf ("unlock %d failed\n", i);
+ exit (1);
+ }
+
+ if (pthread_join (th[i], &status) != 0)
+ {
+ printf ("join %d failed\n", i);
+ result = 1;
+ }
+ else if (status != NULL)
+ {
+ printf ("%d: result != NULL\n", i);
+ result = 1;
+ }
+ }
+
+ int total = 0;
+ for (i = 0; i < N; ++i)
+ {
+ int j;
+
+ for (j = 0; j <= i; ++j)
+ total += received[i][j];
+
+ for (j = i + 1; j < N; ++j)
+ if (received[i][j] != 0)
+ {
+ printf ("thread %d received signal SIGRTMIN+%d\n", i, j);
+ result = 1;
+ }
+ }
+
+ if (total != ROUNDS)
+ {
+ printf ("total number of handled signals is %d, expected %d\n",
+ total, ROUNDS);
+ result = 1;
+ }
+
+ printf ("A total of %d signals sent and received\n", total);
+ for (i = 0; i < N; ++i)
+ {
+ printf ("thread %2d:", i);
+
+ int j;
+ for (j = 0; j <= i; ++j)
+ {
+ printf (" %5d", received[i][j]);
+ nsig[j] += received[i][j];
+ }
+
+ putchar ('\n');
+
+ }
+
+ printf ("\nTotal :");
+ for (i = 0; i < N; ++i)
+ printf (" %5d", nsig[i]);
+ putchar ('\n');
+
+ return result;
+}
+
+#define TIMEOUT 10
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-signal4.c
@@ -0,0 +1,59 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static int
+do_test (void)
+{
+ sigset_t ss;
+
+ sigemptyset (&ss);
+
+ int i;
+ for (i = 0; i < 10000; ++i)
+ {
+ long int r = random ();
+
+ if (r != SIG_BLOCK && r != SIG_SETMASK && r != SIG_UNBLOCK)
+ {
+ int e = pthread_sigmask (r, &ss, NULL);
+
+ if (e == 0)
+ {
+ printf ("pthread_sigmask succeeded for how = %ld\n", r);
+ exit (1);
+ }
+
+ if (e != EINVAL)
+ {
+ puts ("pthread_sigmask didn't return EINVAL");
+ exit (1);
+ }
+ }
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-signal5.c
@@ -0,0 +1,110 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+
+static sigset_t ss;
+
+
+static void *
+tf (void *arg)
+{
+ sigset_t ss2;
+ if (pthread_sigmask (SIG_SETMASK, NULL, &ss2) != 0)
+ {
+ puts ("child: sigmask failed");
+ exit (1);
+ }
+
+ int i;
+ for (i = 1; i < 32; ++i)
+ if (sigismember (&ss, i) && ! sigismember (&ss2, i))
+ {
+ printf ("signal %d set in parent mask, but not in child\n", i);
+ exit (1);
+ }
+ else if (! sigismember (&ss, i) && sigismember (&ss2, i))
+ {
+ printf ("signal %d set in child mask, but not in parent\n", i);
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ sigemptyset (&ss);
+ sigaddset (&ss, SIGUSR1);
+ if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
+ {
+ puts ("1st sigmask failed");
+ exit (1);
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("1st create failed");
+ exit (1);
+ }
+
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("1st join failed");
+ exit (1);
+ }
+
+ sigemptyset (&ss);
+ sigaddset (&ss, SIGUSR2);
+ sigaddset (&ss, SIGFPE);
+ if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
+ {
+ puts ("2nd sigmask failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("2nd create failed");
+ exit (1);
+ }
+
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("2nd join failed");
+ exit (1);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-signal6.c
@@ -0,0 +1,191 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+#define N 2
+static pthread_barrier_t bar;
+static struct
+{
+ void *p;
+ pthread_t s;
+} ti[N];
+static int sig1;
+
+
+static void
+handler (int sig)
+{
+ pthread_t self = pthread_self ();
+ size_t i;
+
+ for (i = 0; i < N; ++i)
+ if (ti[i].s == self)
+ {
+ if ((uintptr_t) ti[i].p <= (uintptr_t) &self
+ && (uintptr_t) ti[i].p + 2 * MINSIGSTKSZ > (uintptr_t) &self)
+ {
+ puts ("alt stack not used");
+ exit (1);
+ }
+
+ printf ("thread %zu used alt stack for signal %d\n", i, sig);
+
+ return;
+ }
+
+ puts ("handler: thread not found");
+ exit (1);
+}
+
+
+static void *
+tf (void *arg)
+{
+ size_t nr = (uintptr_t) arg;
+ if (nr >= N)
+ {
+ puts ("wrong nr parameter");
+ exit (1);
+ }
+
+ sigset_t ss;
+ sigemptyset (&ss);
+ size_t i;
+ for (i = 0; i < N; ++i)
+ if (i != nr)
+ if (sigaddset (&ss, sig1 + i) != 0)
+ {
+ puts ("tf: sigaddset failed");
+ exit (1);
+ }
+ if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+ {
+ puts ("tf: sigmask failed");
+ exit (1);
+ }
+
+ void *p = malloc (2 * MINSIGSTKSZ);
+ if (p == NULL)
+ {
+ puts ("tf: malloc failed");
+ exit (1);
+ }
+
+ stack_t s;
+ s.ss_sp = p;
+ s.ss_size = 2 * MINSIGSTKSZ;
+ s.ss_flags = 0;
+ if (sigaltstack (&s, NULL) != 0)
+ {
+ puts ("tf: sigaltstack failed");
+ exit (1);
+ }
+
+ ti[nr].p = p;
+ ti[nr].s = pthread_self ();
+
+ pthread_barrier_wait (&bar);
+
+ pthread_barrier_wait (&bar);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ sig1 = SIGRTMIN;
+ if (sig1 + N > SIGRTMAX)
+ {
+ puts ("too few RT signals");
+ return 0;
+ }
+
+ struct sigaction sa;
+ sa.sa_handler = handler;
+ sa.sa_flags = 0;
+ sigemptyset (&sa.sa_mask);
+
+ if (sigaction (sig1, &sa, NULL) != 0
+ || sigaction (sig1 + 1, &sa, NULL) != 0
+ || sigaction (sig1 + 2, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ if (pthread_barrier_init (&bar, NULL, 1 + N) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ pthread_t th[N];
+ size_t i;
+ for (i = 0; i < N; ++i)
+ if (pthread_create (&th[i], NULL, tf, (void *) (long int) i) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ /* Block the three signals. */
+ sigset_t ss;
+ sigemptyset (&ss);
+ for (i = 0; i <= N; ++i)
+ sigaddset (&ss, sig1 + i);
+ if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+ {
+ puts ("main: sigmask failed");
+ return 1;
+ }
+
+ pthread_barrier_wait (&bar);
+
+ /* Send some signals. */
+ pid_t me = getpid ();
+ kill (me, sig1 + N);
+ for (i = 0; i < N; ++i)
+ kill (me, sig1 + i);
+ kill (me, sig1 + N);
+
+ /* Give the signals a chance to be worked on. */
+ sleep (1);
+
+ pthread_barrier_wait (&bar);
+
+ for (i = 0; i < N; ++i)
+ if (pthread_join (th[i], NULL) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-signal7.c
@@ -0,0 +1,58 @@
+/* Copyright (C) 2005-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthreadP.h>
+#include <signal.h>
+#include <stdio.h>
+
+
+static int
+do_test (void)
+{
+ int result = 0;
+
+ errno = 0;
+ if (sigaction (SIGCANCEL, NULL, NULL) == 0)
+ {
+ puts ("sigaction(SIGCANCEL) did not fail");
+ result = 1;
+ }
+ else if (errno != EINVAL)
+ {
+ puts ("sigaction(SIGCANCEL) did not set errno to EINVAL");
+ result = 1;
+ }
+
+ errno = 0;
+ if (sigaction (SIGSETXID, NULL, NULL) == 0)
+ {
+ puts ("sigaction(SIGSETXID) did not fail");
+ result = 1;
+ }
+ else if (errno != EINVAL)
+ {
+ puts ("sigaction(SIGSETXID) did not set errno to EINVAL");
+ result = 1;
+ }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-spin1.c
@@ -0,0 +1,56 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+
+
+static int
+do_test (void)
+{
+ pthread_spinlock_t s;
+
+ if (pthread_spin_init (&s, PTHREAD_PROCESS_PRIVATE) != 0)
+ {
+ puts ("spin_init failed");
+ return 1;
+ }
+
+ if (pthread_spin_lock (&s) != 0)
+ {
+ puts ("spin_lock failed");
+ return 1;
+ }
+
+ if (pthread_spin_unlock (&s) != 0)
+ {
+ puts ("spin_unlock failed");
+ return 1;
+ }
+
+ if (pthread_spin_destroy (&s) != 0)
+ {
+ puts ("spin_destroy failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-spin2.c
@@ -0,0 +1,158 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+
+static int
+do_test (void)
+{
+ size_t ps = sysconf (_SC_PAGESIZE);
+ char tmpfname[] = "/tmp/tst-spin2.XXXXXX";
+ char data[ps];
+ void *mem;
+ int fd;
+ pthread_spinlock_t *s;
+ pid_t pid;
+ char *p;
+ int err;
+
+ fd = mkstemp (tmpfname);
+ if (fd == -1)
+ {
+ printf ("cannot open temporary file: %m\n");
+ return 1;
+ }
+
+ /* Make sure it is always removed. */
+ unlink (tmpfname);
+
+ /* Create one page of data. */
+ memset (data, '\0', ps);
+
+ /* Write the data to the file. */
+ if (write (fd, data, ps) != (ssize_t) ps)
+ {
+ puts ("short write");
+ return 1;
+ }
+
+ mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (mem == MAP_FAILED)
+ {
+ printf ("mmap failed: %m\n");
+ return 1;
+ }
+
+ s = (pthread_spinlock_t *) (((uintptr_t) mem
+ + __alignof (pthread_spinlock_t))
+ & ~(__alignof (pthread_spinlock_t) - 1));
+ p = (char *) (s + 1);
+
+ if (pthread_spin_init (s, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("spin_init failed");
+ return 1;
+ }
+
+ if (pthread_spin_lock (s) != 0)
+ {
+ puts ("spin_lock failed");
+ return 1;
+ }
+
+ err = pthread_spin_trylock (s);
+ if (err == 0)
+ {
+ puts ("1st spin_trylock succeeded");
+ return 1;
+ }
+ else if (err != EBUSY)
+ {
+ puts ("1st spin_trylock didn't return EBUSY");
+ return 1;
+ }
+
+ err = pthread_spin_unlock (s);
+ if (err != 0)
+ {
+ puts ("parent: spin_unlock failed");
+ return 1;
+ }
+
+ err = pthread_spin_trylock (s);
+ if (err != 0)
+ {
+ puts ("2nd spin_trylock failed");
+ return 1;
+ }
+
+ *p = 0;
+
+ puts ("going to fork now");
+ pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ return 1;
+ }
+ else if (pid == 0)
+ {
+ /* Play some lock ping-pong. It's our turn to unlock first. */
+ if ((*p)++ != 0)
+ {
+ puts ("child: *p != 0");
+ return 1;
+ }
+
+ if (pthread_spin_unlock (s) != 0)
+ {
+ puts ("child: 1st spin_unlock failed");
+ return 1;
+ }
+
+ puts ("child done");
+ }
+ else
+ {
+ if (pthread_spin_lock (s) != 0)
+ {
+ puts ("parent: 2nd spin_lock failed");
+ return 1;
+ }
+
+ puts ("waiting for child");
+
+ waitpid (pid, NULL, 0);
+
+ puts ("parent done");
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-spin3.c
@@ -0,0 +1,53 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+static int
+do_test (void)
+{
+ pthread_spinlock_t s;
+
+ if (pthread_spin_init (&s, PTHREAD_PROCESS_PRIVATE) != 0)
+ {
+ puts ("spin_init failed");
+ return 1;
+ }
+
+ if (pthread_spin_lock (&s) != 0)
+ {
+ puts ("1st spin_lock failed");
+ return 1;
+ }
+
+ delayed_exit (1);
+
+ /* This call should never return. */
+ xpthread_spin_lock (&s);
+
+ puts ("2nd spin_lock returned");
+ return 1;
+}
--- /dev/null
+++ b/fbtl/tst-stack1.c
@@ -0,0 +1,145 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <limits.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <unistd.h>
+
+
+static void *stack;
+static size_t size;
+
+
+static void *
+tf (void *a)
+{
+ int result = 0;
+
+ puts ("child start");
+
+ pthread_attr_t attr;
+ if (pthread_getattr_np (pthread_self (), &attr) != 0)
+ {
+ puts ("getattr_np failed");
+ exit (1);
+ }
+
+ size_t test_size;
+ void *test_stack;
+ if (pthread_attr_getstack (&attr, &test_stack, &test_size) != 0)
+ {
+ puts ("attr_getstack failed");
+ exit (1);
+ }
+
+ if (test_size != size)
+ {
+ printf ("child: reported size differs: is %zu, expected %zu\n",
+ test_size, size);
+ result = 1;
+ }
+
+ if (test_stack != stack)
+ {
+ printf ("child: reported stack address differs: is %p, expected %p\n",
+ test_stack, stack);
+ result = 1;
+ }
+
+ puts ("child OK");
+
+ return result ? (void *) 1l : NULL;
+}
+
+
+int
+do_test (void)
+{
+ int result = 0;
+
+ size = MAX (4 * getpagesize (), PTHREAD_STACK_MIN);
+ if (posix_memalign (&stack, getpagesize (), size) != 0)
+ {
+ puts ("out of memory while allocating the stack memory");
+ exit (1);
+ }
+
+ pthread_attr_t attr;
+ if (pthread_attr_init (&attr) != 0)
+ {
+ puts ("attr_init failed");
+ exit (1);
+ }
+
+ puts ("attr_setstack");
+ if (pthread_attr_setstack (&attr, stack, size) != 0)
+ {
+ puts ("attr_setstack failed");
+ exit (1);
+ }
+
+ size_t test_size;
+ void *test_stack;
+ puts ("attr_getstack");
+ if (pthread_attr_getstack (&attr, &test_stack, &test_size) != 0)
+ {
+ puts ("attr_getstack failed");
+ exit (1);
+ }
+
+ if (test_size != size)
+ {
+ printf ("reported size differs: is %zu, expected %zu\n",
+ test_size, size);
+ result = 1;
+ }
+
+ if (test_stack != stack)
+ {
+ printf ("reported stack address differs: is %p, expected %p\n",
+ test_stack, stack);
+ result = 1;
+ }
+
+ puts ("create");
+
+ pthread_t th;
+ if (pthread_create (&th, &attr, tf, NULL) != 0)
+ {
+ puts ("failed to create thread");
+ exit (1);
+ }
+
+ void *status;
+ if (pthread_join (th, &status) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ result |= status != NULL;
+
+ return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-stack2.c
@@ -0,0 +1,78 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Test whether it is possible to create a thread with PTHREAD_STACK_MIN
+ stack size. */
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+static int seen;
+
+static void *
+tf (void *p)
+{
+ ++seen;
+ return NULL;
+}
+
+static int
+do_test (void)
+{
+ pthread_attr_t attr;
+ pthread_attr_init (&attr);
+
+ int result = 0;
+ int res = pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
+ if (res)
+ {
+ printf ("pthread_attr_setstacksize failed %d\n", res);
+ result = 1;
+ }
+
+ /* Create the thread. */
+ pthread_t th;
+ res = pthread_create (&th, &attr, tf, NULL);
+ if (res)
+ {
+ printf ("pthread_create failed %d\n", res);
+ result = 1;
+ }
+ else
+ {
+ res = pthread_join (th, NULL);
+ if (res)
+ {
+ printf ("pthread_join failed %d\n", res);
+ result = 1;
+ }
+ }
+
+ if (seen != 1)
+ {
+ printf ("seen %d != 1\n", seen);
+ result = 1;
+ }
+
+ return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-stack3.c
@@ -0,0 +1,100 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Test whether pthread_create/pthread_join with user defined stacks
+ doesn't leak memory.
+ NOTE: this tests functionality beyond POSIX. In POSIX user defined
+ stacks cannot be ever freed once used by pthread_create nor they can
+ be reused for other thread. */
+
+#include <limits.h>
+#include <mcheck.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+static int seen;
+
+static void *
+tf (void *p)
+{
+ ++seen;
+ return NULL;
+}
+
+static int
+do_test (void)
+{
+ mtrace ();
+
+ void *stack;
+ int res = posix_memalign (&stack, getpagesize (), 4 * PTHREAD_STACK_MIN);
+ if (res)
+ {
+ printf ("malloc failed %s\n", strerror (res));
+ return 1;
+ }
+
+ pthread_attr_t attr;
+ pthread_attr_init (&attr);
+
+ int result = 0;
+ res = pthread_attr_setstack (&attr, stack, 4 * PTHREAD_STACK_MIN);
+ if (res)
+ {
+ printf ("pthread_attr_setstack failed %d\n", res);
+ result = 1;
+ }
+
+ for (int i = 0; i < 16; ++i)
+ {
+ /* Create the thread. */
+ pthread_t th;
+ res = pthread_create (&th, &attr, tf, NULL);
+ if (res)
+ {
+ printf ("pthread_create failed %d\n", res);
+ result = 1;
+ }
+ else
+ {
+ res = pthread_join (th, NULL);
+ if (res)
+ {
+ printf ("pthread_join failed %d\n", res);
+ result = 1;
+ }
+ }
+ }
+
+ pthread_attr_destroy (&attr);
+
+ if (seen != 16)
+ {
+ printf ("seen %d != 16\n", seen);
+ result = 1;
+ }
+
+ free (stack);
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-stackguard1-static.c
@@ -0,0 +1 @@
+#include "tst-stackguard1.c"
--- /dev/null
+++ b/fbtl/tst-stackguard1.c
@@ -0,0 +1,226 @@
+/* Copyright (C) 2005-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <stackguard-macros.h>
+#include <tls.h>
+#include <unistd.h>
+
+static const char *command;
+static bool child;
+static uintptr_t stack_chk_guard_copy;
+static bool stack_chk_guard_copy_set;
+static int fds[2];
+
+static void __attribute__ ((constructor))
+con (void)
+{
+ stack_chk_guard_copy = STACK_CHK_GUARD;
+ stack_chk_guard_copy_set = true;
+}
+
+static int
+uintptr_t_cmp (const void *a, const void *b)
+{
+ if (*(uintptr_t *) a < *(uintptr_t *) b)
+ return 1;
+ if (*(uintptr_t *) a > *(uintptr_t *) b)
+ return -1;
+ return 0;
+}
+
+static void *
+tf (void *arg)
+{
+ if (stack_chk_guard_copy != STACK_CHK_GUARD)
+ {
+ puts ("STACK_CHK_GUARD changed in thread");
+ return (void *) 1L;
+ }
+ return NULL;
+}
+
+static int
+do_test (void)
+{
+ if (!stack_chk_guard_copy_set)
+ {
+ puts ("constructor has not been run");
+ return 1;
+ }
+
+ if (stack_chk_guard_copy != STACK_CHK_GUARD)
+ {
+ puts ("STACK_CHK_GUARD changed between constructor and do_test");
+ return 1;
+ }
+
+ if (child)
+ {
+ int i;
+ pthread_t th[4];
+ void *ret;
+ for (i = 0; i < 4; ++i)
+ if (pthread_create (&th[i], NULL, tf, NULL))
+ {
+ puts ("thread creation failed");
+ return 1;
+ }
+ for (i = 0; i < 4; ++i)
+ if (pthread_join (th[i], &ret))
+ {
+ puts ("thread join failed");
+ return 1;
+ }
+ else if (ret != NULL)
+ return 1;
+
+ write (2, &stack_chk_guard_copy, sizeof (stack_chk_guard_copy));
+ return 0;
+ }
+
+ if (command == NULL)
+ {
+ puts ("missing --command or --child argument");
+ return 1;
+ }
+
+#define N 16
+ uintptr_t child_stack_chk_guards[N + 1];
+ child_stack_chk_guards[N] = stack_chk_guard_copy;
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ if (pipe (fds) < 0)
+ {
+ printf ("couldn't create pipe: %m\n");
+ return 1;
+ }
+
+ pid_t pid = fork ();
+ if (pid < 0)
+ {
+ printf ("fork failed: %m\n");
+ return 1;
+ }
+
+ if (!pid)
+ {
+ if (stack_chk_guard_copy != STACK_CHK_GUARD)
+ {
+ puts ("STACK_CHK_GUARD changed after fork");
+ exit (1);
+ }
+
+ close (fds[0]);
+ close (2);
+ dup2 (fds[1], 2);
+ close (fds[1]);
+
+ system (command);
+ exit (0);
+ }
+
+ close (fds[1]);
+
+ if (TEMP_FAILURE_RETRY (read (fds[0], &child_stack_chk_guards[i],
+ sizeof (uintptr_t))) != sizeof (uintptr_t))
+ {
+ puts ("could not read stack_chk_guard value from child");
+ return 1;
+ }
+
+ close (fds[0]);
+
+ pid_t termpid;
+ int status;
+ termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
+ if (termpid == -1)
+ {
+ printf ("waitpid failed: %m\n");
+ return 1;
+ }
+ else if (termpid != pid)
+ {
+ printf ("waitpid returned %ld != %ld\n",
+ (long int) termpid, (long int) pid);
+ return 1;
+ }
+ else if (!WIFEXITED (status) || WEXITSTATUS (status))
+ {
+ puts ("child hasn't exited with exit status 0");
+ return 1;
+ }
+ }
+
+ qsort (child_stack_chk_guards, N + 1, sizeof (uintptr_t), uintptr_t_cmp);
+
+ uintptr_t default_guard = 0;
+ unsigned char *p = (unsigned char *) &default_guard;
+ p[sizeof (uintptr_t) - 1] = 255;
+ p[sizeof (uintptr_t) - 2] = '\n';
+ p[0] = 0;
+
+ /* Test if the stack guard canaries are either randomized,
+ or equal to the default stack guard canary value.
+ Even with randomized stack guards it might happen
+ that the random number generator generates the same
+ values, but if that happens in more than half from
+ the 16 runs, something is very wrong. */
+ int ndifferences = 0;
+ int ndefaults = 0;
+ for (i = 0; i < N; ++i)
+ {
+ if (child_stack_chk_guards[i] != child_stack_chk_guards[i+1])
+ ndifferences++;
+ else if (child_stack_chk_guards[i] == default_guard)
+ ndefaults++;
+ }
+
+ printf ("differences %d defaults %d\n", ndifferences, ndefaults);
+
+ if (ndifferences < N / 2 && ndefaults < N / 2)
+ {
+ puts ("stack guard canaries are not randomized enough");
+ puts ("nor equal to the default canary value");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define OPT_COMMAND 10000
+#define OPT_CHILD 10001
+#define CMDLINE_OPTIONS \
+ { "command", required_argument, NULL, OPT_COMMAND }, \
+ { "child", no_argument, NULL, OPT_CHILD },
+#define CMDLINE_PROCESS \
+ case OPT_COMMAND: \
+ command = optarg; \
+ break; \
+ case OPT_CHILD: \
+ child = true; \
+ break;
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-stdio1.c
@@ -0,0 +1,56 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+static void *tf (void *a)
+{
+ flockfile (stdout);
+ /* This call should never return. */
+ return a;
+}
+
+
+int
+do_test (void)
+{
+ pthread_t th;
+
+ flockfile (stdout);
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ write (2, "create failed\n", 14);
+ _exit (1);
+ }
+
+ delayed_exit (1);
+ xpthread_join (th);
+
+ puts ("join returned");
+
+ return 1;
+}
--- /dev/null
+++ b/fbtl/tst-stdio2.c
@@ -0,0 +1,81 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static void *tf (void *a)
+{
+ puts ("start tf");
+
+ /* Multiple locking, implicitly or explicitly, must be possible. */
+ flockfile (stdout);
+
+ puts ("after first flockfile");
+
+ flockfile (stdout);
+
+ puts ("foo");
+
+ funlockfile (stdout);
+
+ puts ("after first funlockfile");
+
+ funlockfile (stdout);
+
+ puts ("all done");
+
+ return a;
+}
+
+
+int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ write (2, "create failed\n", 14);
+ _exit (1);
+ }
+
+ void *result;
+ if (pthread_join (th, &result) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+ else if (result != NULL)
+ {
+ printf ("wrong return value: %p, expected %p\n", result, NULL);
+ exit (1);
+ }
+
+ puts ("join returned succsefully");
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-sysconf.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+static int
+do_test (void)
+{
+ puts ("We expect no limits");
+ /* We have no fixed limit on the number of threads. Make sure the
+ headers tell the right story. */
+#ifdef PTHREAD_THREADS_MAX
+ printf ("Header report maximum number of threads = %lu\n",
+ (unsigned long int) PTHREAD_THREADS_MAX);
+ return 1;
+#else
+ long int r = sysconf (_SC_THREAD_THREADS_MAX);
+ if (r != -1)
+ {
+ printf ("sysconf(_SC_THREAD_THREADS_MAX) return %ld\n", r);
+ return 1;
+ }
+#endif
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-tls1.c
@@ -0,0 +1,111 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+struct test_s
+{
+ int a;
+ int b;
+};
+
+#define INIT_A 1
+#define INIT_B 42
+/* Deliberately not static. */
+__thread struct test_s s __attribute__ ((tls_model ("initial-exec"))) =
+{
+ .a = INIT_A,
+ .b = INIT_B
+};
+
+
+static void *
+tf (void *arg)
+{
+ if (s.a != INIT_A || s.b != INIT_B)
+ {
+ puts ("initial value of s in child thread wrong");
+ exit (1);
+ }
+
+ ++s.a;
+
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+ if (s.a != INIT_A || s.b != INIT_B)
+ {
+ puts ("initial value of s in main thread wrong");
+ exit (1);
+ }
+
+ pthread_attr_t a;
+
+ if (pthread_attr_init (&a) != 0)
+ {
+ puts ("attr_init failed");
+ exit (1);
+ }
+
+ if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+#define N 10
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+#define M 10
+ pthread_t th[M];
+ int j;
+ for (j = 0; j < M; ++j, ++s.a)
+ if (pthread_create (&th[j], &a, tf, NULL) != 0)
+ {
+ puts ("pthread_create failed");
+ exit (1);
+ }
+
+ for (j = 0; j < M; ++j)
+ if (pthread_join (th[j], NULL) != 0)
+ {
+ puts ("pthread_join failed");
+ exit (1);
+ }
+ }
+
+ if (pthread_attr_destroy (&a) != 0)
+ {
+ puts ("attr_destroy failed");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-tls2.c
@@ -0,0 +1,205 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+#define N 10
+static pthread_t th[N];
+
+
+#define CB(n) \
+static void \
+cb##n (void) \
+{ \
+ if (th[n] != pthread_self ()) \
+ { \
+ write (STDOUT_FILENO, "wrong callback\n", 15); \
+ _exit (1); \
+ } \
+}
+CB (0)
+CB (1)
+CB (2)
+CB (3)
+CB (4)
+CB (5)
+CB (6)
+CB (7)
+CB (8)
+CB (9)
+static void (*cbs[]) (void) =
+{
+ cb0, cb1, cb2, cb3, cb4, cb5, cb6, cb7, cb8, cb9
+};
+
+
+static __thread void (*fp) (void) __attribute__ ((tls_model ("local-exec")));
+
+
+static sem_t s;
+
+
+#define THE_SIG SIGUSR1
+static void
+handler (int sig)
+{
+ if (sig != THE_SIG)
+ {
+ write (STDOUT_FILENO, "wrong signal\n", 13);
+ _exit (1);
+ }
+
+ fp ();
+
+ if (sem_post (&s) != 0)
+ {
+ write (STDOUT_FILENO, "sem_post failed\n", 16);
+ _exit (1);
+ }
+}
+
+
+static pthread_barrier_t b;
+
+#define TOTAL_SIGS 1000
+static int nsigs;
+
+
+static void *
+tf (void *arg)
+{
+ fp = arg;
+
+ pthread_barrier_wait (&b);
+
+ pthread_barrier_wait (&b);
+
+ if (nsigs != TOTAL_SIGS)
+ {
+ puts ("barrier_wait prematurely returns");
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+ if (pthread_barrier_init (&b, NULL, N + 1) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (sem_init (&s, 0, 0) != 0)
+ {
+ puts ("sem_init failed");
+ exit (1);
+ }
+
+ struct sigaction sa;
+ sa.sa_handler = handler;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+ if (sigaction (THE_SIG, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ exit (1);
+ }
+
+ pthread_attr_t a;
+
+ if (pthread_attr_init (&a) != 0)
+ {
+ puts ("attr_init failed");
+ exit (1);
+ }
+
+ if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+ int i;
+ for (i = 0; i < N; ++i)
+ if (pthread_create (&th[i], &a, tf, cbs[i]) != 0)
+ {
+ puts ("pthread_create failed");
+ exit (1);
+ }
+
+ if (pthread_attr_destroy (&a) != 0)
+ {
+ puts ("attr_destroy failed");
+ exit (1);
+ }
+
+ pthread_barrier_wait (&b);
+
+ sigset_t ss;
+ sigemptyset (&ss);
+ sigaddset (&ss, THE_SIG);
+ if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+ {
+ puts ("pthread_sigmask failed");
+ exit (1);
+ }
+
+ /* Start sending signals. */
+ for (i = 0; i < TOTAL_SIGS; ++i)
+ {
+ if (kill (getpid (), THE_SIG) != 0)
+ {
+ puts ("kill failed");
+ exit (1);
+ }
+
+ if (TEMP_FAILURE_RETRY (sem_wait (&s)) != 0)
+ {
+ puts ("sem_wait failed");
+ exit (1);
+ }
+
+ ++nsigs;
+ }
+
+ pthread_barrier_wait (&b);
+
+ for (i = 0; i < N; ++i)
+ if (pthread_join (th[i], NULL) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-tls3.c
@@ -0,0 +1,206 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <semaphore.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthreaddef.h>
+
+#define THE_SIG SIGUSR1
+
+
+#define N 10
+static pthread_t th[N];
+
+
+#define CB(n) \
+static void \
+cb##n (void) \
+{ \
+ if (th[n] != pthread_self ()) \
+ { \
+ write (STDOUT_FILENO, "wrong callback\n", 15); \
+ _exit (1); \
+ } \
+}
+CB (0)
+CB (1)
+CB (2)
+CB (3)
+CB (4)
+CB (5)
+CB (6)
+CB (7)
+CB (8)
+CB (9)
+static void (*cbs[]) (void) =
+{
+ cb0, cb1, cb2, cb3, cb4, cb5, cb6, cb7, cb8, cb9
+};
+
+
+sem_t s;
+
+
+pthread_barrier_t b;
+
+#define TOTAL_SIGS 1000
+int nsigs;
+
+
+int
+do_test (void)
+{
+ if ((uintptr_t) pthread_self () & (TCB_ALIGNMENT - 1))
+ {
+ puts ("initial thread's struct pthread not aligned enough");
+ exit (1);
+ }
+
+ if (pthread_barrier_init (&b, NULL, N + 1) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (sem_init (&s, 0, 0) != 0)
+ {
+ puts ("sem_init failed");
+ exit (1);
+ }
+
+ void *h = dlopen ("tst-tls3mod.so", RTLD_LAZY);
+ if (h == NULL)
+ {
+ puts ("dlopen failed");
+ exit (1);
+ }
+
+ void *(*tf) (void *) = dlsym (h, "tf");
+ if (tf == NULL)
+ {
+ puts ("dlsym for tf failed");
+ exit (1);
+ }
+
+ struct sigaction sa;
+ sa.sa_handler = dlsym (h, "handler");
+ if (sa.sa_handler == NULL)
+ {
+ puts ("dlsym for handler failed");
+ exit (1);
+ }
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+ if (sigaction (THE_SIG, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ exit (1);
+ }
+
+ pthread_attr_t a;
+
+ if (pthread_attr_init (&a) != 0)
+ {
+ puts ("attr_init failed");
+ exit (1);
+ }
+
+ if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+ int r;
+ for (r = 0; r < 10; ++r)
+ {
+ int i;
+ for (i = 0; i < N; ++i)
+ if (pthread_create (&th[i], &a, tf, cbs[i]) != 0)
+ {
+ puts ("pthread_create failed");
+ exit (1);
+ }
+
+ nsigs = 0;
+
+ pthread_barrier_wait (&b);
+
+ sigset_t ss;
+ sigemptyset (&ss);
+ sigaddset (&ss, THE_SIG);
+ if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+ {
+ puts ("pthread_sigmask failed");
+ exit (1);
+ }
+
+ /* Start sending signals. */
+ for (i = 0; i < TOTAL_SIGS; ++i)
+ {
+ if (kill (getpid (), THE_SIG) != 0)
+ {
+ puts ("kill failed");
+ exit (1);
+ }
+
+ if (TEMP_FAILURE_RETRY (sem_wait (&s)) != 0)
+ {
+ puts ("sem_wait failed");
+ exit (1);
+ }
+
+ ++nsigs;
+ }
+
+ pthread_barrier_wait (&b);
+
+ if (pthread_sigmask (SIG_UNBLOCK, &ss, NULL) != 0)
+ {
+ puts ("pthread_sigmask failed");
+ exit (1);
+ }
+
+ for (i = 0; i < N; ++i)
+ if (pthread_join (th[i], NULL) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+ }
+
+ if (pthread_attr_destroy (&a) != 0)
+ {
+ puts ("attr_destroy failed");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TIMEOUT 5
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-tls3mod.c
@@ -0,0 +1,88 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthreaddef.h>
+
+
+extern pthread_barrier_t b;
+
+#define TOTAL_SIGS 1000
+extern int nsigs;
+
+extern sem_t s;
+
+
+static __thread void (*fp) (void);
+
+
+#define THE_SIG SIGUSR1
+void
+handler (int sig)
+{
+ if (sig != THE_SIG)
+ {
+ write (STDOUT_FILENO, "wrong signal\n", 13);
+ _exit (1);
+ }
+
+ fp ();
+
+ if (sem_post (&s) != 0)
+ {
+ write (STDOUT_FILENO, "sem_post failed\n", 16);
+ _exit (1);
+ }
+}
+
+
+void *
+tf (void *arg)
+{
+ if ((uintptr_t) pthread_self () & (TCB_ALIGNMENT - 1))
+ {
+ puts ("thread's struct pthread not aligned enough");
+ exit (1);
+ }
+
+ if (fp != NULL)
+ {
+ puts ("fp not initially NULL");
+ exit (1);
+ }
+
+ fp = arg;
+
+ pthread_barrier_wait (&b);
+
+ pthread_barrier_wait (&b);
+
+ if (nsigs != TOTAL_SIGS)
+ {
+ puts ("barrier_wait prematurely returns");
+ exit (1);
+ }
+
+ return NULL;
+}
--- /dev/null
+++ b/fbtl/tst-tls4.c
@@ -0,0 +1,182 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <tls.h>
+
+
+#define N 3
+
+void (*test1) (void), (*test2) (void);
+
+pthread_barrier_t b2, b3;
+
+static void *
+tf (void *arg)
+{
+ int i;
+
+ for (i = 0; i <= (uintptr_t) arg; ++i)
+ {
+ int r = pthread_barrier_wait (&b3);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("tf: barrier_wait failed");
+ exit (1);
+ }
+ }
+
+ test1 ();
+
+ for (i = 0; i < 3; ++i)
+ {
+ int r = pthread_barrier_wait (&b3);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("tf: barrier_wait failed");
+ exit (1);
+ }
+ }
+
+ test2 ();
+
+ for (i = 0; i < 3 - (uintptr_t) arg; ++i)
+ {
+ int r = pthread_barrier_wait (&b3);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("tf: barrier_wait failed");
+ exit (1);
+ }
+ }
+
+ return NULL;
+}
+
+static void *
+tf2 (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("tf2: barrier_wait failed");
+ exit (1);
+ }
+
+ int i;
+ for (i = 0; i < N; ++i)
+ tf (arg);
+ return NULL;
+}
+
+int
+do_test (void)
+{
+ pthread_t th[2];
+ const char *modules[N]
+ = { "tst-tls4moda.so", "tst-tls4moda.so", "tst-tls4modb.so" };
+
+ if (pthread_barrier_init (&b2, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ if (pthread_barrier_init (&b3, NULL, 3) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ if (pthread_create (&th[0], NULL, tf2, (void *) (uintptr_t) 1))
+ {
+ puts ("pthread_create failed");
+ return 1;
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ return 1;
+ }
+
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ void *h = dlopen (modules[i], RTLD_LAZY);
+ if (h == NULL)
+ {
+ printf ("dlopen failed %s\n", dlerror ());
+ return 1;
+ }
+
+ test1 = dlsym (h, "test1");
+ if (test1 == NULL)
+ {
+ printf ("dlsym for test1 failed %s\n", dlerror ());
+ return 1;
+ }
+
+ test2 = dlsym (h, "test2");
+ if (test2 == NULL)
+ {
+ printf ("dlsym for test2 failed %s\n", dlerror ());
+ return 1;
+ }
+
+ if (pthread_create (&th[1], NULL, tf, (void *) (uintptr_t) 2))
+ {
+ puts ("pthread_create failed");
+ return 1;
+ }
+
+ tf ((void *) (uintptr_t) 0);
+
+ if (pthread_join (th[1], NULL) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ if (dlclose (h))
+ {
+ puts ("dlclose failed");
+ return 1;
+ }
+
+ printf ("test %d with %s succeeded\n", i, modules[i]);
+ }
+
+ if (pthread_join (th[0], NULL) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TIMEOUT 5
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-tls4moda.c
@@ -0,0 +1,52 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <tls.h>
+
+
+static __thread unsigned char foo [32]
+ __attribute__ ((tls_model ("initial-exec"), aligned (sizeof (void *))));
+
+void
+test1 (void)
+{
+ size_t s;
+
+ for (s = 0; s < sizeof (foo); ++s)
+ {
+ if (foo [s])
+ abort ();
+ foo [s] = s;
+ }
+}
+
+void
+test2 (void)
+{
+ size_t s;
+
+ for (s = 0; s < sizeof (foo); ++s)
+ {
+ if (foo [s] != s)
+ abort ();
+ foo [s] = sizeof (foo) - s;
+ }
+}
--- /dev/null
+++ b/fbtl/tst-tls4modb.c
@@ -0,0 +1,61 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <tls.h>
+
+
+static int i;
+int bar;
+
+static __thread void *foo [32 / sizeof (void *)]
+ __attribute__ ((tls_model ("initial-exec"), aligned (sizeof (void *))))
+ = { &i, &bar };
+
+void
+test1 (void)
+{
+ size_t s;
+
+ if (foo [0] != &i || foo [1] != &bar)
+ abort ();
+
+ foo [0] = NULL;
+ foo [1] = NULL;
+ for (s = 0; s < sizeof (foo) / sizeof (void *); ++s)
+ {
+ if (foo [s])
+ abort ();
+ foo [s] = &foo[s];
+ }
+}
+
+void
+test2 (void)
+{
+ size_t s;
+
+ for (s = 0; s < sizeof (foo) / sizeof (void *); ++s)
+ {
+ if (foo [s] != &foo [s])
+ abort ();
+ foo [s] = &foo [s ^ 1];
+ }
+}
--- /dev/null
+++ b/fbtl/tst-tls5.c
@@ -0,0 +1,119 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Check alignment, overlapping and layout of TLS variables. */
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <pthreadP.h>
+#include <sys/param.h>
+
+#include "tst-tls5.h"
+
+#ifdef TLS_REGISTER
+
+struct tls_obj tls_registry[64];
+
+static int
+tls_addr_cmp (const void *a, const void *b)
+{
+ if (((struct tls_obj *)a)->addr < ((struct tls_obj *)b)->addr)
+ return -1;
+ if (((struct tls_obj *)a)->addr > ((struct tls_obj *)b)->addr)
+ return 1;
+ return 0;
+}
+
+static int
+do_test (void)
+{
+ size_t cnt, i;
+ int res = 0;
+ uintptr_t min_addr = ~(uintptr_t) 0, max_addr = 0;
+
+ for (cnt = 0; tls_registry[cnt].name; ++cnt);
+ tls_registry[cnt].name = NULL;
+ tls_registry[cnt].addr = (uintptr_t) pthread_self ();
+ tls_registry[cnt].size = sizeof (struct pthread);
+ tls_registry[cnt++].align = __alignof__ (struct pthread);
+
+ qsort (tls_registry, cnt, sizeof (struct tls_obj), tls_addr_cmp);
+
+ for (i = 0; i < cnt; ++i)
+ {
+ printf ("%s%s = %p, size %zd, align %zd",
+ tls_registry[i].name ? "&" : "",
+ tls_registry[i].name ?: "pthread_self ()",
+ (void *) tls_registry[i].addr,
+ tls_registry[i].size, tls_registry[i].align);
+ if (tls_registry[i].addr & (tls_registry[i].align - 1))
+ {
+ fputs (", WRONG ALIGNMENT", stdout);
+ res = 1;
+ }
+ if (i > 0
+ && (tls_registry[i - 1].addr + tls_registry[i - 1].size
+ > tls_registry[i].addr))
+ {
+ fputs (", ADDRESS OVERLAP", stdout);
+ res = 1;
+ }
+ puts ("");
+ if (tls_registry[i].name)
+ {
+ min_addr = MIN (tls_registry[i].addr, min_addr);
+ max_addr = MAX (tls_registry[i].addr + tls_registry[i].size,
+ max_addr);
+ }
+ }
+
+ if (cnt > 1)
+ {
+#if TLS_TCB_AT_TP
+ if (tls_registry[cnt - 1].name)
+ {
+ puts ("pthread_self () not larger than all TLS addresses");
+ res = 1;
+ }
+ else
+ max_addr = MAX (tls_registry[cnt - 1].addr, max_addr);
+#elif TLS_DTV_AT_TP
+ if (tls_registry[0].name)
+ {
+ puts ("pthread_self () not smaller than all TLS addresses");
+ res = 1;
+ }
+#else
+ abort ();
+#endif
+ printf ("Initial TLS used block size %zd\n",
+ (size_t) (max_addr - min_addr));
+ }
+ return res;
+}
+
+#define TEST_FUNCTION do_test ()
+
+#else
+
+#define TEST_FUNCTION 0
+
+#endif
+
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-tls5.h
@@ -0,0 +1,25 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <tls.h>
+
+
+struct tls_obj
+{
+ const char *name;
+ uintptr_t addr;
+ size_t size;
+ size_t align;
+};
+extern struct tls_obj tls_registry[];
+
+#define TLS_REGISTER(x) \
+static void __attribute__((constructor)) \
+tls_register_##x (void) \
+{ \
+ size_t i; \
+ for (i = 0; tls_registry[i].name; ++i); \
+ tls_registry[i].name = #x; \
+ tls_registry[i].addr = (uintptr_t) &x; \
+ tls_registry[i].size = sizeof (x); \
+ tls_registry[i].align = __alignof__ (x); \
+}
--- /dev/null
+++ b/fbtl/tst-tls5mod.c
@@ -0,0 +1,6 @@
+#include <tst-tls5.h>
+
+#ifdef TLS_REGISTER
+/* Ensure tls_registry is exported from the binary. */
+void *tst_tls5mod attribute_hidden = tls_registry;
+#endif
--- /dev/null
+++ b/fbtl/tst-tls5moda.c
@@ -0,0 +1,6 @@
+#include <tst-tls5.h>
+
+#ifdef TLS_REGISTER
+static __thread char a [32] __attribute__ ((aligned (64)));
+TLS_REGISTER (a)
+#endif
--- /dev/null
+++ b/fbtl/tst-tls5modb.c
@@ -0,0 +1,6 @@
+#include <tst-tls5.h>
+
+#ifdef TLS_REGISTER
+static __thread int b;
+TLS_REGISTER (b)
+#endif
--- /dev/null
+++ b/fbtl/tst-tls5modc.c
@@ -0,0 +1,6 @@
+#include <tst-tls5.h>
+
+#ifdef TLS_REGISTER
+static __thread int c;
+TLS_REGISTER (c)
+#endif
--- /dev/null
+++ b/fbtl/tst-tls5modd.c
@@ -0,0 +1,6 @@
+#include <tst-tls5.h>
+
+#ifdef TLS_REGISTER
+static __thread int d;
+TLS_REGISTER (d)
+#endif
--- /dev/null
+++ b/fbtl/tst-tls5mode.c
@@ -0,0 +1,8 @@
+#include <tst-tls5.h>
+
+#ifdef TLS_REGISTER
+static __thread int e1 = 24;
+static __thread char e2 [32] __attribute__ ((aligned (64)));
+TLS_REGISTER (e1)
+TLS_REGISTER (e2)
+#endif
--- /dev/null
+++ b/fbtl/tst-tls5modf.c
@@ -0,0 +1,9 @@
+#include <tst-tls5.h>
+
+#ifdef TLS_REGISTER
+char tst_tls5modf[60] attribute_hidden = { 26 };
+static __thread int f1 = 24;
+static __thread char f2 [32] __attribute__ ((aligned (64)));
+TLS_REGISTER (f1)
+TLS_REGISTER (f2)
+#endif
--- /dev/null
+++ b/fbtl/tst-tls6.sh
@@ -0,0 +1,76 @@
+#! /bin/bash
+# A tls test.
+# Copyright (C) 2003-2013 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+set -e
+
+common_objpfx=$1; shift
+test_via_rtld_prefix=$1; shift
+test_wrapper_env=$1; shift
+logfile=$common_objpfx/fbtl/tst-tls6.out
+
+# We have to find libc and fbtl
+library_path=${common_objpfx}:${common_objpfx}fbtl
+tst_tls5="${test_via_rtld_prefix} ${common_objpfx}/fbtl/tst-tls5"
+
+LC_ALL=C
+export LC_ALL
+LANG=C
+export LANG
+
+> $logfile
+fail=0
+
+for aligned in a e f; do
+ echo "preload tst-tls5mod{$aligned,b,c,d}.so" >> $logfile
+ echo "===============" >> $logfile
+ ${test_wrapper_env} \
+ LD_PRELOAD="`echo ${common_objpfx}fbtl/tst-tls5mod{$aligned,b,c,d}.so \
+ | sed 's/:$//;s/: /:/g'`" ${tst_tls5} >> $logfile || fail=1
+ echo >> $logfile
+
+ echo "preload tst-tls5mod{b,$aligned,c,d}.so" >> $logfile
+ echo "===============" >> $logfile
+ ${test_wrapper_env} \
+ LD_PRELOAD="`echo ${common_objpfx}fbtl/tst-tls5mod{b,$aligned,c,d}.so \
+ | sed 's/:$//;s/: /:/g'`" ${tst_tls5} >> $logfile || fail=1
+ echo >> $logfile
+
+ echo "preload tst-tls5mod{b,c,d,$aligned}.so" >> $logfile
+ echo "===============" >> $logfile
+ ${test_wrapper_env} \
+ LD_PRELOAD="`echo ${common_objpfx}fbtl/tst-tls5mod{b,c,d,$aligned}.so \
+ | sed 's/:$//;s/: /:/g'`" ${tst_tls5} >> $logfile || fail=1
+ echo >> $logfile
+done
+
+echo "preload tst-tls5mod{d,a,b,c,e}" >> $logfile
+echo "===============" >> $logfile
+${test_wrapper_env} \
+LD_PRELOAD="`echo ${common_objpfx}fbtl/tst-tls5mod{d,a,b,c,e}.so \
+ | sed 's/:$//;s/: /:/g'`" ${tst_tls5} >> $logfile || fail=1
+echo >> $logfile
+
+echo "preload tst-tls5mod{d,a,b,e,f}" >> $logfile
+echo "===============" >> $logfile
+${test_wrapper_env} \
+LD_PRELOAD="`echo ${common_objpfx}fbtl/tst-tls5mod{d,a,b,e,f}.so \
+ | sed 's/:$//;s/: /:/g'`" ${tst_tls5} >> $logfile || fail=1
+echo >> $logfile
+
+exit $fail
--- /dev/null
+++ b/fbtl/tst-tpp.h
@@ -0,0 +1,93 @@
+/* Copyright (C) 2006-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <sched.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+/* This test is Linux specific. */
+#define CHECK_TPP_PRIORITY(normal, boosted) \
+ do \
+ { \
+ pid_t tid = syscall (__NR_gettid); \
+ \
+ struct sched_param cep_sp; \
+ int cep_policy; \
+ if (pthread_getschedparam (pthread_self (), &cep_policy, \
+ &cep_sp) != 0) \
+ { \
+ puts ("getschedparam failed"); \
+ ret = 1; \
+ } \
+ else if (cep_sp.sched_priority != (normal)) \
+ { \
+ printf ("unexpected priority %d != %d\n", \
+ cep_sp.sched_priority, (normal)); \
+ } \
+ if (syscall (__NR_sched_getparam, tid, &cep_sp) == 0 \
+ && cep_sp.sched_priority != (boosted)) \
+ { \
+ printf ("unexpected boosted priority %d != %d\n", \
+ cep_sp.sched_priority, (boosted)); \
+ ret = 1; \
+ } \
+ } \
+ while (0)
+
+int fifo_min, fifo_max;
+
+void
+init_tpp_test (void)
+{
+ fifo_min = sched_get_priority_min (SCHED_FIFO);
+ if (fifo_min < 0)
+ {
+ printf ("couldn't get min priority for SCHED_FIFO: %m\n");
+ exit (1);
+ }
+
+ fifo_max = sched_get_priority_max (SCHED_FIFO);
+ if (fifo_max < 0)
+ {
+ printf ("couldn't get max priority for SCHED_FIFO: %m\n");
+ exit (1);
+ }
+
+ if (fifo_min > 4 || fifo_max < 10)
+ {
+ printf ("%d..%d SCHED_FIFO priority interval not suitable for this test\n",
+ fifo_min, fifo_max);
+ exit (0);
+ }
+
+ struct sched_param sp;
+ memset (&sp, 0, sizeof (sp));
+ sp.sched_priority = 4;
+ int e = pthread_setschedparam (pthread_self (), SCHED_FIFO, &sp);
+ if (e != 0)
+ {
+ errno = e;
+ printf ("cannot set scheduling params: %m\n");
+ exit (0);
+ }
+}
--- /dev/null
+++ b/fbtl/tst-tsd1.c
@@ -0,0 +1,117 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+
+
+static int
+do_test (void)
+{
+ pthread_key_t key1;
+ pthread_key_t key2;
+ void *value;
+ int result = 0;
+ int err;
+
+ err = pthread_key_create (&key1, NULL);
+ if (err != 0)
+ {
+ printf ("1st key_create failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ /* Initial value must be NULL. */
+ value = pthread_getspecific (key1);
+ if (value != NULL)
+ {
+ puts ("1st getspecific != NULL");
+ result = 1;
+ }
+
+ err = pthread_setspecific (key1, (void *) -2l);
+ if (err != 0)
+ {
+ printf ("1st setspecific failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ value = pthread_getspecific (key1);
+ if (value == NULL)
+ {
+ puts ("2nd getspecific == NULL\n");
+ result = 1;
+ }
+ else if (value != (void *) -2l)
+ {
+ puts ("2nd getspecific != -2l\n");
+ result = 1;
+ }
+
+ err = pthread_setspecific (key1, (void *) -3l);
+ if (err != 0)
+ {
+ printf ("2nd setspecific failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ value = pthread_getspecific (key1);
+ if (value == NULL)
+ {
+ puts ("3rd getspecific == NULL\n");
+ result = 1;
+ }
+ else if (value != (void *) -3l)
+ {
+ puts ("3rd getspecific != -2l\n");
+ result = 1;
+ }
+
+ err = pthread_key_delete (key1);
+ if (err != 0)
+ {
+ printf ("key_delete failed: %s\n", strerror (err));
+ result = 1;
+ }
+
+
+ err = pthread_key_create (&key2, NULL);
+ if (err != 0)
+ {
+ printf ("2nd key_create failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ if (key1 != key2)
+ puts ("key1 != key2; no more tests performed");
+ else
+ {
+ value = pthread_getspecific (key2);
+ if (value != NULL)
+ {
+ puts ("4th getspecific != NULL");
+ result = 1;
+ }
+ }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-tsd2.c
@@ -0,0 +1,96 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+
+
+static int result;
+
+
+static void
+destr (void *arg)
+{
+ if (arg != (void *) -2l)
+ result = 2;
+ else
+ result = 0;
+}
+
+
+static void *
+tf (void *arg)
+{
+ pthread_key_t key = (pthread_key_t) (long int) arg;
+ int err;
+
+ err = pthread_setspecific (key, (void *) -2l);
+ if (err != 0)
+ result = 3;
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_key_t key;
+ pthread_t th;
+ int err;
+
+ err = pthread_key_create (&key, destr);
+ if (err != 0)
+ {
+ printf ("key_create failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ result = 1;
+
+ err = pthread_create (&th, NULL, tf, (void *) (long int) key);
+ if (err != 0)
+ {
+ printf ("create failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ /* Wait for the thread to terminate. */
+ err = pthread_join (th, NULL);
+ if (err != 0)
+ {
+ printf ("join failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ if (result == 1)
+ puts ("destructor not called");
+ else if (result == 2)
+ puts ("destructor got passed a wrong value");
+ else if (result == 3)
+ puts ("setspecific in child failed");
+ else if (result != 0)
+ puts ("result != 0");
+
+ return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-tsd3.c
@@ -0,0 +1,128 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <limits.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static pthread_key_t key1;
+static pthread_key_t key2;
+
+
+static int left;
+
+
+static void
+destr1 (void *arg)
+{
+ if (--left > 0)
+ {
+ puts ("set key2");
+
+ if (pthread_setspecific (key2, (void *) 1l) != 0)
+ {
+ puts ("destr1: setspecific failed");
+ exit (1);
+ }
+ }
+}
+
+
+static void
+destr2 (void *arg)
+{
+ if (--left > 0)
+ {
+ puts ("set key1");
+
+ if (pthread_setspecific (key1, (void *) 1l) != 0)
+ {
+ puts ("destr2: setspecific failed");
+ exit (1);
+ }
+ }
+}
+
+
+static void *
+tf (void *arg)
+{
+ /* Let the destructors work. */
+ left = 7;
+
+ if (pthread_setspecific (key1, (void *) 1l) != 0
+ || pthread_setspecific (key2, (void *) 1l) != 0)
+ {
+ puts ("tf: setspecific failed");
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ /* Allocate two keys, both with destructors. */
+ if (pthread_key_create (&key1, destr1) != 0
+ || pthread_key_create (&key2, destr2) != 0)
+ {
+ puts ("key_create failed");
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ if (pthread_join (th, NULL) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ if (left != 0)
+ {
+ printf ("left == %d\n", left);
+ return 1;
+ }
+
+ if (pthread_getspecific (key1) != NULL)
+ {
+ puts ("key1 data != NULL");
+ return 1;
+ }
+ if (pthread_getspecific (key2) != NULL)
+ {
+ puts ("key2 data != NULL");
+ return 1;
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-tsd4.c
@@ -0,0 +1,102 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <limits.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static pthread_key_t key;
+
+
+static int rounds;
+
+
+static void
+destr (void *arg)
+{
+ ++rounds;
+
+ if (pthread_setspecific (key, (void *) 1l) != 0)
+ {
+ puts ("destr: setspecific failed");
+ exit (1);
+ }
+}
+
+
+static void *
+tf (void *arg)
+{
+ if (pthread_setspecific (key, (void *) 1l) != 0)
+ {
+ puts ("tf: setspecific failed");
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+/* This test check non-standard behavior. The standard does not
+ require that the implementation has to stop calling TSD destructors
+ when they are set over and over again. But NPTL does. */
+static int
+do_test (void)
+{
+ /* Allocate two keys, both with destructors. */
+ if (pthread_key_create (&key, destr) != 0)
+ {
+ puts ("key_create failed");
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ if (pthread_join (th, NULL) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ if (rounds < PTHREAD_DESTRUCTOR_ITERATIONS)
+ {
+ printf ("rounds == %d, PTHREAD_DESTRUCTOR_ITERATIONS = %d\n",
+ rounds, PTHREAD_DESTRUCTOR_ITERATIONS);
+ return 1;
+ }
+
+ if (pthread_getspecific (key) != NULL)
+ {
+ puts ("key data != NULL");
+ return 1;
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-tsd5.c
@@ -0,0 +1,80 @@
+/* Copyright (C) 2004-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void
+cl (void *p)
+{
+ pthread_mutex_unlock (&m);
+}
+
+
+static void *
+tf (void *arg)
+{
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("2nd mutex_lock failed");
+ exit (1);
+ }
+
+ exit (0);
+}
+
+
+static int
+do_test (void)
+{
+ pthread_key_t k;
+ if (pthread_key_create (&k, cl) != 0)
+ {
+ puts ("key_create failed");
+ return 1;
+ }
+ if (pthread_setspecific (k, (void *) 1) != 0)
+ {
+ puts ("setspecific failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("1st mutex_lock failed");
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ pthread_exit (NULL);
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-tsd6.c
@@ -0,0 +1,89 @@
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+#define NKEYS 100
+static pthread_key_t keys[NKEYS];
+static pthread_barrier_t b;
+
+
+static void *
+tf (void *arg)
+{
+ void *res = NULL;
+ for (int i = 0; i < NKEYS; ++i)
+ {
+ void *p = pthread_getspecific (keys[i]);
+ pthread_setspecific (keys[i], (void *) 7);
+ if (p != NULL)
+ res = p;
+ }
+ if (arg != NULL)
+ {
+ pthread_barrier_wait (arg);
+ pthread_barrier_wait (arg);
+ }
+ return res;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_barrier_init (&b, NULL, 2);
+
+ for (int i = 0; i < NKEYS; ++i)
+ if (pthread_key_create (&keys[i], NULL) != 0)
+ {
+ puts ("cannot create keys");
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, &b) != 0)
+ {
+ puts ("cannot create thread in parent");
+ return 1;
+ }
+
+ pthread_barrier_wait (&b);
+
+ pid_t pid = fork ();
+ if (pid == 0)
+ {
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("cannot create thread in child");
+ exit (1);
+ }
+
+ void *res;
+ pthread_join (th, &res);
+
+ exit (res != NULL);
+ }
+ else if (pid == -1)
+ {
+ puts ("cannot create child process");
+ return 1;
+ }
+
+ int s;
+ if (TEMP_FAILURE_RETRY (waitpid (pid, &s, 0)) != pid)
+ {
+ puts ("failing to wait for child process");
+ return 1;
+ }
+
+ pthread_barrier_wait (&b);
+ pthread_join (th, NULL);
+
+ return !WIFEXITED (s) ? 2 : WEXITSTATUS (s);
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-typesizes.c
@@ -0,0 +1,95 @@
+/* Copyright (C) 2005-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <pthreadP.h>
+#include <semaphore.h>
+
+static const struct
+{
+ const char *name;
+ size_t expected;
+ size_t is;
+} types[] =
+ {
+#define T(t, c) \
+ { #t, c, sizeof (t) }
+ T (pthread_attr_t, __SIZEOF_PTHREAD_ATTR_T),
+ T (pthread_mutex_t, __SIZEOF_PTHREAD_MUTEX_T),
+ T (pthread_mutexattr_t, __SIZEOF_PTHREAD_MUTEXATTR_T),
+ T (pthread_cond_t, __SIZEOF_PTHREAD_COND_T),
+ T (pthread_condattr_t, __SIZEOF_PTHREAD_CONDATTR_T),
+ T (pthread_rwlock_t, __SIZEOF_PTHREAD_RWLOCK_T),
+ T (pthread_rwlockattr_t, __SIZEOF_PTHREAD_RWLOCKATTR_T),
+ T (pthread_barrier_t, __SIZEOF_PTHREAD_BARRIER_T),
+ T (pthread_barrierattr_t, __SIZEOF_PTHREAD_BARRIERATTR_T)
+ };
+
+static int
+do_test (void)
+{
+ int result = 0;
+
+#define TEST_TYPE(name) \
+ printf ("%s: ", #name); \
+ if (sizeof (name) != sizeof (((name *) 0)->__size)) \
+ { \
+ printf ("expected %zu, is %zu\n", \
+ sizeof (((name *) 0)->__size), sizeof (name)); \
+ result = 1; \
+ } \
+ else \
+ puts ("OK")
+
+ TEST_TYPE (pthread_mutex_t);
+ TEST_TYPE (pthread_cond_t);
+ TEST_TYPE (pthread_rwlock_t);
+
+#define TEST_TYPE2(name, internal) \
+ printf ("%s: ", #name); \
+ if (sizeof (((name *) 0)->__size) < sizeof (internal)) \
+ { \
+ printf ("expected %zu, is %zu\n", \
+ sizeof (((name *) 0)->__size), sizeof (internal)); \
+ result = 1; \
+ } \
+ else \
+ puts ("OK")
+
+ TEST_TYPE2 (pthread_attr_t, struct pthread_attr);
+ TEST_TYPE2 (pthread_mutexattr_t, struct pthread_mutexattr);
+ TEST_TYPE2 (pthread_condattr_t, struct pthread_condattr);
+ TEST_TYPE2 (pthread_rwlockattr_t, struct pthread_rwlockattr);
+ TEST_TYPE2 (pthread_barrier_t, struct pthread_barrier);
+ TEST_TYPE2 (pthread_barrierattr_t, struct pthread_barrierattr);
+ TEST_TYPE2 (sem_t, struct new_sem);
+ TEST_TYPE2 (sem_t, struct old_sem);
+
+ for (size_t i = 0; i < sizeof (types) / sizeof (types[0]); ++i)
+ if (types[i].expected != types[i].is)
+ {
+ printf ("%s: expected %zu, is %zu\n",
+ types[i].name, types[i].expected, types[i].is);
+ result = 1;
+ }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-umask1.c
@@ -0,0 +1,136 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+
+static struct
+{
+ int (*fp) (const char *, mode_t);
+ const char *name;
+ bool is_fd;
+} fcts[] =
+{
+ { creat, "creat", true },
+ { mkdir, "mkdir", false },
+ { mkfifo, "mkfifo", false },
+};
+#define nfcts (sizeof (fcts) / sizeof (fcts[0]))
+
+
+static int
+work (const char *fname, int mask)
+{
+ int result = 0;
+ size_t i;
+ for (i = 0; i < nfcts; ++i)
+ {
+ remove (fname);
+ int fd = fcts[i].fp (fname, 0777);
+ if (fd == -1)
+ {
+ printf ("cannot %s %s: %m\n", fcts[i].name, fname);
+ exit (1);
+ }
+ if (fcts[i].is_fd)
+ close (fd);
+ struct stat64 st;
+ if (stat64 (fname, &st) == -1)
+ {
+ printf ("cannot stat %s after %s: %m\n", fname, fcts[i].name);
+ exit (1);
+ }
+
+ if ((st.st_mode & mask) != 0)
+ {
+ printf ("mask not successful after %s: %x still set\n",
+ fcts[i].name, (unsigned int) (st.st_mode & mask));
+ result = 1;
+ }
+ }
+
+ return result;
+}
+
+
+static pthread_barrier_t bar;
+
+
+static void *
+tf (void *arg)
+{
+ pthread_barrier_wait (&bar);
+
+ int result = work (arg, 022);
+
+ pthread_barrier_wait (&bar);
+
+ pthread_barrier_wait (&bar);
+
+ return (work (arg, 0) | result) ? (void *) -1l : NULL;
+}
+
+
+static int
+do_test (const char *fname)
+{
+ int result = 0;
+
+ umask (0);
+ result |= work (fname, 0);
+
+ pthread_barrier_init (&bar, NULL, 2);
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, (void *) fname) != 0)
+ {
+ puts ("cannot create thread");
+ exit (1);
+ }
+
+ umask (022);
+ result |= work (fname, 022);
+
+ pthread_barrier_wait (&bar);
+
+ pthread_barrier_wait (&bar);
+
+ umask (0);
+
+ pthread_barrier_wait (&bar);
+
+ void *res;
+ if (pthread_join (th, &res) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ remove (fname);
+
+ return result || res != NULL;
+}
+
+#define TEST_FUNCTION do_test (argc < 2 ? "/tmp/tst-umask.tmp" : argv[1])
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-unload.c
@@ -0,0 +1,47 @@
+/* Tests for non-unloading of libpthread.
+ Copyright (C) 2000-2013 Free Software Foundation, Inc.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <gnu/lib-names.h>
+
+static int
+do_test (void)
+{
+ void *p = dlopen (LIBPTHREAD_SO, RTLD_LAZY);
+
+ if (p == NULL)
+ {
+ puts ("failed to load " LIBPTHREAD_SO);
+ return 1;
+ }
+
+ if (dlclose (p) != 0)
+ {
+ puts ("dlclose (" LIBPTHREAD_SO ") failed");
+ return 1;
+ }
+
+ puts ("seems to work");
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- /dev/null
+++ b/fbtl/tst-vfork1.c
@@ -0,0 +1 @@
+#include <posix/tst-vfork1.c>
--- /dev/null
+++ b/fbtl/tst-vfork1x.c
@@ -0,0 +1 @@
+#include <posix/tst-vfork1.c>
--- /dev/null
+++ b/fbtl/tst-vfork2.c
@@ -0,0 +1 @@
+#include <posix/tst-vfork2.c>
--- /dev/null
+++ b/fbtl/tst-vfork2x.c
@@ -0,0 +1 @@
+#include <posix/tst-vfork2.c>
--- /dev/null
+++ b/fbtl/unwind.c
@@ -0,0 +1,148 @@
+/* Copyright (C) 2003-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <setjmp.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "pthreadP.h"
+#include <jmpbuf-unwind.h>
+
+#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 (__glibc_unlikely (curp != NULL))
+ {
+ /* 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_Ptr) _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. */
+#if 0 // does not work due to multiple macro expansions
+# 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"));
+#else
+# define UNWIND_FAILED_MSG "FATAL: exception not rethrown\n"
+ INTERNAL_SYSCALL_DECL (err);
+ INTERNAL_SYSCALL (write, err, 3, STDERR_FILENO,
+ UNWIND_FAILED_MSG, strlen(UNWIND_FAILED_MSG));
+#endif
+ abort ();
+}
+
+
+void
+__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;
+
+ /* 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);
+ /* 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)
--- /dev/null
+++ b/fbtl/vars.c
@@ -0,0 +1,43 @@
+/* Copyright (C) 2004-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthreadP.h>
+#include <stdlib.h>
+#include <tls.h>
+#include <unistd.h>
+
+/* Default thread attributes for the case when the user does not
+ provide any. */
+struct pthread_attr __default_pthread_attr attribute_hidden;
+
+/* Mutex protecting __default_pthread_attr. */
+int __default_pthread_attr_lock = LLL_LOCK_INITIALIZER;
+
+/* 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 either if more than one thread runs or ran,
+ or if a single-threaded process is trying to cancel itself. See
+ nptl/descr.h for more context on the single-threaded process case. */
+int __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)
--- /dev/null
+++ b/fbtl/version.c
@@ -0,0 +1,42 @@
+/* Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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"
+"Forced unwind support included.\n"
+;
+
+
+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);
+}
--- /dev/null
+++ b/fbtl_db/ChangeLog
@@ -0,0 +1,333 @@
+2013-05-31 Joseph Myers <joseph@codesourcery.com>
+
+ * Makefile ($(objpfx)libthread_db.so): Remove dependencies on
+ libc.
+
+2013-05-16 Ryan S. Arnold <rsa@linux.vnet.ibm.com>
+
+ * db_info.c: Add missing #include <stdint.h> due to uint64_t or
+ uint32_t usage.
+ * fetch-value.c: Likewise.
+ * td_ta_clear_event.c: Likewise.
+ * td_ta_set_event.c: Likewise.
+ * td_ta_tsd_iter.c: Likewise.
+ * td_thr_clear_event.c: Likewise.
+ * td_thr_get_info.c: Likewise.
+ * td_thr_set_event.c: Likewise.
+ * td_thr_tsd.c: Likewise.
+
+2013-01-02 Joseph Myers <joseph@codesourcery.com>
+
+ * All files with FSF copyright notices: Update copyright dates
+ using scripts/update-copyrights.
+
+2013-01-01 Joseph Myers <joseph@codesourcery.com>
+
+ * td_ta_thr_iter.c: Reformat copyright notice.
+ * td_thr_validate.c: Likewise.
+
+2012-11-23 Mike Frysinger <vapier@gentoo.org>
+
+ * Makefile ($(objpfx)db-symbols.out): Change readelf to $(READELF).
+
+2012-10-08 Jonathan Nieder <jrnieder@gmail.com>
+
+ [BZ #14661]
+ * Makefile ($(objpfx)db-symbols.out): Force C locale when running
+ readelf -s.
+
+2012-03-07 Ulrich Drepper <drepper@gmail.com>
+
+ * Makefile (distribute): Remove variable.
+
+2011-09-15 Andreas Schwab <schwab@redhat.com>
+
+ * thread_dbP.h: Include <list.h>
+
+2009-08-23 Roland McGrath <roland@redhat.com>
+
+ * td_ta_map_lwp2thr.c (__td_ta_lookup_th_unique): Move ta_ok check
+ and LOG call back to ...
+ (td_ta_map_lwp2thr): ... here.
+ Reported by Maciej W. Rozycki <macro@codesourcery.com>.
+
+2009-05-25 Aurelien Jarno <aurelien@aurel32.net>
+
+ [BZ #10200]
+ * db-symbols.awk: Use the last field for the symbol name instead
+ of the 8th one.
+
+2009-03-19 Roland McGrath <roland@redhat.com>
+
+ * td_symbol_list.c (DB_LOOKUP_NAME, DB_LOOKUP_NAME_TH_UNIQUE):
+ Use STRINGIFY macro in place of #argument.
+
+2009-02-27 Roland McGrath <roland@redhat.com>
+
+ * td_symbol_list.c (symbol_list_arr): Move initializer guts to ...
+ * db-symbols.h: ... here, new file.
+ * db-symbols.awk: New file.
+ * Makefile (distribute): Add them.
+ ($(objpfx)db-symbols.out): New target.
+ (tests): Depend on it.
+ ($(objpfx)db-symbols.v.i): New dependent rule.
+
+2009-02-06 Ulrich Drepper <drepper@redhat.com>
+
+ * td_thr_get_info.c (td_thr_get_info): Initialize schedpolicy in
+ the special case [Coverity CID 251].
+
+2008-03-25 Roland McGrath <roland@redhat.com>
+
+ [BZ #5983]
+ * structs.def: Add pid field of struct pthread.
+ * td_ta_thr_iter.c (iterate_thread_list): Take new arg MATCH_PID.
+ If a thread's pid does not match nor is < 0 while its tid matches
+ nor is < 0 and equal to -MATCH_PID, ignore it.
+ * td_thr_validate.c (td_thr_validate): Validate thread's pid/tid.
+
+2007-05-16 Roland McGrath <roland@redhat.com>
+
+ * td_thr_get_info.c: Fake the results for TH->th_unique == 0.
+ * td_thr_validate.c: Likewise.
+ * td_thr_setgregs.c: Likewise.
+ * td_thr_setfpregs.c: Likewise.
+ * td_thr_getgregs.c: Likewise.
+ * td_thr_getfpregs.c: Likewise.
+ * td_thr_tlsbase.c: Likewise.
+
+ * structs.def: Add DB_VARIABLE (__nptl_initial_report_events).
+ * db_info.c: Add necessary declaration.
+ * td_thr_event_enable.c: Set __nptl_initial_report_events too.
+
+ * td_ta_thr_iter.c (iterate_thread_list): Make FAKE_EMPTY bool.
+ Use th_unique=0 in fake descriptor before initialization.
+
+ * td_ta_map_lwp2thr.c (__td_ta_lookup_th_unique): New function, broken
+ out of ...
+ (td_ta_map_lwp2thr): ... here, call it. But don't before __stack_user
+ is initialized, then fake a handle with th_unique=0.
+ * thread_dbP.h: Declare it.
+
+2006-10-26 Pete Eberlein <eberlein@us.ibm.com>
+
+ * nptl_db/db_info.c [TLS_DTV_AT_TP]: Fixed size init for dtvp
+ to sizeof a pointer, instead of sizeof the union.
+
+2006-10-27 Ulrich Drepper <drepper@redhat.com>
+
+ * structs.def: USE_TLS support is now default.
+
+2006-02-03 Roland McGrath <roland@redhat.com>
+
+ * structs.def: Add a descriptor for pointer.val field of dtv_t.
+ * td_thr_tlsbase.c (td_thr_tlsbase): Extract pointer.val field from
+ DTV slot.
+
+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.
--- /dev/null
+++ b/fbtl_db/Makefile
@@ -0,0 +1,59 @@
+# Copyright (C) 2002-2013 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+# Makefile for NPTL debug library subdirectory of GNU C Library.
+
+subdir := fbtl_db
+
+fbtl_db-version = 1.0
+
+extra-libs = libthread_db
+extra-libs-others := $(extra-libs)
+
+headers = thread_db.h
+
+libthread_db-routines = td_init td_log td_ta_new td_ta_delete \
+ td_ta_get_nthreads td_ta_get_ph \
+ td_ta_map_id2thr td_ta_map_lwp2thr \
+ td_ta_thr_iter td_ta_tsd_iter \
+ td_thr_get_info td_thr_getfpregs td_thr_getgregs \
+ td_thr_getxregs td_thr_getxregsize td_thr_setfpregs \
+ td_thr_setgregs td_thr_setprio td_thr_setsigpending \
+ td_thr_setxregs td_thr_sigsetmask td_thr_tsd \
+ td_thr_validate td_thr_dbsuspend td_thr_dbresume \
+ td_ta_setconcurrency td_ta_enable_stats \
+ td_ta_reset_stats td_ta_get_stats td_ta_event_addr \
+ td_thr_event_enable td_thr_set_event \
+ td_thr_clear_event td_thr_event_getmsg \
+ td_ta_set_event td_ta_event_getmsg \
+ td_ta_clear_event td_symbol_list \
+ td_thr_tlsbase td_thr_tls_get_addr \
+ fetch-value
+
+libthread_db-inhibit-o = $(filter-out .os,$(object-suffixes))
+
+# The ps_* callback functions are not defined.
+libthread_db.so-no-z-defs = yes
+
+include ../Rules
+
+tests: $(objpfx)db-symbols.out
+$(objpfx)db-symbols.out: $(objpfx)db-symbols.v.i \
+ $(common-objpfx)fbtl/libpthread.so
+ LC_ALL=C $(READELF) -W -s $(filter %.so,$^) | $(AWK) -f $< > $@
+
+$(objpfx)db-symbols.v.i: db-symbols.awk
--- /dev/null
+++ b/fbtl_db/Versions
@@ -0,0 +1,24 @@
+libthread_db {
+ GLIBC_2.1.3 {
+ # t*
+ td_init; td_log; td_ta_clear_event; td_ta_delete; td_ta_enable_stats;
+ td_ta_event_addr; td_ta_event_getmsg; td_ta_get_nthreads; td_ta_get_ph;
+ td_ta_get_stats; td_ta_map_id2thr; td_ta_map_lwp2thr; td_ta_new;
+ td_ta_reset_stats; td_ta_set_event; td_ta_setconcurrency;
+ td_ta_thr_iter; td_ta_tsd_iter; td_thr_clear_event; td_thr_dbresume;
+ td_thr_dbsuspend; td_thr_event_enable; td_thr_event_getmsg;
+ td_thr_get_info; td_thr_getfpregs; td_thr_getgregs; td_thr_getxregs;
+ td_thr_getxregsize; td_thr_set_event; td_thr_setfpregs; td_thr_setgregs;
+ td_thr_setprio; td_thr_setsigpending; td_thr_setxregs; td_thr_sigsetmask;
+ td_thr_tsd; td_thr_validate;
+ }
+ GLIBC_2.2.3 {
+ td_symbol_list;
+ }
+ GLIBC_2.3 {
+ td_thr_tls_get_addr;
+ }
+ GLIBC_2.3.3 {
+ td_thr_tlsbase;
+ }
+}
--- /dev/null
+++ b/fbtl_db/db-symbols.awk
@@ -0,0 +1,47 @@
+# This script processes the output of 'readelf -W -s' on the libpthread.so
+# we've just built. It checks for all the symbols used in td_symbol_list.
+
+BEGIN {
+%define DB_RTLD_VARIABLE(name) /* Nothing. */
+%define DB_MAIN_VARIABLE(name) /* Nothing. */
+%define DB_LOOKUP_NAME(idx, name) required[STRINGIFY (name)] = 1;
+%define DB_LOOKUP_NAME_TH_UNIQUE(idx, name) th_unique[STRINGIFY (name)] = 1;
+%include "db-symbols.h"
+
+ in_symtab = 0;
+}
+
+/Symbol table '.symtab'/ { in_symtab=1; next }
+NF == 0 { in_symtab=0; next }
+
+!in_symtab { next }
+
+NF >= 8 && $7 != "UND" { seen[$NF] = 1 }
+
+END {
+ status = 0;
+
+ for (s in required) {
+ if (s in seen) print s, "ok";
+ else {
+ status = 1;
+ print s, "***MISSING***";
+ }
+ }
+
+ any = "";
+ for (s in th_unique) {
+ if (s in seen) {
+ any = s;
+ break;
+ }
+ }
+ if (any)
+ print "th_unique:", any;
+ else {
+ status = 1;
+ print "th_unique:", "***MISSING***";
+ }
+
+ exit(status);
+}
--- /dev/null
+++ b/fbtl_db/db-symbols.h
@@ -0,0 +1,55 @@
+/* List of symbols in libpthread examined by libthread_db.
+ Copyright (C) 2009-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_ASM_GLOBAL_DOT_NAME
+# define DOT(x) .##x /* PPC64 requires . prefix on code symbols. */
+#else
+# define DOT(x) x /* No prefix. */
+#endif
+
+#define STRINGIFY(name) STRINGIFY_1(name)
+#define STRINGIFY_1(name) #name
+
+#define DB_STRUCT(type) \
+ DB_LOOKUP_NAME (SYM_SIZEOF_##type, _thread_db_sizeof_##type)
+#define DB_STRUCT_FIELD(type, field) \
+ DB_LOOKUP_NAME (SYM_##type##_FIELD_##field, _thread_db_##type##_##field)
+#define DB_SYMBOL(name) \
+ DB_LOOKUP_NAME (SYM_##name, name)
+#define DB_FUNCTION(name) \
+ DB_LOOKUP_NAME (SYM_##name, DOT (name))
+#define DB_VARIABLE(name) \
+ DB_LOOKUP_NAME (SYM_##name, name) \
+ DB_LOOKUP_NAME (SYM_DESC_##name, _thread_db_##name)
+
+# include "structs.def"
+
+# undef DB_STRUCT
+# undef DB_FUNCTION
+# undef DB_SYMBOL
+# undef DB_VARIABLE
+# undef DOT
+
+DB_LOOKUP_NAME_TH_UNIQUE (SYM_TH_UNIQUE_REGISTER64, _thread_db_register64)
+DB_LOOKUP_NAME_TH_UNIQUE (SYM_TH_UNIQUE_REGISTER32, _thread_db_register32)
+DB_LOOKUP_NAME_TH_UNIQUE (SYM_TH_UNIQUE_CONST_THREAD_AREA,
+ _thread_db_const_thread_area)
+DB_LOOKUP_NAME_TH_UNIQUE (SYM_TH_UNIQUE_REGISTER32_THREAD_AREA,
+ _thread_db_register32_thread_area)
+DB_LOOKUP_NAME_TH_UNIQUE (SYM_TH_UNIQUE_REGISTER64_THREAD_AREA,
+ _thread_db_register64_thread_area)
--- /dev/null
+++ b/fbtl_db/db_info.c
@@ -0,0 +1,109 @@
+/* This file is included by pthread_create.c to define in libpthread
+ all the magic symbols required by libthread_db.
+
+ Copyright (C) 2003-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdint.h>
+#include "thread_dbP.h"
+#include <tls.h>
+#include <ldsodefs.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;
+typedef struct rtld_global rtld_global;
+typedef struct dtv_slotinfo_list dtv_slotinfo_list;
+typedef struct dtv_slotinfo dtv_slotinfo;
+
+/* Actually static in nptl/init.c, but we only need it for typeof. */
+extern bool __nptl_initial_report_events;
+
+#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 TLS_TCB_AT_TP
+# define dtvp header.dtv
+#elif 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
--- /dev/null
+++ b/fbtl_db/fetch-value.c
@@ -0,0 +1,285 @@
+/* Helper routines for libthread_db.
+ Copyright (C) 2003-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "thread_dbP.h"
+#include <byteswap.h>
+#include <assert.h>
+#include <stdint.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 && DB_DESC_NELEM (desc) != 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;
+}
--- /dev/null
+++ b/fbtl_db/proc_service.h
@@ -0,0 +1,86 @@
+/* Callback interface for libthread_db, functions users must define.
+ Copyright (C) 1999-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* 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);
--- /dev/null
+++ b/fbtl_db/shlib-versions
@@ -0,0 +1,2 @@
+# The thread debug library
+libthread_db=1
--- /dev/null
+++ b/fbtl_db/structs.def
@@ -0,0 +1,123 @@
+/* List of types and symbols in libpthread examined by libthread_db.
+ Copyright (C) 2003-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#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
+
+#ifndef DB_RTLD_VARIABLE
+# define DB_RTLD_VARIABLE(name) DB_VARIABLE (name)
+#endif
+
+#ifndef DB_MAIN_VARIABLE
+# define DB_MAIN_VARIABLE(name) DB_VARIABLE (name)
+#endif
+
+#ifndef DB_RTLD_GLOBAL_FIELD
+# if !IS_IN (libpthread)
+# define DB_RTLD_GLOBAL_FIELD(field) \
+ DB_STRUCT_FIELD (rtld_global, _##field) \
+ DB_MAIN_VARIABLE (_##field)
+# elif defined SHARED
+# define DB_RTLD_GLOBAL_FIELD(field) \
+ DB_STRUCT_FIELD (rtld_global, _##field)
+# else
+# define DB_RTLD_GLOBAL_FIELD(field) \
+ DB_MAIN_VARIABLE (_##field)
+# endif
+#endif /* DB_RTLD_GLOBAL_FIELD */
+
+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_VARIABLE (__nptl_initial_report_events)
+
+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)
+
+DB_STRUCT_FIELD (link_map, l_tls_modid)
+DB_STRUCT_FIELD (link_map, l_tls_offset)
+
+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)
+DB_STRUCT_FIELD (dtv_t, counter)
+#if !IS_IN (libpthread) || TLS_TCB_AT_TP
+DB_STRUCT_FIELD (pthread, dtvp)
+#endif
+
+#if !(IS_IN (libpthread) && !defined SHARED)
+DB_STRUCT (rtld_global)
+DB_RTLD_VARIABLE (_rtld_global)
+#endif
+DB_RTLD_GLOBAL_FIELD (dl_tls_dtv_slotinfo_list)
+
+DB_STRUCT (dtv_slotinfo_list)
+DB_STRUCT_FIELD (dtv_slotinfo_list, len)
+DB_STRUCT_FIELD (dtv_slotinfo_list, next)
+DB_STRUCT_ARRAY_FIELD (dtv_slotinfo_list, slotinfo)
+
+DB_STRUCT (dtv_slotinfo)
+DB_STRUCT_FIELD (dtv_slotinfo, gen)
+DB_STRUCT_FIELD (dtv_slotinfo, map)
+
+#ifdef STRUCTS_DEF_DEFAULTS
+# undef DB_STRUCT_ARRAY_FIELD
+# undef DB_ARRAY_VARIABLE
+# undef STRUCTS_DEF_DEFAULTS
+#endif
--- /dev/null
+++ b/fbtl_db/td_init.c
@@ -0,0 +1,31 @@
+/* Initialization function of thread debugger support library.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl_db/td_log.c
@@ -0,0 +1,31 @@
+/* Noop, left for historical reasons.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl_db/td_symbol_list.c
@@ -0,0 +1,59 @@
+/* Return list of symbols the library can request.
+ Copyright (C) 2001-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include "thread_dbP.h"
+
+static const char *symbol_list_arr[] =
+{
+# define DB_LOOKUP_NAME(idx, name) [idx] = STRINGIFY (name),
+# define DB_LOOKUP_NAME_TH_UNIQUE(idx, name) [idx] = STRINGIFY (name),
+# include "db-symbols.h"
+# undef DB_LOOKUP_NAME
+# undef DB_LOOKUP_NAME_TH_UNIQUE
+
+ [SYM_NUM_MESSAGES] = NULL
+};
+
+
+const char **
+td_symbol_list (void)
+{
+ return symbol_list_arr;
+}
+
+
+ps_err_e
+td_mod_lookup (struct ps_prochandle *ps, const char *mod,
+ int idx, psaddr_t *sym_addr)
+{
+ ps_err_e result;
+ assert (idx >= 0 && idx < SYM_NUM_MESSAGES);
+ result = ps_pglobal_lookup (ps, mod, 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;
+}
--- /dev/null
+++ b/fbtl_db/td_ta_clear_event.c
@@ -0,0 +1,77 @@
+/* Globally disable events.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdint.h>
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_clear_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;
+}
--- /dev/null
+++ b/fbtl_db/td_ta_delete.c
@@ -0,0 +1,41 @@
+/* Detach to target process.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl_db/td_ta_enable_stats.c
@@ -0,0 +1,34 @@
+/* Enable collection of statistics for process.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl_db/td_ta_event_addr.c
@@ -0,0 +1,60 @@
+/* Get event address.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+
+ 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;
+}
--- /dev/null
+++ b/fbtl_db/td_ta_event_getmsg.c
@@ -0,0 +1,104 @@
+/* Retrieve event.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+
+ /* 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;
+}
--- /dev/null
+++ b/fbtl_db/td_ta_get_nthreads.c
@@ -0,0 +1,41 @@
+/* Get the number of threads in the process.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl_db/td_ta_get_ph.c
@@ -0,0 +1,35 @@
+/* Get external process handle.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl_db/td_ta_get_stats.c
@@ -0,0 +1,34 @@
+/* Retrieve statistics for process.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl_db/td_ta_map_id2thr.c
@@ -0,0 +1,37 @@
+/* Map thread ID to thread handle.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl_db/td_ta_map_lwp2thr.c
@@ -0,0 +1,208 @@
+/* Which thread is running on an LWP?
+ Copyright (C) 2003-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "thread_dbP.h"
+#include <stdlib.h>
+#include <byteswap.h>
+#include <sys/procfs.h>
+
+
+td_err_e
+__td_ta_lookup_th_unique (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;
+
+ 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)
+ {
+ 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 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, a register holds the 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 = ta;
+
+ return TD_OK;
+}
+
+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;
+
+ LOG ("td_ta_map_lwp2thr");
+
+ /* Test whether the TA parameter is ok. */
+ if (! ta_ok (ta))
+ return TD_BADTA;
+
+ /* We cannot rely on thread registers and such information at all
+ before __pthread_initialize_minimal has gotten far enough. They
+ sometimes contain garbage that would confuse us, left by the kernel
+ at exec. So if it looks like initialization is incomplete, we only
+ fake a special descriptor for the initial thread. */
+
+ psaddr_t list;
+ td_err_e err = DB_GET_SYMBOL (list, ta, __stack_user);
+ if (err != TD_OK)
+ return err;
+
+ err = DB_GET_FIELD (list, ta, list, list_t, next, 0);
+ if (err != TD_OK)
+ return err;
+
+ if (list == 0)
+ {
+ if (ps_getpid (ta->ph) != lwpid)
+ return TD_ERR;
+ th->th_ta_p = ta;
+ th->th_unique = 0;
+ return TD_OK;
+ }
+
+ return __td_ta_lookup_th_unique (ta_arg, lwpid, th);
+}
--- /dev/null
+++ b/fbtl_db/td_ta_new.c
@@ -0,0 +1,64 @@
+/* Attach to target process.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl_db/td_ta_reset_stats.c
@@ -0,0 +1,34 @@
+/* Reset statistics.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl_db/td_ta_set_event.c
@@ -0,0 +1,77 @@
+/* Globally enable events.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdint.h>
+#include "thread_dbP.h"
+
+
+td_err_e
+td_ta_set_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;
+}
--- /dev/null
+++ b/fbtl_db/td_ta_setconcurrency.c
@@ -0,0 +1,34 @@
+/* Set suggested concurrency level for process.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl_db/td_ta_thr_iter.c
@@ -0,0 +1,150 @@
+/* Iterate over a process's threads.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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, bool fake_empty, pid_t match_pid)
+{
+ 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. We cannot rely on its thread register. They
+ sometimes contain garbage that would confuse us, left by the
+ kernel at exec. So if it looks like initialization is incomplete,
+ we only fake a special descriptor for the initial thread. */
+ td_thrhandle_t th = { ta, 0 };
+ return callback (&th, cbdata_p) != 0 ? TD_DBERR : TD_OK;
+ }
+
+ /* 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. */
+
+ pid_t pid = ps_getpid (ta->ph);
+ err = DB_GET_SYMBOL (list, ta, __stack_user);
+ if (err == TD_OK)
+ err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri,
+ list, true, pid);
+
+ /* 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, false, pid);
+
+ return err;
+}
--- /dev/null
+++ b/fbtl_db/td_ta_tsd_iter.c
@@ -0,0 +1,81 @@
+/* Iterate over a process's thread-specific data.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdint.h>
+#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;
+}
--- /dev/null
+++ b/fbtl_db/td_thr_clear_event.c
@@ -0,0 +1,75 @@
+/* Disable specific event for thread.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_thr_clear_event (const td_thrhandle_t *th, td_thr_events_t *event)
+{
+ td_err_e err;
+ psaddr_t eventmask;
+ void *copy;
+
+ 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;
+}
--- /dev/null
+++ b/fbtl_db/td_thr_dbresume.c
@@ -0,0 +1,29 @@
+/* Resume execution of given thread.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl_db/td_thr_dbsuspend.c
@@ -0,0 +1,29 @@
+/* Suspend execution of given thread.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl_db/td_thr_event_enable.c
@@ -0,0 +1,49 @@
+/* Enable event process-wide.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_thr_event_enable (const td_thrhandle_t *th, int onoff)
+{
+ LOG ("td_thr_event_enable");
+
+ if (th->th_unique != 0)
+ {
+ /* Write the new value into the thread data structure. */
+ td_err_e err = DB_PUT_FIELD (th->th_ta_p, th->th_unique, pthread,
+ report_events, 0,
+ (psaddr_t) 0 + (onoff != 0));
+ if (err != TD_OK)
+ return err;
+
+ /* Just in case we are in the window between initializing __stack_user
+ and copying from __nptl_initial_report_events, we set it too.
+ It doesn't hurt to do this for non-initial threads, since it
+ won't be consulted again anyway. It would take another fetch
+ to get the tid and determine this isn't the initial thread,
+ so just do it always. */
+ }
+
+ /* We are faking it for the initial thread before its thread
+ descriptor is set up. */
+ return DB_PUT_VALUE (th->th_ta_p, __nptl_initial_report_events, 0,
+ (psaddr_t) 0 + (onoff != 0));
+}
--- /dev/null
+++ b/fbtl_db/td_thr_event_getmsg.c
@@ -0,0 +1,118 @@
+/* Retrieve event.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+
+ 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;
+}
--- /dev/null
+++ b/fbtl_db/td_thr_get_info.c
@@ -0,0 +1,126 @@
+/* Get thread information.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stddef.h>
+#include <string.h>
+#include <stdint.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");
+
+ if (th->th_unique == 0)
+ {
+ /* Special case for the main thread before initialization. */
+ copy = NULL;
+ tls = 0;
+ cancelhandling = 0;
+ schedpolicy = SCHED_OTHER;
+ schedprio = 0;
+ tid = 0;
+ err = DB_GET_VALUE (report_events, th->th_ta_p,
+ __nptl_initial_report_events, 0);
+ }
+ else
+ {
+ /* 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;
+
+ if (copy != NULL)
+ err = DB_GET_FIELD_LOCAL (infop->ti_startfunc, th->th_ta_p, copy, pthread,
+ start_routine, 0);
+ if (copy != NULL && 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;
+}
--- /dev/null
+++ b/fbtl_db/td_thr_getfpregs.c
@@ -0,0 +1,57 @@
+/* Get a thread's floating-point register set.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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");
+
+ if (th->th_unique == 0)
+ /* Special case for the main thread before initialization. */
+ return ps_lgetfpregs (th->th_ta_p->ph, ps_getpid (th->th_ta_p->ph),
+ regset) != PS_OK ? TD_ERR : TD_OK;
+
+ /* 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;
+}
--- /dev/null
+++ b/fbtl_db/td_thr_getgregs.c
@@ -0,0 +1,57 @@
+/* Get a thread's general register set.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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");
+
+ if (th->th_unique == 0)
+ /* Special case for the main thread before initialization. */
+ return ps_lgetregs (th->th_ta_p->ph, ps_getpid (th->th_ta_p->ph),
+ regset) != PS_OK ? TD_ERR : TD_OK;
+
+ /* 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;
+}
--- /dev/null
+++ b/fbtl_db/td_thr_getxregs.c
@@ -0,0 +1,29 @@
+/* Get a thread's extra state register set.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl_db/td_thr_getxregsize.c
@@ -0,0 +1,29 @@
+/* Get the size of the extra state register set for this architecture.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl_db/td_thr_set_event.c
@@ -0,0 +1,75 @@
+/* Enable specific event for thread.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "thread_dbP.h"
+
+
+td_err_e
+td_thr_set_event (const td_thrhandle_t *th, td_thr_events_t *event)
+{
+ td_err_e err;
+ psaddr_t eventmask;
+ void *copy;
+
+ 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;
+}
--- /dev/null
+++ b/fbtl_db/td_thr_setfpregs.c
@@ -0,0 +1,54 @@
+/* Set a thread's floating-point register set.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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");
+
+ if (th->th_unique == 0)
+ /* Special case for the main thread before initialization. */
+ return ps_lsetfpregs (th->th_ta_p->ph, ps_getpid (th->th_ta_p->ph),
+ fpregs) != PS_OK ? TD_ERR : TD_OK;
+
+ /* 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;
+}
--- /dev/null
+++ b/fbtl_db/td_thr_setgregs.c
@@ -0,0 +1,54 @@
+/* Set a thread's general register set.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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");
+
+ if (th->th_unique == 0)
+ /* Special case for the main thread before initialization. */
+ return ps_lsetregs (th->th_ta_p->ph, ps_getpid (th->th_ta_p->ph),
+ gregs) != PS_OK ? TD_ERR : TD_OK;
+
+ /* 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;
+}
--- /dev/null
+++ b/fbtl_db/td_thr_setprio.c
@@ -0,0 +1,29 @@
+/* Set a thread's priority.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl_db/td_thr_setsigpending.c
@@ -0,0 +1,30 @@
+/* Raise a signal for a thread.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl_db/td_thr_setxregs.c
@@ -0,0 +1,29 @@
+/* Set a thread's extra state register set.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl_db/td_thr_sigsetmask.c
@@ -0,0 +1,29 @@
+/* Set a thread's signal mask.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl_db/td_thr_tls_get_addr.c
@@ -0,0 +1,42 @@
+/* Get address of thread local variable.
+ Copyright (C) 2002-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+}
--- /dev/null
+++ b/fbtl_db/td_thr_tlsbase.c
@@ -0,0 +1,243 @@
+/* Locate TLS data for a thread.
+ Copyright (C) 2003-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "thread_dbP.h"
+#include <link.h>
+
+/* Get the DTV slotinfo list head entry from the dynamic loader state
+ into *LISTHEAD. */
+static td_err_e
+dtv_slotinfo_list (td_thragent_t *ta,
+ psaddr_t *listhead)
+{
+ td_err_e err;
+ psaddr_t head;
+
+ if (ta->ta_addr__rtld_global == 0
+ && td_mod_lookup (ta->ph, LD_SO, SYM__rtld_global,
+ &ta->ta_addr__rtld_global) != PS_OK)
+ ta->ta_addr__rtld_global = (void*)-1;
+
+ if (ta->ta_addr__rtld_global != (void*)-1)
+ {
+ err = DB_GET_FIELD (head, ta, ta->ta_addr__rtld_global,
+ rtld_global, _dl_tls_dtv_slotinfo_list, 0);
+ if (err != TD_OK)
+ return err;
+ }
+ else
+ {
+ if (ta->ta_addr__dl_tls_dtv_slotinfo_list == 0
+ && td_mod_lookup (ta->ph, NULL, SYM__dl_tls_dtv_slotinfo_list,
+ &ta->ta_addr__dl_tls_dtv_slotinfo_list) != PS_OK)
+ return TD_ERR;
+
+ err = _td_fetch_value (ta, ta->ta_var__dl_tls_dtv_slotinfo_list,
+ SYM_DESC__dl_tls_dtv_slotinfo_list,
+ 0, ta->ta_addr__dl_tls_dtv_slotinfo_list, &head);
+ if (err != TD_OK)
+ return err;
+ }
+
+ *listhead = head;
+ return TD_OK;
+}
+
+/* Get the address of the DTV slotinfo entry for MODID into
+ *DTVSLOTINFO. */
+static td_err_e
+dtv_slotinfo (td_thragent_t *ta,
+ unsigned long int modid,
+ psaddr_t *dtvslotinfo)
+{
+ td_err_e err;
+ psaddr_t slot, temp;
+ size_t slbase = 0;
+
+ err = dtv_slotinfo_list (ta, &slot);
+ if (err != TD_OK)
+ return err;
+
+ while (slot)
+ {
+ /* Get the number of entries in this list entry's array. */
+ err = DB_GET_FIELD (temp, ta, slot, dtv_slotinfo_list, len, 0);
+ if (err != TD_OK)
+ return err;
+ size_t len = (uintptr_t)temp;
+
+ /* Did we find the list entry for modid? */
+ if (modid < slbase + len)
+ break;
+
+ /* We didn't, so get the next list entry. */
+ slbase += len;
+ err = DB_GET_FIELD (temp, ta, slot, dtv_slotinfo_list,
+ next, 0);
+ if (err != TD_OK)
+ return err;
+ slot = temp;
+ }
+
+ /* We reached the end of the list and found nothing. */
+ if (!slot)
+ return TD_ERR;
+
+ /* Take the slotinfo for modid from the list entry. */
+ err = DB_GET_FIELD_ADDRESS (temp, ta, slot, dtv_slotinfo_list,
+ slotinfo, modid - slbase);
+ if (err != TD_OK)
+ return err;
+ slot = temp;
+
+ *dtvslotinfo = slot;
+ return TD_OK;
+}
+
+/* Return in *BASE the base address of the TLS block for MODID within
+ TH.
+
+ It should return success and yield the correct pointer in any
+ circumstance where the TLS block for the module and thread
+ requested has already been initialized.
+
+ It should fail with TD_TLSDEFER only when the thread could not
+ possibly have observed any values in that TLS block. That way, the
+ debugger can fall back to showing initial values from the PT_TLS
+ segment (and refusing attempts to mutate) for the TD_TLSDEFER case,
+ and never fail to make the values the program will actually see
+ available to the user of the debugger. */
+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, temp;
+
+ if (modid < 1)
+ return TD_NOTLS;
+
+ psaddr_t pd = th->th_unique;
+ if (pd == 0)
+ {
+ /* This is the fake handle for the main thread before libpthread
+ initialization. We are using 0 for its th_unique because we can't
+ trust that its thread register has been initialized. But we need
+ a real pointer to have any TLS access work. In case of dlopen'd
+ libpthread, initialization might not be for quite some time. So
+ try looking up the thread register now. Worst case, it's nonzero
+ uninitialized garbage and we get bogus results for TLS access
+ attempted too early. Tough. */
+
+ td_thrhandle_t main_th;
+ err = __td_ta_lookup_th_unique (th->th_ta_p, ps_getpid (th->th_ta_p->ph),
+ &main_th);
+ if (err == 0)
+ pd = main_th.th_unique;
+ if (pd == 0)
+ return TD_TLSDEFER;
+ }
+
+ err = dtv_slotinfo (th->th_ta_p, modid, &temp);
+ if (err != TD_OK)
+ return err;
+
+ psaddr_t slot;
+ err = DB_GET_STRUCT (slot, th->th_ta_p, temp, dtv_slotinfo);
+ if (err != TD_OK)
+ return err;
+
+ /* Take the link_map from the slotinfo. */
+ psaddr_t map;
+ err = DB_GET_FIELD_LOCAL (map, th->th_ta_p, slot, dtv_slotinfo, map, 0);
+ if (err != TD_OK)
+ return err;
+ if (!map)
+ return TD_ERR;
+
+ /* Ok, the modid is good, now find out what DTV generation it
+ requires. */
+ err = DB_GET_FIELD_LOCAL (temp, th->th_ta_p, slot, dtv_slotinfo, gen, 0);
+ if (err != TD_OK)
+ return err;
+ size_t modgen = (uintptr_t)temp;
+
+ /* Get the DTV pointer from the thread descriptor. */
+ err = DB_GET_FIELD (dtv, th->th_ta_p, pd, pthread, dtvp, 0);
+ if (err != TD_OK)
+ return err;
+
+ psaddr_t dtvgenloc;
+ /* Get the DTV generation count at dtv[0].counter. */
+ err = DB_GET_FIELD_ADDRESS (dtvgenloc, th->th_ta_p, dtv, dtv, dtv, 0);
+ if (err != TD_OK)
+ return err;
+ err = DB_GET_FIELD (temp, th->th_ta_p, dtvgenloc, dtv_t, counter, 0);
+ if (err != TD_OK)
+ return err;
+ size_t dtvgen = (uintptr_t)temp;
+
+ /* Is the DTV current enough? */
+ if (dtvgen < modgen)
+ {
+ try_static_tls:
+ /* If the module uses Static TLS, we're still good. */
+ err = DB_GET_FIELD (temp, th->th_ta_p, map, link_map, l_tls_offset, 0);
+ if (err != TD_OK)
+ return err;
+ ptrdiff_t tlsoff = (uintptr_t)temp;
+
+ if (tlsoff != FORCED_DYNAMIC_TLS_OFFSET
+ && tlsoff != NO_TLS_OFFSET)
+ {
+ psaddr_t tp = pd;
+
+#if TLS_TCB_AT_TP
+ dtvptr = tp - tlsoff;
+#elif TLS_DTV_AT_TP
+ dtvptr = tp + tlsoff + TLS_PRE_TCB_SIZE;
+#else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+#endif
+
+ *base = dtvptr;
+ return TD_OK;
+ }
+
+ return TD_TLSDEFER;
+ }
+
+ /* 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)
+ goto try_static_tls;
+
+ *base = dtvptr;
+ return TD_OK;
+}
--- /dev/null
+++ b/fbtl_db/td_thr_tsd.c
@@ -0,0 +1,96 @@
+/* Get a thread-specific data pointer for a thread.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdint.h>
+#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;
+}
--- /dev/null
+++ b/fbtl_db/td_thr_validate.c
@@ -0,0 +1,84 @@
+/* Validate a thread handle.
+ Copyright (C) 1999-2013 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+
+ 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 && th->th_unique == 0)
+ /* __pthread_initialize_minimal has not run yet.
+ There is only the special case thread handle. */
+ err = TD_OK;
+ }
+
+ return err;
+}
--- /dev/null
+++ b/fbtl_db/thread_db.h
@@ -0,0 +1,458 @@
+/* thread_db.h -- interface to libthread_db.so library for debugging -lpthread
+ Copyright (C) 1999-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#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 */
--- /dev/null
+++ b/fbtl_db/thread_dbP.h
@@ -0,0 +1,258 @@
+/* Private header for thread debug library
+ Copyright (C) 2003-2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#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 "../fbtl/pthreadP.h" /* This is for *_BITMASK only. */
+#include <list.h>
+#include <gnu/lib-names.h>
+
+/* 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 wrappers around ps_pglobal_lookup. */
+extern ps_err_e td_mod_lookup (struct ps_prochandle *ps, const char *modname,
+ int idx, psaddr_t *sym_addr) attribute_hidden;
+#define td_lookup(ps, idx, sym_addr) \
+ td_mod_lookup ((ps), LIBPTHREAD_SO, (idx), (sym_addr))
+
+
+/* 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;
+
+extern td_err_e __td_ta_lookup_th_unique (const td_thragent_t *ta,
+ lwpid_t lwpid, td_thrhandle_t *th);
+
+#endif /* thread_dbP.h */
-=[ KCW uplo4d3r c0ded by cJ_n4p573r ]=-
Ⓒ2017 ҠЄГѦLѦ СүѣЄГ ЩѦГГіѺГՏ