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