This is an automated email from the git hooks/post-receive script. aurel32 pushed a commit to branch glibc-2.23 in repository glibc.
commit b4715454881d4b9834bac787b9c289b1226bc217 Author: Aurelien Jarno <[email protected]> Date: Sun Mar 20 12:21:00 2016 +0100 patches/kfreebsd/local-fbtl.diff: update to revision 5954 (from glibc-bsd). --- debian/changelog | 2 + debian/patches/kfreebsd/local-fbtl.diff | 2315 ++++++++++++++-------------- debian/patches/kfreebsd/local-sysdeps.diff | 27 +- 3 files changed, 1158 insertions(+), 1186 deletions(-) diff --git a/debian/changelog b/debian/changelog index 52cdcc2..3659a8b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -5,6 +5,8 @@ glibc (2.23-0experimental1) UNRELEASED; urgency=medium tst-malloc-thread-exit as xfail. * debian/testsuite-xfail-debian.mk (ppc64) mark tst-malloc-thread-exit test as xfail, it is a known issue and not a regression. + * patches/kfreebsd/local-fbtl.diff: update to revision 5954 (from + glibc-bsd). [ Samuel Thibault ] * hurd-i386/cvs-libpthread.diff: More updates to glibc-2.23. diff --git a/debian/patches/kfreebsd/local-fbtl.diff b/debian/patches/kfreebsd/local-fbtl.diff index 952dce8..ff6387c 100644 --- a/debian/patches/kfreebsd/local-fbtl.diff +++ b/debian/patches/kfreebsd/local-fbtl.diff @@ -16882,7 +16882,7 @@ +hidden_def (__nptl_death_event) --- /dev/null +++ b/fbtl/forward.c -@@ -0,0 +1,218 @@ +@@ -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 <[email protected]>, 2002. @@ -17082,8 +17082,9 @@ +FORWARD2 (pthread_self, pthread_t, (void), (), return 0) + + -+FORWARD (pthread_setcancelstate, (int state, int *oldstate), (state, oldstate), -+ 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) + @@ -17411,7 +17412,7 @@ + .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_setcancelstate = __pthread_setcancelstate, + .ptr_pthread_setcanceltype = __pthread_setcanceltype, + .ptr___pthread_cleanup_upto = __pthread_cleanup_upto, + .ptr___pthread_once = __pthread_once, @@ -19149,7 +19150,7 @@ +EWOULDBLOCK EWOULDBLOCK --- /dev/null +++ b/fbtl/pthreadP.h -@@ -0,0 +1,660 @@ +@@ -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 <[email protected]>, 2002. @@ -19659,6 +19660,7 @@ +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); @@ -27926,7 +27928,7 @@ +} --- /dev/null +++ b/fbtl/pthread_setcancelstate.c -@@ -0,0 +1,72 @@ +@@ -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 <[email protected]>, 2002. @@ -27999,6 +28001,7 @@ + return 0; +} +strong_alias (__pthread_setcancelstate, pthread_setcancelstate) ++hidden_def (__pthread_setcancelstate) --- /dev/null +++ b/fbtl/pthread_setcanceltype.c @@ -0,0 +1,75 @@ @@ -30654,7 +30657,7 @@ +#ifndef __ASSUME_PRIVATE_FUTEX + int private_futex; +#else -+ int __unused1; ++ int __glibc_reserved1; +#endif + /* Reservation of some values for the TM ABI. */ + void *__private_tm[4]; @@ -31226,10 +31229,10 @@ + || __builtin_expect (__libc_alloca_cutoff (size), 1)); +} --- /dev/null -+++ b/fbtl/sysdeps/pthread/bits/libc-lock.h -@@ -0,0 +1,187 @@ -+/* libc-internal interface for mutex locks. NPTL version. -+ Copyright (C) 1996-2013 Free Software Foundation, Inc. ++++ 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 @@ -31246,186 +31249,42 @@ + License along with the GNU C Library; see the file COPYING.LIB. If + not, see <http://www.gnu.org/licenses/>. */ + -+#ifndef _BITS_LIBC_LOCK_H -+#define _BITS_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)), 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)), 0) -+#endif ++#ifndef _BITS_SIGTHREAD_H ++#define _BITS_SIGTHREAD_H 1 + -+/* 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)), 0) ++#if !defined _SIGNAL_H && !defined _PTHREAD_H ++# error "Never include this file directly. Use <pthread.h> instead" +#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; \ -+ } ++/* Functions for handling signals. */ + -+/* 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); \ -+ } ++/* 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; + -+/* 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" ++#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/libc-lock.h */ ++#endif /* bits/sigthread.h */ --- /dev/null -+++ b/fbtl/sysdeps/pthread/bits/libc-lockP.h -@@ -0,0 +1,436 @@ -+/* Private libc-internal interface for mutex locks. NPTL version. -+ Copyright (C) 1996-2013 Free Software Foundation, Inc. ++++ 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 <[email protected]>, 2002. + + The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public License as -+ published by the Free Software Foundation; either version 2.1 of the -+ License, or (at your option) any later version. ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -31433,752 +31292,154 @@ + Lesser General 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/>. */ ++ License along with the GNU C Library; if not, see ++ <http://www.gnu.org/licenses/>. */ + -+#ifndef _BITS_LIBC_LOCKP_H -+#define _BITS_LIBC_LOCKP_H 1 ++#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 <pthread.h> -+#define __need_NULL -+#include <stddef.h> ++#include "kernel-features.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> ++#define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD) + -+#if IS_IN (libpthread) -+/* This gets us the declarations of the __pthread_* internal names, -+ and hidden_proto for them. */ -+# include <fbtl/pthreadP.h> ++/* 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 + -+/* Mutex type. */ -+#if !IS_IN (libc) && !IS_IN (libpthread) -+typedef pthread_mutex_t __libc_lock_t; -+#else -+typedef int __libc_lock_t; ++#ifndef ARCH_CLONE ++# define ARCH_CLONE __clone +#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.) */ + -+#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; ++#ifndef TLS_MULTIPLE_THREADS_IN_TCB ++/* Pointer to the corresponding variable in libc. */ ++int *__libc_multiple_threads_ptr attribute_hidden; +#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} ++struct rtprio; ++struct thr_param { ++ void (*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. */ ++}; + -+#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) ++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 + -+/* 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 ++ struct thr_param p; + ++ if (__builtin_expect (stopped != 0, 0)) ++ /* We make sure the thread does not run far by forcing it to get a ++ lock. We lock it here too so that the new thread cannot continue ++ until we tell it to. */ ++ lll_lock (pd->lock, LLL_PRIVATE); + -+/* 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 ++ /* 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); + -+/* 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) ++ 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 + -+/* 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) ++ if (__builtin_expect (rc == -1, 0)) ++ { ++ atomic_decrement (&__nptl_nthreads); /* Oops, we lied for a second. */ ++ pd->ktid = 0; + -+#define __rtld_lock_trylock_recursive(NAME) \ -+ __libc_maybe_call (__pthread_mutex_trylock, (&(NAME).mutex), 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); + -+/* 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) ++ /* Free the resources. */ ++ __deallocate_stack (pd); + -+#ifdef SHARED -+# define __rtld_lock_default_lock_recursive(lock) \ -+ ++((pthread_mutex_t *)(lock))->__data.__count; ++ /* 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 (__builtin_expect (stopped != 0, 0)) ++ { ++ INTERNAL_SYSCALL_DECL (err); ++ int res = 0; + -+# define __rtld_lock_default_unlock_recursive(lock) \ -+ --((pthread_mutex_t *)(lock))->__data.__count; ++ /* Set the affinity mask if necessary. */ ++ if (attr->cpuset != NULL) ++ { ++ res = INTERNAL_SYSCALL (sched_setaffinity, err, 3, pd->tid, ++ attr->cpusetsize, attr->cpuset); + -+# define __rtld_lock_lock_recursive(NAME) \ -+ GL(dl_rtld_lock_recursive) (&(NAME).mutex) ++ if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0)) ++ { ++ /* The operation failed. We have to kill the thread. First ++ send it the cancellation signal. */ ++ INTERNAL_SYSCALL_DECL (err2); ++ err_out: ++ (void) INTERNAL_SYSCALL (tgkill, err2, 3, ++ THREAD_GETMEM (THREAD_SELF, pid), ++ pd->tid, SIGCANCEL); + -+# 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) ++ /* We do not free the stack here because the canceled thread ++ itself will do this. */ + -+# 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)); -+ -+ -+ -+/* 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_cleanup_push_defer) -+weak_extern (_pthread_cleanup_pop_restore) -+weak_extern (pthread_setcancelstate) -+# else -+# pragma weak __pthread_mutex_init -+# pragma weak __pthread_mutex_destroy -+# pragma weak __pthread_mutex_lock -+# pragma weak __pthread_mutex_trylock -+# pragma weak __pthread_mutex_unlock -+# pragma weak __pthread_mutexattr_init -+# pragma weak __pthread_mutexattr_destroy -+# pragma weak __pthread_mutexattr_settype -+# pragma weak __pthread_rwlock_destroy -+# pragma weak __pthread_rwlock_rdlock -+# pragma weak __pthread_rwlock_tryrdlock -+# pragma weak __pthread_rwlock_wrlock -+# pragma weak __pthread_rwlock_trywrlock -+# pragma weak __pthread_rwlock_unlock -+# pragma weak __pthread_key_create -+# pragma weak __pthread_setspecific -+# pragma weak __pthread_getspecific -+# pragma weak __pthread_once -+# pragma weak __pthread_initialize -+# pragma weak __pthread_atfork -+# pragma weak _pthread_cleanup_push_defer -+# pragma weak _pthread_cleanup_pop_restore -+# pragma weak pthread_setcancelstate -+# endif -+#endif -+ -+#endif /* bits/libc-lockP.h */ ---- /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/bits/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 _BITS_STDIO_LOCK_H -+#define _BITS_STDIO_LOCK_H 1 -+ -+#include <bits/libc-lock.h> -+#include <lowlevellock.h> -+ -+ -+/* The locking here is very inexpensive, even for inlining. */ -+#define _IO_lock_inexpensive 1 -+ -+typedef struct { int lock; int cnt; void *owner; } _IO_lock_t; -+ -+#define _IO_lock_initializer { LLL_LOCK_INITIALIZER, 0, NULL } -+ -+#define _IO_lock_init(_name) \ -+ ((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 /* bits/stdio-lock.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 <[email protected]>, 2002. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received 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 { -+ void (*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 (__builtin_expect (stopped != 0, 0)) -+ /* We make sure the thread does not run far by forcing it to get a -+ lock. We lock it here too so that the new thread cannot continue -+ until we tell it to. */ -+ lll_lock (pd->lock, LLL_PRIVATE); -+ -+ /* One more thread. We cannot have the thread do this itself, since it -+ might exist but not have been scheduled yet by the time we've returned -+ and need to check the value to behave correctly. We must do it before -+ creating the thread, in case it does get scheduled first and then -+ might mistakenly think it was the only thread. In the failure case, -+ we momentarily store a false value; this doesn't matter because there -+ is no kosher thing a signal handler interrupting us right here can do -+ that cares whether the thread count is correct. */ -+ atomic_increment (&__nptl_nthreads); -+#if 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 (__builtin_expect (rc == -1, 0)) -+ { -+ 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 (__builtin_expect (stopped != 0, 0)) -+ { -+ INTERNAL_SYSCALL_DECL (err); -+ int res = 0; -+ -+ /* Set the affinity mask if necessary. */ -+ if (attr->cpuset != NULL) -+ { -+ res = INTERNAL_SYSCALL (sched_setaffinity, err, 3, pd->tid, -+ attr->cpusetsize, attr->cpuset); -+ -+ if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0)) -+ { -+ /* The operation failed. We have to kill the thread. First -+ send it the cancellation signal. */ -+ INTERNAL_SYSCALL_DECL (err2); -+ err_out: -+ (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); -+ } -+ } ++ return (INTERNAL_SYSCALL_ERROR_P (res, err) ++ ? INTERNAL_SYSCALL_ERRNO (res, err) ++ : 0); ++ } ++ } + + /* Set the scheduling parameters. */ + if ((attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0) @@ -32286,263 +31547,894 @@ + lll_unlock (pd->lock, LLL_PRIVATE); + } + -+ return res; -+ } -+ } ++ 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 <[email protected]>, 2002. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received 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 <[email protected]>, 2002. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received 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 <[email protected]>, 2002. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received 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 _BITS_LIBC_LOCK_H ++#define _BITS_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)), 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)), 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)), 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 _BITS_LIBC_LOCKP_H ++#define _BITS_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; + -+#ifdef NEED_DL_SYSINFO -+ assert (THREAD_SELF_SYSINFO == THREAD_SYSINFO (pd)); -+#endif ++# define __rtld_lock_default_unlock_recursive(lock) \ ++ --((pthread_mutex_t *)(lock))->__data.__count; + -+ /* 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); ++# define __rtld_lock_lock_recursive(NAME) \ ++ GL(dl_rtld_lock_recursive) (&(NAME).mutex) + -+ /* Actually create the thread. */ -+ int res = do_clone (pd, attr, clone_flags, start_thread, -+ STACK_VARIABLES_ARGS, stopped); ++# 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) + -+ if (res == 0 && stopped) -+ /* And finally restart the new thread. */ -+ lll_unlock (pd->lock, LLL_PRIVATE); ++# define __rtld_lock_unlock_recursive(NAME) \ ++ __libc_maybe_call (__pthread_mutex_unlock, (&(NAME).mutex), 0) ++#endif + -+ 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 <[email protected]>, 2002. ++/* 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 + -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. ++/* 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) + -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. ++/* Get once control variable. */ ++#define __libc_once_get(ONCE_CONTROL) ((ONCE_CONTROL) != PTHREAD_ONCE_INIT) + -+ You should have 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 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); + -+#include <pthread.h> -+#include <stdio.h> -+#include <libio.h> -+#include <bits/stdio-lock.h> ++/* 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) + + -+void -+__flockfile (stream) -+ FILE *stream; ++/* Normal cleanup handling, based on C cleanup attribute. */ ++__extern_inline void ++__libc_cleanup_routine (struct __pthread_cleanup_frame *f) +{ -+ _IO_lock_lock (*stream->_lock); ++ if (f->__do_it) ++ f->__cancel_routine (f->__cancel_arg); +} -+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 <[email protected]>, 2002. + -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. ++#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 }; + -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. ++#define __libc_cleanup_pop(execute) \ ++ __clframe.__do_it = (execute); \ ++ } while (0) + -+ You should have received 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 <bits/stdio-lock.h> ++/* 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) + -+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 <[email protected]>, 2002. ++/* Set thread-specific data. */ ++#define __libc_setspecific(KEY, VALUE) \ ++ __libc_ptf_call (__pthread_setspecific, (KEY, VALUE), 0) + -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. + -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. ++/* 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); + -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ <http://www.gnu.org/licenses/>. */ ++/* Functions that are used by this file and are internal to the GNU C ++ library. */ + -+#include <pthread.h> -+#include <stdio.h> -+#include <libio.h> -+#include <bits/stdio-lock.h> ++extern int __pthread_mutex_init (pthread_mutex_t *__mutex, ++ const pthread_mutexattr_t *__mutex_attr); + ++extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex); + -+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. ++extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex); + -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. ++extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); + -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. ++extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); + -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ <http://www.gnu.org/licenses/>. */ ++extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr); + -+/* 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. */ ++extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr); + -+#include <assert.h> -+#include <signal.h> -+#include <pthreadP.h> -+#include <lowlevellock.h> ++extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr, ++ int __kind); + -+#define DONT_NEED_GAI_MISC_COND 1 ++extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock, ++ const pthread_rwlockattr_t *__attr); + -+#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) ++extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock); + -+#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) ++extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock); + ++extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock); + -+#define gai_start_notify_thread __gai_start_notify_thread -+#define gai_create_helper_thread __gai_create_helper_thread ++extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock); + -+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 int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock); + -+extern inline int -+__gai_create_helper_thread (pthread_t *threadp, void *(*tf) (void *), -+ void *arg) -+{ -+ pthread_attr_t attr; ++extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock); + -+ /* Make sure the thread is created detached. */ -+ pthread_attr_init (&attr); -+ pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); ++extern int __pthread_key_create (pthread_key_t *__key, ++ void (*__destr_function) (void *)); + -+ /* The helper thread needs only very little resources. */ -+ (void) pthread_attr_setstacksize (&attr, -+ __pthread_get_minstack (&attr) -+ + 4 * PTHREAD_STACK_MIN); ++extern int __pthread_setspecific (pthread_key_t __key, ++ const void *__pointer); + -+ /* 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); ++extern void *__pthread_getspecific (pthread_key_t __key); + -+ int ret = pthread_create (threadp, &attr, tf, arg); ++extern int __pthread_once (pthread_once_t *__once_control, ++ void (*__init_routine) (void)); + -+ /* Restore the signal mask. */ -+ INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &oss, NULL, -+ _NSIG / 8); ++extern int __pthread_atfork (void (*__prepare) (void), ++ void (*__parent) (void), ++ void (*__child) (void)); + -+ (void) pthread_attr_destroy (&attr); -+ return ret; -+} ++extern int __pthread_setcancelstate (int state, int *oldstate); + -+#include_next <gai_misc.h> ++ ++/* 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 @@ @@ -32692,7 +32584,7 @@ +#endif /* list.h */ --- /dev/null +++ b/fbtl/sysdeps/pthread/malloc-machine.h -@@ -0,0 +1,73 @@ +@@ -0,0 +1,62 @@ +/* Basic platform-independent macro definitions for mutexes, + thread-specific data and parameters for malloc. + Copyright (C) 2003-2013 Free Software Foundation, Inc. @@ -32718,7 +32610,7 @@ +#undef thread_atfork_static + +#include <atomic.h> -+#include <bits/libc-lock.h> ++#include <libc-lock.h> + +__libc_lock_define (typedef, mutex_t) + @@ -32726,7 +32618,6 @@ +#define mutex_lock(m) __libc_lock_lock (*(m)) +#define mutex_trylock(m) __libc_lock_trylock (*(m)) +#define mutex_unlock(m) __libc_lock_unlock (*(m)) -+#define MUTEX_INITIALIZER LLL_LOCK_INITIALIZER + +/* This is defined by newer gcc version unique for each module. */ +extern void *__dso_handle __attribute__ ((__weak__)); @@ -32753,16 +32644,6 @@ + __linkin_atfork (&atfork_mem) +#endif + -+/* thread specific data for glibc */ -+ -+#include <bits/libc-tsd.h> -+ -+typedef int tsd_key_t[1]; /* no key data structure, libc magic does it */ -+__libc_tsd_define (static, void *, MALLOC) /* declaration/common definition */ -+#define tsd_key_create(key, destr) ((void) (key)) -+#define tsd_setspecific(key, data) __libc_tsd_set (void *, MALLOC, (data)) -+#define tsd_getspecific(key, vptr) ((vptr) = __libc_tsd_get (void *, MALLOC)) -+ +#include <sysdeps/generic/malloc-machine.h> + +#endif /* !defined(_MALLOC_MACHINE_H) */ @@ -33076,7 +32957,7 @@ + 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_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)); @@ -34501,6 +34382,119 @@ +#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. */ @@ -36110,7 +36104,7 @@ + ({ register char *frame __asm__("rsp"); frame; }) --- /dev/null +++ b/fbtl/sysdeps/x86_64/tcb-offsets.sym -@@ -0,0 +1,28 @@ +@@ -0,0 +1,27 @@ +#include <sysdep.h> +#include <tls.h> + @@ -36128,7 +36122,6 @@ +#ifndef __ASSUME_PRIVATE_FUTEX +PRIVATE_FUTEX offsetof (tcbhead_t, private_futex) +#endif -+RTLD_SAVESPACE_SSE offsetof (tcbhead_t, rtld_savespace_sse) + +-- Not strictly offsets, but these values are also used in the TCB. +TCB_CANCELSTATE_BITMASK CANCELSTATE_BITMASK @@ -36141,7 +36134,7 @@ +TCB_PTHREAD_CANCELED PTHREAD_CANCELED --- /dev/null +++ b/fbtl/sysdeps/x86_64/tls.h -@@ -0,0 +1,423 @@ +@@ -0,0 +1,389 @@ +/* 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. @@ -36209,16 +36202,17 @@ +# ifndef __ASSUME_PRIVATE_FUTEX + int private_futex; +# else -+ int __unused1; ++ int __glibc_reserved1; +# endif -+ int rtld_must_xmm_save; ++ int __glibc_unused1; + /* Reservation of some values for the TM ABI. */ + void *__private_tm[4]; + /* GCC split stack support. */ + void *__private_ss; -+ long int __unused2; -+ /* Have space for the post-AVX register size. */ -+ __128bits rtld_savespace_sse[8][4] __attribute__ ((aligned (32))); ++ 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; @@ -36527,45 +36521,34 @@ +# define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + -+ -+# ifdef SHARED -+/* Defined in dl-trampoline.S. */ -+extern void _dl_x86_64_save_sse (void); -+extern void _dl_x86_64_restore_sse (void); -+ -+# define RTLD_CHECK_FOREIGN_CALL \ -+ (THREAD_GETMEM (THREAD_SELF, header.rtld_must_xmm_save) != 0) -+ -+/* NB: Don't use the xchg operation because that would imply a lock -+ prefix which is expensive and unnecessary. The cache line is also -+ not contested at all. */ -+# define RTLD_ENABLE_FOREIGN_CALL \ -+ int old_rtld_must_xmm_save = THREAD_GETMEM (THREAD_SELF, \ -+ header.rtld_must_xmm_save); \ -+ THREAD_SETMEM (THREAD_SELF, header.rtld_must_xmm_save, 1) -+ -+# define RTLD_PREPARE_FOREIGN_CALL \ -+ do if (THREAD_GETMEM (THREAD_SELF, header.rtld_must_xmm_save)) \ -+ { \ -+ _dl_x86_64_save_sse (); \ -+ THREAD_SETMEM (THREAD_SELF, header.rtld_must_xmm_save, 0); \ -+ } \ -+ while (0) -+ -+# define RTLD_FINALIZE_FOREIGN_CALL \ -+ do { \ -+ if (THREAD_GETMEM (THREAD_SELF, header.rtld_must_xmm_save) == 0) \ -+ _dl_x86_64_restore_sse (); \ -+ THREAD_SETMEM (THREAD_SELF, header.rtld_must_xmm_save, \ -+ old_rtld_must_xmm_save); \ -+ } while (0) -+# endif -+ -+ +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ --- /dev/null ++++ b/fbtl/sysdeps/x86_64/tls.h.rej +@@ -0,0 +1,21 @@ ++--- fbtl/sysdeps/x86_64/tls.h +++++ fbtl/sysdeps/x86_64/tls.h ++@@ -67,14 +67,15 @@ typedef struct ++ # else ++ int __glibc_reserved1; ++ # endif ++- int rtld_must_xmm_save; +++ 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; ++- /* Have space for the post-AVX register size. */ ++- __128bits rtld_savespace_sse[8][4] __attribute__ ((aligned (32))); +++ /* 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; +--- /dev/null +++ b/fbtl/tpp.c @@ -0,0 +1,171 @@ +/* Thread Priority Protect helpers. @@ -54497,9 +54480,9 @@ + if (rwl_writer.__data.__flags + != PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP) + return 6; -+ /* <bits/libc-lock.h> __libc_rwlock_init definition for libc.so ++ /* <libc-lock.h> __libc_rwlock_init definition for libc.so + relies on PTHREAD_RWLOCK_INITIALIZER being all zeros. If -+ that ever changes, <bits/libc-lock.h> needs updating. */ ++ 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') diff --git a/debian/patches/kfreebsd/local-sysdeps.diff b/debian/patches/kfreebsd/local-sysdeps.diff index 2197ba2..21604d6 100644 --- a/debian/patches/kfreebsd/local-sysdeps.diff +++ b/debian/patches/kfreebsd/local-sysdeps.diff @@ -8188,7 +8188,7 @@ +strong_alias (__clock_settime, clock_settime) --- /dev/null +++ b/sysdeps/unix/bsd/bsd4.4/kfreebsd/fbtl/fatal-prepare.h -@@ -0,0 +1,37 @@ +@@ -0,0 +1,24 @@ +/* Copyright (C) 2003-2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + @@ -8210,22 +8210,9 @@ + +/* We have to completely disable cancellation. assert() must not be a + cancellation point but the implementation uses write() etc. */ -+#ifdef SHARED -+# include <pthread-functions.h> -+# define FATAL_PREPARE \ -+ { \ -+ if (__libc_pthread_functions_init) \ -+ PTHFCT_CALL (ptr_pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, \ -+ NULL)); \ -+ } -+#else -+# pragma weak pthread_setcancelstate -+# define FATAL_PREPARE \ -+ { \ -+ if (pthread_setcancelstate != NULL) \ -+ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); \ -+ } -+#endif ++#define FATAL_PREPARE \ ++ __libc_ptf_call (__pthread_setcancelstate, \ ++ (PTHREAD_CANCEL_DISABLE, NULL), 0) --- /dev/null +++ b/sysdeps/unix/bsd/bsd4.4/kfreebsd/fbtl/fork.c @@ -0,0 +1,231 @@ @@ -8257,7 +8244,7 @@ +#include "fork.h" +#include <hp-timing.h> +#include <ldsodefs.h> -+#include <bits/stdio-lock.h> ++#include <stdio-lock.h> +#include <atomic.h> +#include <pthreadP.h> + @@ -9081,7 +9068,7 @@ +#include <tls.h> +#include <string.h> +#include <pthreadP.h> -+#include <bits/libc-lock.h> ++#include <libc-lock.h> +#include <sysdep.h> +#include <ldsodefs.h> + @@ -26710,7 +26697,7 @@ +#include <stdio.h> +#include <string.h> +#include <sys/statfs.h> -+#include <bits/libc-lock.h> ++#include <libc-lock.h> + +/* Mount point of the shared memory filesystem. */ +static struct -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-glibc/glibc.git

