glibc/compat-2.17-libpthreadcond-so.patch
Yang Yanchao 0efa08b12d glibc:add glibc-compat-2.17 subpackage to provide the function of the glibc-2.17 pthread library.
Currently, provide pthread_condition function.

Signed-off-by: Yang Yanchao <yangyanchao6@huawei.com>
2021-10-26 15:11:36 +08:00

9559 lines
338 KiB
Diff

commit a88c9263686012ca2a336379b7d66e59dea2b43b
Author: Ulrich Drepper <drepper@redhat.com>
Date: Wed Feb 5 09:54:24 2003 +0000
Subject: [PATCH] build extra lipthreadcond so
since https://sourceware.org/git/?p=glibc.git;a=commit;h=ed19993b5b0d05d62cc883571519a67dae481a14
delete pthread_condtion function.However, using these interfaces has better performance.
Therefore, we add a subpacket to use these interfaces.
you can use it by adding LD_PRELOAD=./libpthreadcond.so in front of your program (eg:
LD_PRELOAD=./libpthreadcond.so ./test). use with-compat_2_17 to compile it.
WARNING:2.17 version does not meet the posix standard, you should pay attention when using it.
This patch contains, but is not limited to, the following submissions:
a88c9263686,59ba27a63ad,9bc6103d046,5acf7263d52,7ce5c1640cb,3e976b962a8,5bd8a24966d
During the evolution of glibc, many header files are changed. To ensure the stability
of libpthread-2.17, header files of earlier versions are used, such as lowlevellock.h, sysdep.h,
descr.h, and futex-internal.h,pthread-function.h,pthreadtypes-arch.h,no-cancel.h.etc. Of course,
there are some interface modifications, such as __pause_nocancel.
---
nptl_2_17/Makefile | 50 +
nptl_2_17/bits/pthreadtypes_2_17.h | 127 ++
nptl_2_17/bits/thread-shared-types_2_17.h | 185 +++
nptl_2_17/build_libpthread-2.17.so.sh | 10 +
nptl_2_17/cancellation_2_17.c | 102 ++
nptl_2_17/cleanup_compat_2_17.c | 50 +
nptl_2_17/descr_2_17.h | 412 ++++++
nptl_2_17/elision-conf_2_17.c | 137 ++
nptl_2_17/elision-conf_2_17.h | 41 +
nptl_2_17/elision-lock_2_17.c | 107 ++
nptl_2_17/elision-timed_2_17.c | 26 +
nptl_2_17/elision-trylock_2_17.c | 75 ++
nptl_2_17/elision-unlock_2_17.c | 33 +
nptl_2_17/futex-internal_2_17.h | 263 ++++
nptl_2_17/hle_2_17.h | 75 ++
nptl_2_17/internaltypes_2_17.h | 179 +++
nptl_2_17/kernel-features_2_17.h | 162 +++
nptl_2_17/libpthread-2.17-aarch64.map | 8 +
nptl_2_17/libpthread-2.17-x86_64.map | 8 +
nptl_2_17/lll_timedlock_wait_2_17.c | 59 +
nptl_2_17/lowlevellock_2_17.c | 46 +
nptl_2_17/pthread-functions_2_17.h | 116 ++
nptl_2_17/pthreadP_2_17.h | 714 ++++++++++
nptl_2_17/pthread_2_17.h | 1162 +++++++++++++++++
nptl_2_17/pthread_cond_broadcast_2_17.c | 98 ++
nptl_2_17/pthread_cond_destroy_2_17.c | 85 ++
nptl_2_17/pthread_cond_init_2_17.c | 50 +
nptl_2_17/pthread_cond_signal_2_17.c | 82 ++
nptl_2_17/pthread_cond_timedwait_2_17.c | 266 ++++
nptl_2_17/pthread_cond_wait_2_17.c | 234 ++++
nptl_2_17/pthread_condattr_getclock_2_17.c | 28 +
nptl_2_17/pthread_condattr_getpshared_2_17.c | 28 +
nptl_2_17/pthread_condattr_init_2_17.c | 33 +
nptl_2_17/pthread_condattr_setclock_2_17.c | 45 +
nptl_2_17/pthread_mutex_cond_lock_2_17.c | 21 +
nptl_2_17/pthread_mutex_lock_2_17.c | 635 +++++++++
nptl_2_17/pthread_mutex_unlock_2_17.c | 359 +++++
.../nptl/bits/pthreadtypes-arch_2_17.h | 71 +
nptl_2_17/sysdeps/generic/sysdep_2_17.h | 97 ++
nptl_2_17/sysdeps/nptl/futex-internal_2_17.h | 210 +++
nptl_2_17/sysdeps/nptl/lowlevellock_2_17.h | 208 +++
nptl_2_17/sysdeps/unix/sysdep_2_17.h | 148 +++
.../unix/sysv/linux/aarch64/sysdep_2_17.h | 301 +++++
.../unix/sysv/linux/generic/sysdep_2_17.h | 35 +
.../unix/sysv/linux/internal-signals_2_17.h | 91 ++
.../unix/sysv/linux/lowlevellock-futex_2_17.h | 150 +++
.../sysdeps/unix/sysv/linux/not-cancel_2_17.h | 93 ++
.../sysdeps/unix/sysv/linux/sysdep_2_17.h | 68 +
.../unix/sysv/linux/x86_64/sysdep_2_17.h | 432 ++++++
nptl_2_17/sysdeps/unix/x86_64/sysdep_2_17.h | 34 +
nptl_2_17/sysdeps/x86/sysdep_2_17.h | 104 ++
.../x86_64/nptl/bits/pthreadtypes-arch_2_17.h | 106 ++
nptl_2_17/sysdeps/x86_64/sysdep_2_17.h | 129 ++
nptl_2_17/thread_db_2_17.h | 458 +++++++
nptl_2_17/tpp_2_17.c | 195 +++
nptl_2_17/vars_2_17.c | 43 +
56 files changed, 9084 insertions(+)
create mode 100644 nptl_2_17/Makefile
create mode 100644 nptl_2_17/bits/pthreadtypes_2_17.h
create mode 100644 nptl_2_17/bits/thread-shared-types_2_17.h
create mode 100644 nptl_2_17/build_libpthread-2.17.so.sh
create mode 100644 nptl_2_17/cancellation_2_17.c
create mode 100644 nptl_2_17/cleanup_compat_2_17.c
create mode 100644 nptl_2_17/descr_2_17.h
create mode 100644 nptl_2_17/elision-conf_2_17.c
create mode 100644 nptl_2_17/elision-conf_2_17.h
create mode 100644 nptl_2_17/elision-lock_2_17.c
create mode 100644 nptl_2_17/elision-timed_2_17.c
create mode 100644 nptl_2_17/elision-trylock_2_17.c
create mode 100644 nptl_2_17/elision-unlock_2_17.c
create mode 100644 nptl_2_17/futex-internal_2_17.h
create mode 100644 nptl_2_17/hle_2_17.h
create mode 100644 nptl_2_17/internaltypes_2_17.h
create mode 100644 nptl_2_17/kernel-features_2_17.h
create mode 100644 nptl_2_17/libpthread-2.17-aarch64.map
create mode 100644 nptl_2_17/libpthread-2.17-x86_64.map
create mode 100644 nptl_2_17/lll_timedlock_wait_2_17.c
create mode 100644 nptl_2_17/lowlevellock_2_17.c
create mode 100644 nptl_2_17/pthread-functions_2_17.h
create mode 100644 nptl_2_17/pthreadP_2_17.h
create mode 100644 nptl_2_17/pthread_2_17.h
create mode 100644 nptl_2_17/pthread_cond_broadcast_2_17.c
create mode 100644 nptl_2_17/pthread_cond_destroy_2_17.c
create mode 100644 nptl_2_17/pthread_cond_init_2_17.c
create mode 100644 nptl_2_17/pthread_cond_signal_2_17.c
create mode 100644 nptl_2_17/pthread_cond_timedwait_2_17.c
create mode 100644 nptl_2_17/pthread_cond_wait_2_17.c
create mode 100644 nptl_2_17/pthread_condattr_getclock_2_17.c
create mode 100644 nptl_2_17/pthread_condattr_getpshared_2_17.c
create mode 100644 nptl_2_17/pthread_condattr_init_2_17.c
create mode 100644 nptl_2_17/pthread_condattr_setclock_2_17.c
create mode 100644 nptl_2_17/pthread_mutex_cond_lock_2_17.c
create mode 100644 nptl_2_17/pthread_mutex_lock_2_17.c
create mode 100644 nptl_2_17/pthread_mutex_unlock_2_17.c
create mode 100644 nptl_2_17/sysdeps/aarch64/nptl/bits/pthreadtypes-arch_2_17.h
create mode 100644 nptl_2_17/sysdeps/generic/sysdep_2_17.h
create mode 100644 nptl_2_17/sysdeps/nptl/futex-internal_2_17.h
create mode 100644 nptl_2_17/sysdeps/nptl/lowlevellock_2_17.h
create mode 100644 nptl_2_17/sysdeps/unix/sysdep_2_17.h
create mode 100644 nptl_2_17/sysdeps/unix/sysv/linux/aarch64/sysdep_2_17.h
create mode 100644 nptl_2_17/sysdeps/unix/sysv/linux/generic/sysdep_2_17.h
create mode 100644 nptl_2_17/sysdeps/unix/sysv/linux/internal-signals_2_17.h
create mode 100644 nptl_2_17/sysdeps/unix/sysv/linux/lowlevellock-futex_2_17.h
create mode 100644 nptl_2_17/sysdeps/unix/sysv/linux/not-cancel_2_17.h
create mode 100644 nptl_2_17/sysdeps/unix/sysv/linux/sysdep_2_17.h
create mode 100644 nptl_2_17/sysdeps/unix/sysv/linux/x86_64/sysdep_2_17.h
create mode 100644 nptl_2_17/sysdeps/unix/x86_64/sysdep_2_17.h
create mode 100644 nptl_2_17/sysdeps/x86/sysdep_2_17.h
create mode 100644 nptl_2_17/sysdeps/x86_64/nptl/bits/pthreadtypes-arch_2_17.h
create mode 100644 nptl_2_17/sysdeps/x86_64/sysdep_2_17.h
create mode 100644 nptl_2_17/thread_db_2_17.h
create mode 100644 nptl_2_17/tpp_2_17.c
create mode 100644 nptl_2_17/vars_2_17.c
diff --git a/nptl_2_17/Makefile b/nptl_2_17/Makefile
new file mode 100644
index 00000000..4c66b2b6
--- /dev/null
+++ b/nptl_2_17/Makefile
@@ -0,0 +1,50 @@
+include libpthread-2.17_config
+subdir=libpthread-2.17
+objdir=../$(build_dir)/
+
+
+ifdef subdir
+.. := ../
+endif
+
+objpfx := $(patsubst %//,%/,$(objdir)/$(subdir)/)
+common-objpfx = $(objdir)/
+common-objdir = $(objdir)
+
+sysdep_dir := $(..)sysdeps
+export sysdep_dir := $(sysdep_dir)
+
+include $(common-objpfx)soversions.mk
+include $(common-objpfx)config.make
+
+uses-callbacks = -fexceptions
+
+sysdirs := $(foreach D,$(config-sysdirs),$(firstword $(filter /%,$D) $(..)$D))
+
++sysdep_dirs = $(sysdirs)
++sysdep_dirs := $(objdir) $(+sysdep_dirs)
+
++sysdep-includes := $(foreach dir,$(+sysdep_dirs), $(addprefix -I,$(wildcard $(dir)/include) $(dir)))
+
+compile_obj = pthread_cond_wait_2_17.os pthread_cond_timedwait_2_17.os pthread_cond_signal_2_17.os pthread_cond_broadcast_2_17.os pthread_cond_init_2_17.os pthread_cond_destroy_2_17.os pthread_condattr_getclock_2_17.os pthread_condattr_getpshared_2_17.os pthread_condattr_init_2_17.os pthread_condattr_setclock_2_17.os cleanup_compat_2_17.os cancellation_2_17.os pthread_mutex_lock_2_17.os pthread_mutex_unlock_2_17.os tpp_2_17.os vars_2_17.os pthread_mutex_cond_lock_2_17.os lll_timedlock_wait_2_17.os lowlevellock_2_17.os
+
+ifeq (x86_64, $(arch))
+compile_obj += elision-lock_2_17.os elision-unlock_2_17.os elision-timed_2_17.os elision-trylock_2_17.os
+endif
+
+compile_obj_dir = $(foreach n,$(compile_obj),../$(build_dir)/nptl/$(n))
+
+CFLAGS = -c -std=gnu11 -fgnu89-inline -fPIE -DNDEBUG -O2 -Wall -Werror -Wp,-D_GLIBCXX_ASSERTIONS -Wundef -Wwrite-strings -fasynchronous-unwind-tables -fmerge-all-constants -frounding-math -fstack-clash-protection -fstack-protector-strong -g -mtune=generic -Wstrict-prototypes -Wold-style-definition -fno-math-errno -fPIC -fexceptions -fasynchronous-unwind-tables -ftls-model=initial-exec -D_FORTIFY_SOURCE=2 -DSHARED -DTOP_NAMESPACE=glibc
+
+Headers = -I../include -I../$(build_dir)/nptl $(+sysdep-includes) -I../nptl_2_17 -I../nptl -I../libio -I../. -I../nptl_2_17/sysdeps/$(arch)/nptl -I../nptl_2_17/sysdeps/nptl -I../nptl_2_17/sysdeps/unix/sysv/linux/$(arch) -I../nptl_2_17/sysdeps/unix/sysv/linux -D_LIBC_REENTRANT -include ../$(build_dir)/libc-modules.h -include include/libc-symbols.h
+
+all: libpthread-2.17.so
+
+libpthread-2.17.so : $(compile_obj) libpthread-2.17_pic.a
+ gcc -shared -static-libgcc -Wl,-O1 -Wl,-z,defs -Wl,-dynamic-linker=/usr/local/lib/$(ld.so-version) -B../$(build_dir)/csu/ -Wl,--version-script=libpthread-2.17-$(arch).map -Wl,-soname=libpthread-2.17.so.0 -Wl,-z,noexecstack -Wtrampolines -Wl,-z,combreloc -Wl,-z,relro -Wl,--hash-style=both -Wl,-z,now -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst -L../$(build_dir) -L../$(build_dir)/math -L../$(build_dir)/elf -L../$(build_dir)/dlfcn -L../$(build_dir)/nss -L../$(build_dir)/nis -L../$(build_dir)/rt -L../$(build_dir)/resolv -L../$(build_dir)/mathvec -L../$(build_dir)/support -L../$(build_dir)/crypt -L../$(build_dir)/nptl -Wl,-rpath-link=../$(build_dir):../$(build_dir)/math:../$(build_dir)/elf:../$(build_dir)/dlfcn:../$(build_dir)/nss:../$(build_dir)/nis:../$(build_dir)/rt:../$(build_dir)/resolv:../$(build_dir)/mathvec:../$(build_dir)/support:../$(build_dir)/crypt:../$(build_dir)/nptl -o ../$(build_dir)/nptl/libpthread-2.17.so ../$(build_dir)/csu/abi-note.o -Wl,--whole-archive ../$(build_dir)/nptl/libpthread-2.17_pic.a -Wl,--no-whole-archive -Wl,--start-group ../$(build_dir)/libc.so ../$(build_dir)/libc_nonshared.a -Wl,--as-needed ../$(build_dir)/elf/ld.so -Wl,--no-as-needed -Wl,--end-group
+
+libpthread-2.17_pic.a : $(compile_obj_dir)
+ ar cruv ../$(build_dir)/nptl/$@ $^
+
+$(compile_obj) : %.os : %.c
+ gcc $< $(CFLAGS) $(Headers) -o ../$(build_dir)/nptl/$@ -MD -MP -MF ../$(build_dir)/nptl/$@.dt -MT ../$(build_dir)/nptl/$@
diff --git a/nptl_2_17/bits/pthreadtypes_2_17.h b/nptl_2_17/bits/pthreadtypes_2_17.h
new file mode 100644
index 00000000..da5521c1
--- /dev/null
+++ b/nptl_2_17/bits/pthreadtypes_2_17.h
@@ -0,0 +1,127 @@
+/* Declaration of common pthread types for all architectures.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _BITS_PTHREADTYPES_COMMON_H
+# define _BITS_PTHREADTYPES_COMMON_H 1
+
+/* For internal mutex and condition variable definitions. */
+#include "thread-shared-types_2_17.h"
+
+/* Thread identifiers. The structure of the attribute type is not
+ exposed on purpose. */
+typedef unsigned long int pthread_t;
+
+
+/* Data structures for mutex handling. The structure of the attribute
+ type is not exposed on purpose. */
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
+ int __align;
+} pthread_mutexattr_t;
+
+
+/* Data structure for condition variable handling. The structure of
+ the attribute type is not exposed on purpose. */
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_CONDATTR_T];
+ int __align;
+} pthread_condattr_t;
+
+
+/* Keys for thread-specific data */
+typedef unsigned int pthread_key_t;
+
+
+/* Once-only execution */
+typedef int __ONCE_ALIGNMENT pthread_once_t;
+
+
+union pthread_attr_t
+{
+ char __size[__SIZEOF_PTHREAD_ATTR_T];
+ long int __align;
+};
+#ifndef __have_pthread_attr_t
+typedef union pthread_attr_t pthread_attr_t;
+# define __have_pthread_attr_t 1
+#endif
+
+
+typedef union
+{
+ struct __pthread_mutex_s __data;
+ char __size[__SIZEOF_PTHREAD_MUTEX_T];
+ long int __align;
+} pthread_mutex_t;
+
+
+typedef union
+{
+struct
+{
+ int __lock;
+ unsigned int __futex;
+ __extension__ unsigned long long int __total_seq;
+ __extension__ unsigned long long int __wakeup_seq;
+ __extension__ unsigned long long int __woken_seq;
+ void *__mutex;
+ unsigned int __nwaiters;
+ unsigned int __broadcast_seq;
+}__data;
+ char __size[__SIZEOF_PTHREAD_COND_T];
+ long int __align;
+} pthread_cond_t;
+
+
+/* Data structure for reader-writer lock variable handling. The
+ structure of the attribute type is deliberately not exposed. */
+typedef union
+{
+ struct __pthread_rwlock_arch_t __data;
+ char __size[__SIZEOF_PTHREAD_RWLOCK_T];
+ long int __align;
+} pthread_rwlock_t;
+
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T];
+ long int __align;
+} pthread_rwlockattr_t;
+
+
+/* POSIX spinlock data type. */
+typedef volatile int pthread_spinlock_t;
+
+
+/* POSIX barriers data type. The structure of the type is
+ deliberately not exposed. */
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_BARRIER_T];
+ long int __align;
+} pthread_barrier_t;
+
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_BARRIERATTR_T];
+ int __align;
+} pthread_barrierattr_t;
+
+#endif
diff --git a/nptl_2_17/bits/thread-shared-types_2_17.h b/nptl_2_17/bits/thread-shared-types_2_17.h
new file mode 100644
index 00000000..497e6903
--- /dev/null
+++ b/nptl_2_17/bits/thread-shared-types_2_17.h
@@ -0,0 +1,185 @@
+/* Common threading primitives definitions for both POSIX and C11.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _THREAD_SHARED_TYPES_H
+#define _THREAD_SHARED_TYPES_H 1
+
+/* Arch-specific definitions. Each architecture must define the following
+ macros to define the expected sizes of pthread data types:
+
+ __SIZEOF_PTHREAD_ATTR_T - size of pthread_attr_t.
+ __SIZEOF_PTHREAD_MUTEX_T - size of pthread_mutex_t.
+ __SIZEOF_PTHREAD_MUTEXATTR_T - size of pthread_mutexattr_t.
+ __SIZEOF_PTHREAD_COND_T - size of pthread_cond_t.
+ __SIZEOF_PTHREAD_CONDATTR_T - size of pthread_condattr_t.
+ __SIZEOF_PTHREAD_RWLOCK_T - size of pthread_rwlock_t.
+ __SIZEOF_PTHREAD_RWLOCKATTR_T - size of pthread_rwlockattr_t.
+ __SIZEOF_PTHREAD_BARRIER_T - size of pthread_barrier_t.
+ __SIZEOF_PTHREAD_BARRIERATTR_T - size of pthread_barrierattr_t.
+
+ Also, the following macros must be define for internal pthread_mutex_t
+ struct definitions (struct __pthread_mutex_s):
+
+ __PTHREAD_COMPAT_PADDING_MID - any additional members after 'kind'
+ and before '__spin' (for 64 bits) or
+ '__nusers' (for 32 bits).
+ __PTHREAD_COMPAT_PADDING_END - any additional members at the end of
+ the internal structure.
+ __PTHREAD_MUTEX_LOCK_ELISION - 1 if the architecture supports lock
+ elision or 0 otherwise.
+ __PTHREAD_MUTEX_NUSERS_AFTER_KIND - control where to put __nusers. The
+ preferred value for new architectures
+ is 0.
+ __PTHREAD_MUTEX_USE_UNION - control whether internal __spins and
+ __list will be place inside a union for
+ linuxthreads compatibility.
+ The preferred value for new architectures
+ is 0.
+
+ For a new port the preferred values for the required defines are:
+
+ #define __PTHREAD_COMPAT_PADDING_MID
+ #define __PTHREAD_COMPAT_PADDING_END
+ #define __PTHREAD_MUTEX_LOCK_ELISION 0
+ #define __PTHREAD_MUTEX_NUSERS_AFTER_KIND 0
+ #define __PTHREAD_MUTEX_USE_UNION 0
+
+ __PTHREAD_MUTEX_LOCK_ELISION can be set to 1 if the hardware plans to
+ eventually support lock elision using transactional memory.
+
+ The additional macro defines any constraint for the lock alignment
+ inside the thread structures:
+
+ __LOCK_ALIGNMENT - for internal lock/futex usage.
+
+ Same idea but for the once locking primitive:
+
+ __ONCE_ALIGNMENT - for pthread_once_t/once_flag definition.
+
+ And finally the internal pthread_rwlock_t (struct __pthread_rwlock_arch_t)
+ must be defined.
+ */
+#include <bits/pthreadtypes-arch_2_17.h>
+
+/* Common definition of pthread_mutex_t. */
+
+#if !__PTHREAD_MUTEX_USE_UNION
+typedef struct __pthread_internal_list
+{
+ struct __pthread_internal_list *__prev;
+ struct __pthread_internal_list *__next;
+} __pthread_list_t;
+#else
+typedef struct __pthread_internal_slist
+{
+ struct __pthread_internal_slist *__next;
+} __pthread_slist_t;
+#endif
+
+/* Lock elision support. */
+#if __PTHREAD_MUTEX_LOCK_ELISION
+# if !__PTHREAD_MUTEX_USE_UNION
+# define __PTHREAD_SPINS_DATA \
+ short __spins; \
+ short __elision
+# define __PTHREAD_SPINS 0, 0
+# else
+# define __PTHREAD_SPINS_DATA \
+ struct \
+ { \
+ short __espins; \
+ short __eelision; \
+ } __elision_data
+# define __PTHREAD_SPINS { 0, 0 }
+# define __spins __elision_data.__espins
+# define __elision __elision_data.__eelision
+# endif
+#else
+# define __PTHREAD_SPINS_DATA int __spins
+/* Mutex __spins initializer used by PTHREAD_MUTEX_INITIALIZER. */
+# define __PTHREAD_SPINS 0
+#endif
+
+struct __pthread_mutex_s
+{
+ int __lock __LOCK_ALIGNMENT;
+ unsigned int __count;
+ int __owner;
+#if !__PTHREAD_MUTEX_NUSERS_AFTER_KIND
+ unsigned int __nusers;
+#endif
+ /* KIND must stay at this position in the structure to maintain
+ binary compatibility with static initializers.
+
+ Concurrency notes:
+ The __kind of a mutex is initialized either by the static
+ PTHREAD_MUTEX_INITIALIZER or by a call to pthread_mutex_init.
+
+ After a mutex has been initialized, the __kind of a mutex is usually not
+ changed. BUT it can be set to -1 in pthread_mutex_destroy or elision can
+ be enabled. This is done concurrently in the pthread_mutex_*lock functions
+ by using the macro FORCE_ELISION. This macro is only defined for
+ architectures which supports lock elision.
+
+ For elision, there are the flags PTHREAD_MUTEX_ELISION_NP and
+ PTHREAD_MUTEX_NO_ELISION_NP which can be set in addition to the already set
+ type of a mutex.
+ Before a mutex is initialized, only PTHREAD_MUTEX_NO_ELISION_NP can be set
+ with pthread_mutexattr_settype.
+ After a mutex has been initialized, the functions pthread_mutex_*lock can
+ enable elision - if the mutex-type and the machine supports it - by setting
+ the flag PTHREAD_MUTEX_ELISION_NP. This is done concurrently. Afterwards
+ the lock / unlock functions are using specific elision code-paths. */
+ int __kind;
+ __PTHREAD_COMPAT_PADDING_MID
+#if __PTHREAD_MUTEX_NUSERS_AFTER_KIND
+ unsigned int __nusers;
+#endif
+#if !__PTHREAD_MUTEX_USE_UNION
+ __PTHREAD_SPINS_DATA;
+ __pthread_list_t __list;
+# define __PTHREAD_MUTEX_HAVE_PREV 1
+#else
+ __extension__ union
+ {
+ __PTHREAD_SPINS_DATA;
+ __pthread_slist_t __list;
+ };
+# define __PTHREAD_MUTEX_HAVE_PREV 0
+#endif
+ __PTHREAD_COMPAT_PADDING_END
+};
+
+
+/* Common definition of pthread_cond_t. */
+
+struct __pthread_cond_s
+{
+ int __lock;
+ unsigned int __futex;
+ __extension__ unsigned long long int __total_seq;
+ __extension__ unsigned long long int __wakeup_seq;
+ __extension__ unsigned long long int __woken_seq;
+ void *__mutex;
+ unsigned int __nwaiters;
+ unsigned int __broadcast_seq;
+
+long int __align;
+};
+
+#endif /* _THREAD_SHARED_TYPES_H */
diff --git a/nptl_2_17/build_libpthread-2.17.so.sh b/nptl_2_17/build_libpthread-2.17.so.sh
new file mode 100644
index 00000000..bdb97d0f
--- /dev/null
+++ b/nptl_2_17/build_libpthread-2.17.so.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+set -e
+build_arch=$1
+build_dir=$2
+config_dir=libpthread-2.17_config
+
+echo arch=${build_arch} > ${config_dir}
+echo build_dir=${build_dir} >> ${config_dir}
+make
+rm -rf ${config_dir}
diff --git a/nptl_2_17/cancellation_2_17.c b/nptl_2_17/cancellation_2_17.c
new file mode 100644
index 00000000..db299fec
--- /dev/null
+++ b/nptl_2_17/cancellation_2_17.c
@@ -0,0 +1,102 @@
+/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received 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_2_17.h>
+#include <descr_2_17.h>
+#include "pthreadP_2_17.h"
+#include <setjmp.h>
+#include <stdlib.h>
+#include "futex-internal_2_17.h"
+
+/* The next two functions are similar to pthread_setcanceltype() but
+ more specialized for the use in the cancelable functions like write().
+ They do not need to check parameters etc. */
+int
+attribute_hidden
+__pthread_enable_asynccancel (void)
+{
+ struct pthread *self = THREAD_SELF;
+ int oldval = THREAD_GETMEM (self, cancelhandling);
+
+ while (1)
+ {
+ int newval = oldval | CANCELTYPE_BITMASK;
+
+ if (newval == oldval)
+ break;
+
+ int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
+ oldval);
+ if (__glibc_likely (curval == oldval))
+ {
+ if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval))
+ {
+ THREAD_SETMEM (self, result, PTHREAD_CANCELED);
+ __do_cancel ();
+ }
+
+ break;
+ }
+
+ /* Prepare the next round. */
+ oldval = curval;
+ }
+
+ return oldval;
+}
+
+
+void
+attribute_hidden
+__pthread_disable_asynccancel (int oldtype)
+{
+ /* If asynchronous cancellation was enabled before we do not have
+ anything to do. */
+ if (oldtype & CANCELTYPE_BITMASK)
+ return;
+
+ struct pthread *self = THREAD_SELF;
+ int newval;
+
+ int oldval = THREAD_GETMEM (self, cancelhandling);
+
+ while (1)
+ {
+ newval = oldval & ~CANCELTYPE_BITMASK;
+
+ int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
+ oldval);
+ if (__glibc_likely (curval == oldval))
+ break;
+
+ /* Prepare the next round. */
+ oldval = curval;
+ }
+
+ /* We cannot return when we are being canceled. Upon return the
+ thread might be things which would have to be undone. The
+ following loop should loop until the cancellation signal is
+ delivered. */
+ while (__builtin_expect ((newval & (CANCELING_BITMASK | CANCELED_BITMASK))
+ == CANCELING_BITMASK, 0))
+ {
+ futex_wait_simple ((unsigned int *) &self->cancelhandling, newval,
+ FUTEX_PRIVATE);
+ newval = THREAD_GETMEM (self, cancelhandling);
+ }
+}
diff --git a/nptl_2_17/cleanup_compat_2_17.c b/nptl_2_17/cleanup_compat_2_17.c
new file mode 100644
index 00000000..53cf903d
--- /dev/null
+++ b/nptl_2_17/cleanup_compat_2_17.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received 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_2_17.h"
+#include <stdlib.h>
+
+
+void
+_pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer,
+ void (*routine) (void *), void *arg)
+{
+ struct pthread *self = THREAD_SELF;
+
+ buffer->__routine = routine;
+ buffer->__arg = arg;
+ buffer->__prev = THREAD_GETMEM (self, cleanup);
+
+ THREAD_SETMEM (self, cleanup, buffer);
+}
+strong_alias (_pthread_cleanup_push, __pthread_cleanup_push)
+
+
+void
+_pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer, int execute)
+{
+ struct pthread *self __attribute ((unused)) = THREAD_SELF;
+
+ THREAD_SETMEM (self, cleanup, buffer->__prev);
+
+ /* If necessary call the cleanup routine after we removed the
+ current cleanup block from the list. */
+ if (execute)
+ buffer->__routine (buffer->__arg);
+}
+strong_alias (_pthread_cleanup_pop, __pthread_cleanup_pop)
diff --git a/nptl_2_17/descr_2_17.h b/nptl_2_17/descr_2_17.h
new file mode 100644
index 00000000..5148c852
--- /dev/null
+++ b/nptl_2_17/descr_2_17.h
@@ -0,0 +1,412 @@
+/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _DESCR_H
+#define _DESCR_H 1
+
+#include <limits.h>
+#include <sched.h>
+#include <setjmp.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include <hp-timing.h>
+#include <list_t.h>
+#include <lowlevellock_2_17.h>
+#include <pthreaddef.h>
+#include <dl-sysdep.h>
+#include "thread_db_2_17.h"
+#include <tls.h>
+#include <unwind.h>
+#include <bits/types/res_state.h>
+#include <kernel-features.h>
+
+#ifndef TCB_ALIGNMENT
+# define TCB_ALIGNMENT sizeof (double)
+#endif
+
+
+/* We keep thread specific data in a special data structure, a two-level
+ array. The top-level array contains pointers to dynamically allocated
+ arrays of a certain number of data pointers. So we can implement a
+ sparse array. Each dynamic second-level array has
+ PTHREAD_KEY_2NDLEVEL_SIZE
+ entries. This value shouldn't be too large. */
+#define PTHREAD_KEY_2NDLEVEL_SIZE 32
+
+/* We need to address PTHREAD_KEYS_MAX key with PTHREAD_KEY_2NDLEVEL_SIZE
+ keys in each subarray. */
+#define PTHREAD_KEY_1STLEVEL_SIZE \
+ ((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1) \
+ / PTHREAD_KEY_2NDLEVEL_SIZE)
+
+
+
+
+/* Internal version of the buffer to store cancellation handler
+ information. */
+struct pthread_unwind_buf
+{
+ struct
+ {
+ __jmp_buf jmp_buf;
+ int mask_was_saved;
+ } cancel_jmp_buf[1];
+
+ union
+ {
+ /* This is the placeholder of the public version. */
+ void *pad[4];
+
+ struct
+ {
+ /* Pointer to the previous cleanup buffer. */
+ struct pthread_unwind_buf *prev;
+
+ /* Backward compatibility: state of the old-style cleanup
+ handler at the time of the previous new-style cleanup handler
+ installment. */
+ struct _pthread_cleanup_buffer *cleanup;
+
+ /* Cancellation type before the push call. */
+ int canceltype;
+ } data;
+ } priv;
+};
+
+
+/* Opcodes and data types for communication with the signal handler to
+ change user/group IDs. */
+struct xid_command
+{
+ int syscall_no;
+ /* Enforce zero-extension for the pointer argument in
+
+ int setgroups (size_t size, const gid_t *list);
+
+ The kernel XID arguments are unsigned and do not require sign
+ extension. */
+ unsigned long int id[3];
+ volatile int cntr;
+ volatile int error; /* -1: no call yet, 0: success seen, >0: error seen. */
+};
+
+
+/* Data structure used by the kernel to find robust futexes. */
+struct robust_list_head
+{
+ void *list;
+ long int futex_offset;
+ void *list_op_pending;
+};
+
+
+/* Data strcture used to handle thread priority protection. */
+struct priority_protection_data
+{
+ int priomax;
+ unsigned int priomap[];
+};
+
+
+/* Thread descriptor data structure. */
+struct pthread
+{
+ union
+ {
+#if !TLS_DTV_AT_TP
+ /* This overlaps the TCB as used for TLS without threads (see tls.h). */
+ tcbhead_t header;
+#else
+ struct
+ {
+ /* multiple_threads is enabled either when the process has spawned at
+ least one thread or when a single-threaded process cancels itself.
+ This enables additional code to introduce locking before doing some
+ compare_and_exchange operations and also enable cancellation points.
+ The concepts of multiple threads and cancellation points ideally
+ should be separate, since it is not necessary for multiple threads to
+ have been created for cancellation points to be enabled, as is the
+ case is when single-threaded process cancels itself.
+
+ Since enabling multiple_threads enables additional code in
+ cancellation points and compare_and_exchange operations, there is a
+ potential for an unneeded performance hit when it is enabled in a
+ single-threaded, self-canceling process. This is OK though, since a
+ single-threaded process will enable async cancellation only when it
+ looks to cancel itself and is hence going to end anyway. */
+ int multiple_threads;
+ int gscope_flag;
+ } header;
+#endif
+
+ /* This extra padding has no special purpose, and this structure layout
+ is private and subject to change without affecting the official ABI.
+ We just have it here in case it might be convenient for some
+ implementation-specific instrumentation hack or suchlike. */
+ void *__padding[24];
+ };
+
+ /* This descriptor's link on the `stack_used' or `__stack_user' list. */
+ list_t list;
+
+ /* Thread ID - which is also a 'is this thread descriptor (and
+ therefore stack) used' flag. */
+ pid_t tid;
+
+ /* Ununsed. */
+ pid_t pid_ununsed;
+
+ /* List of robust mutexes the thread is holding. */
+#if __PTHREAD_MUTEX_HAVE_PREV
+ void *robust_prev;
+ struct robust_list_head robust_head;
+
+ /* The list above is strange. It is basically a double linked list
+ but the pointer to the next/previous element of the list points
+ in the middle of the object, the __next element. Whenever
+ casting to __pthread_list_t we need to adjust the pointer
+ first.
+ These operations are effectively concurrent code in that the thread
+ can get killed at any point in time and the kernel takes over. Thus,
+ the __next elements are a kind of concurrent list and we need to
+ enforce using compiler barriers that the individual operations happen
+ in such a way that the kernel always sees a consistent list. The
+ backward links (ie, the __prev elements) are not used by the kernel.
+ FIXME We should use relaxed MO atomic operations here and signal fences
+ because this kind of concurrency is similar to synchronizing with a
+ signal handler. */
+# define QUEUE_PTR_ADJUST (offsetof (__pthread_list_t, __next))
+
+# define ENQUEUE_MUTEX_BOTH(mutex, val) \
+ do { \
+ __pthread_list_t *next = (__pthread_list_t *) \
+ ((((uintptr_t) THREAD_GETMEM (THREAD_SELF, robust_head.list)) & ~1ul) \
+ - QUEUE_PTR_ADJUST); \
+ next->__prev = (void *) &mutex->__data.__list.__next; \
+ mutex->__data.__list.__next = THREAD_GETMEM (THREAD_SELF, \
+ robust_head.list); \
+ mutex->__data.__list.__prev = (void *) &THREAD_SELF->robust_head; \
+ /* Ensure that the new list entry is ready before we insert it. */ \
+ __asm ("" ::: "memory"); \
+ THREAD_SETMEM (THREAD_SELF, robust_head.list, \
+ (void *) (((uintptr_t) &mutex->__data.__list.__next) \
+ | val)); \
+ } while (0)
+# define DEQUEUE_MUTEX(mutex) \
+ do { \
+ __pthread_list_t *next = (__pthread_list_t *) \
+ ((char *) (((uintptr_t) mutex->__data.__list.__next) & ~1ul) \
+ - QUEUE_PTR_ADJUST); \
+ next->__prev = mutex->__data.__list.__prev; \
+ __pthread_list_t *prev = (__pthread_list_t *) \
+ ((char *) (((uintptr_t) mutex->__data.__list.__prev) & ~1ul) \
+ - QUEUE_PTR_ADJUST); \
+ prev->__next = mutex->__data.__list.__next; \
+ /* Ensure that we remove the entry from the list before we change the \
+ __next pointer of the entry, which is read by the kernel. */ \
+ __asm ("" ::: "memory"); \
+ mutex->__data.__list.__prev = NULL; \
+ mutex->__data.__list.__next = NULL; \
+ } while (0)
+#else
+ union
+ {
+ __pthread_slist_t robust_list;
+ struct robust_list_head robust_head;
+ };
+
+# define ENQUEUE_MUTEX_BOTH(mutex, val) \
+ do { \
+ mutex->__data.__list.__next \
+ = THREAD_GETMEM (THREAD_SELF, robust_list.__next); \
+ /* Ensure that the new list entry is ready before we insert it. */ \
+ __asm ("" ::: "memory"); \
+ THREAD_SETMEM (THREAD_SELF, robust_list.__next, \
+ (void *) (((uintptr_t) &mutex->__data.__list) | val)); \
+ } while (0)
+# define DEQUEUE_MUTEX(mutex) \
+ do { \
+ __pthread_slist_t *runp = (__pthread_slist_t *) \
+ (((uintptr_t) THREAD_GETMEM (THREAD_SELF, robust_list.__next)) & ~1ul); \
+ if (runp == &mutex->__data.__list) \
+ THREAD_SETMEM (THREAD_SELF, robust_list.__next, runp->__next); \
+ else \
+ { \
+ __pthread_slist_t *next = (__pthread_slist_t *) \
+ (((uintptr_t) runp->__next) & ~1ul); \
+ while (next != &mutex->__data.__list) \
+ { \
+ runp = next; \
+ next = (__pthread_slist_t *) (((uintptr_t) runp->__next) & ~1ul); \
+ } \
+ \
+ runp->__next = next->__next; \
+ /* Ensure that we remove the entry from the list before we change the \
+ __next pointer of the entry, which is read by the kernel. */ \
+ __asm ("" ::: "memory"); \
+ mutex->__data.__list.__next = NULL; \
+ } \
+ } while (0)
+#endif
+#define ENQUEUE_MUTEX(mutex) ENQUEUE_MUTEX_BOTH (mutex, 0)
+#define ENQUEUE_MUTEX_PI(mutex) ENQUEUE_MUTEX_BOTH (mutex, 1)
+
+ /* List of cleanup buffers. */
+ struct _pthread_cleanup_buffer *cleanup;
+
+ /* Unwind information. */
+ struct pthread_unwind_buf *cleanup_jmp_buf;
+#define HAVE_CLEANUP_JMP_BUF
+
+ /* Flags determining processing of cancellation. */
+ int cancelhandling;
+ /* Bit set if cancellation is disabled. */
+#define CANCELSTATE_BIT 0
+#define CANCELSTATE_BITMASK (0x01 << CANCELSTATE_BIT)
+ /* Bit set if asynchronous cancellation mode is selected. */
+#define CANCELTYPE_BIT 1
+#define CANCELTYPE_BITMASK (0x01 << CANCELTYPE_BIT)
+ /* Bit set if canceling has been initiated. */
+#define CANCELING_BIT 2
+#define CANCELING_BITMASK (0x01 << CANCELING_BIT)
+ /* Bit set if canceled. */
+#define CANCELED_BIT 3
+#define CANCELED_BITMASK (0x01 << CANCELED_BIT)
+ /* Bit set if thread is exiting. */
+#define EXITING_BIT 4
+#define EXITING_BITMASK (0x01 << EXITING_BIT)
+ /* Bit set if thread terminated and TCB is freed. */
+#define TERMINATED_BIT 5
+#define TERMINATED_BITMASK (0x01 << TERMINATED_BIT)
+ /* Bit set if thread is supposed to change XID. */
+#define SETXID_BIT 6
+#define SETXID_BITMASK (0x01 << SETXID_BIT)
+ /* Mask for the rest. Helps the compiler to optimize. */
+#define CANCEL_RESTMASK 0xffffff80
+
+#define CANCEL_ENABLED_AND_CANCELED(value) \
+ (((value) & (CANCELSTATE_BITMASK | CANCELED_BITMASK | EXITING_BITMASK \
+ | CANCEL_RESTMASK | TERMINATED_BITMASK)) == CANCELED_BITMASK)
+#define CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS(value) \
+ (((value) & (CANCELSTATE_BITMASK | CANCELTYPE_BITMASK | CANCELED_BITMASK \
+ | EXITING_BITMASK | CANCEL_RESTMASK | TERMINATED_BITMASK)) \
+ == (CANCELTYPE_BITMASK | CANCELED_BITMASK))
+
+ /* Flags. Including those copied from the thread attribute. */
+ int flags;
+
+ /* We allocate one block of references here. This should be enough
+ to avoid allocating any memory dynamically for most applications. */
+ struct pthread_key_data
+ {
+ /* Sequence number. We use uintptr_t to not require padding on
+ 32- and 64-bit machines. On 64-bit machines it helps to avoid
+ wrapping, too. */
+ uintptr_t seq;
+
+ /* Data pointer. */
+ void *data;
+ } specific_1stblock[PTHREAD_KEY_2NDLEVEL_SIZE];
+
+ /* Two-level array for the thread-specific data. */
+ struct pthread_key_data *specific[PTHREAD_KEY_1STLEVEL_SIZE];
+
+ /* Flag which is set when specific data is set. */
+ bool specific_used;
+
+ /* True if events must be reported. */
+ bool report_events;
+
+ /* True if the user provided the stack. */
+ bool user_stack;
+
+ /* True if thread must stop at startup time. */
+ bool stopped_start;
+
+ /* The parent's cancel handling at the time of the pthread_create
+ call. This might be needed to undo the effects of a cancellation. */
+ int parent_cancelhandling;
+
+ /* Lock to synchronize access to the descriptor. */
+ int lock;
+
+ /* Lock for synchronizing setxid calls. */
+ unsigned int setxid_futex;
+
+#ifdef __x86_64__
+ /* Offset of the CPU clock at start thread start time. */
+ hp_timing_t cpuclock_offset;
+#endif
+
+ /* If the thread waits to join another one the ID of the latter is
+ stored here.
+
+ In case a thread is detached this field contains a pointer of the
+ TCB if the thread itself. This is something which cannot happen
+ in normal operation. */
+ struct pthread *joinid;
+ /* Check whether a thread is detached. */
+#define IS_DETACHED(pd) ((pd)->joinid == (pd))
+
+ /* The result of the thread function. */
+ void *result;
+
+ /* Scheduling parameters for the new thread. */
+ struct sched_param schedparam;
+ int schedpolicy;
+
+ /* Start position of the code to be executed and the argument passed
+ to the function. */
+ void *(*start_routine) (void *);
+ void *arg;
+
+ /* Debug state. */
+ td_eventbuf_t eventbuf;
+ /* Next descriptor with a pending event. */
+ struct pthread *nextevent;
+
+ /* Machine-specific unwind info. */
+ struct _Unwind_Exception exc;
+
+ /* If nonzero, pointer to the area allocated for the stack and guard. */
+ void *stackblock;
+ /* Size of the stackblock area including the guard. */
+ size_t stackblock_size;
+ /* Size of the included guard area. */
+ size_t guardsize;
+ /* This is what the user specified and what we will report. */
+ size_t reported_guardsize;
+
+ /* Thread Priority Protection data. */
+ struct priority_protection_data *tpp;
+
+ /* Resolver state. */
+ struct __res_state res;
+
+ /* Indicates whether is a C11 thread created by thrd_creat. */
+ bool c11;
+
+ /* This member must be last. */
+ char end_padding[];
+
+#define PTHREAD_STRUCT_END_PADDING \
+ (sizeof (struct pthread) - offsetof (struct pthread, end_padding))
+} __attribute ((aligned (TCB_ALIGNMENT)));
+
+
+#endif /* descr.h */
diff --git a/nptl_2_17/elision-conf_2_17.c b/nptl_2_17/elision-conf_2_17.c
new file mode 100644
index 00000000..13dd985e
--- /dev/null
+++ b/nptl_2_17/elision-conf_2_17.c
@@ -0,0 +1,137 @@
+/* elision-conf.c: Lock elision tunable parameters.
+ Copyright (C) 2013-2018 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 "config.h"
+#include <pthreadP_2_17.h>
+#include <init-arch.h>
+#include <elision-conf_2_17.h>
+#include <unistd.h>
+
+# define TUNABLE_NAMESPACE elision
+# define TOP_NAMESPACE glibc
+#include <elf/dl-tunables.h>
+
+/* Reasonable initial tuning values, may be revised in the future.
+ This is a conservative initial value. */
+
+struct elision_config __elision_aconf =
+ {
+ /* How often to not attempt to use elision if a transaction aborted
+ because the lock is already acquired. Expressed in number of lock
+ acquisition attempts. */
+ .skip_lock_busy = 3,
+ /* How often to not attempt to use elision if a transaction aborted due
+ to reasons other than other threads' memory accesses. Expressed in
+ number of lock acquisition attempts. */
+ .skip_lock_internal_abort = 3,
+ /* How often we retry using elision if there is chance for the transaction
+ to finish execution (e.g., it wasn't aborted due to the lock being
+ already acquired. */
+ .retry_try_xbegin = 3,
+ /* Same as SKIP_LOCK_INTERNAL_ABORT but for trylock. */
+ .skip_trylock_internal_abort = 3,
+ };
+
+/* Force elision for all new locks. This is used to decide whether existing
+ DEFAULT locks should be automatically upgraded to elision in
+ pthread_mutex_lock(). Disabled for suid programs. Only used when elision
+ is available. */
+
+int __pthread_force_elision attribute_hidden = 0;
+
+#if HAVE_TUNABLES
+static inline void
+__always_inline
+do_set_elision_enable (int32_t elision_enable)
+{
+ /* Enable elision if it's avaliable in hardware. It's not necessary to check
+ if __libc_enable_secure isn't enabled since elision_enable will be set
+ according to the default, which is disabled. */
+ if (elision_enable == 1)
+ __pthread_force_elision = HAS_CPU_FEATURE (RTM) ? 1 : 0;
+}
+
+/* The pthread->elision_enable tunable is 0 or 1 indicating that elision
+ should be disabled or enabled respectively. The feature will only be used
+ if it's supported by the hardware. */
+
+void
+TUNABLE_CALLBACK (set_elision_enable) (tunable_val_t *valp)
+{
+ int32_t elision_enable = (int32_t) valp->numval;
+ do_set_elision_enable (elision_enable);
+}
+
+#define TUNABLE_CALLBACK_FNDECL(__name, __type) \
+static inline void \
+__always_inline \
+do_set_elision_ ## __name (__type value) \
+{ \
+ __elision_aconf.__name = value; \
+} \
+void \
+TUNABLE_CALLBACK (set_elision_ ## __name) (tunable_val_t *valp) \
+{ \
+ __type value = (__type) (valp)->numval; \
+ do_set_elision_ ## __name (value); \
+}
+
+TUNABLE_CALLBACK_FNDECL (skip_lock_busy, int32_t);
+TUNABLE_CALLBACK_FNDECL (skip_lock_internal_abort, int32_t);
+TUNABLE_CALLBACK_FNDECL (retry_try_xbegin, int32_t);
+TUNABLE_CALLBACK_FNDECL (skip_trylock_internal_abort, int32_t);
+#endif
+
+/* Initialize elision. */
+
+static void
+elision_init (int argc __attribute__ ((unused)),
+ char **argv __attribute__ ((unused)),
+ char **environ)
+{
+#if HAVE_TUNABLES
+ /* Elision depends on tunables and must be explicitly turned on by setting
+ the appropriate tunable on a supported platform. */
+
+ TUNABLE_GET (enable, int32_t,
+ TUNABLE_CALLBACK (set_elision_enable));
+ TUNABLE_GET (skip_lock_busy, int32_t,
+ TUNABLE_CALLBACK (set_elision_skip_lock_busy));
+ TUNABLE_GET (skip_lock_internal_abort, int32_t,
+ TUNABLE_CALLBACK (set_elision_skip_lock_internal_abort));
+ TUNABLE_GET (tries, int32_t,
+ TUNABLE_CALLBACK (set_elision_retry_try_xbegin));
+ TUNABLE_GET (skip_trylock_internal_abort, int32_t,
+ TUNABLE_CALLBACK (set_elision_skip_trylock_internal_abort));
+#endif
+
+ if (!__pthread_force_elision)
+ __elision_aconf.retry_try_xbegin = 0; /* Disable elision on rwlocks. */
+}
+
+#ifdef SHARED
+# define INIT_SECTION ".init_array"
+#else
+# define INIT_SECTION ".preinit_array"
+#endif
+
+void (*const __pthread_init_array []) (int, char **, char **)
+ __attribute__ ((section (INIT_SECTION), aligned (sizeof (void *)))) =
+{
+ &elision_init
+};
diff --git a/nptl_2_17/elision-conf_2_17.h b/nptl_2_17/elision-conf_2_17.h
new file mode 100644
index 00000000..9cd38962
--- /dev/null
+++ b/nptl_2_17/elision-conf_2_17.h
@@ -0,0 +1,41 @@
+/* elision-conf.h: Lock elision tunable parameters.
+ Copyright (C) 2013-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+#ifndef _ELISION_CONF_H
+#define _ELISION_CONF_H 1
+
+#include <pthread_2_17.h>
+#include <time.h>
+
+/* Should make sure there is no false sharing on this. */
+
+struct elision_config
+{
+ int skip_lock_busy;
+ int skip_lock_internal_abort;
+ int retry_try_xbegin;
+ int skip_trylock_internal_abort;
+};
+
+extern struct elision_config __elision_aconf attribute_hidden;
+
+extern int __pthread_force_elision attribute_hidden;
+
+/* Tell the test suite to test elision for this architecture. */
+#define HAVE_ELISION 1
+
+#endif
diff --git a/nptl_2_17/elision-lock_2_17.c b/nptl_2_17/elision-lock_2_17.c
new file mode 100644
index 00000000..6eebde8a
--- /dev/null
+++ b/nptl_2_17/elision-lock_2_17.c
@@ -0,0 +1,107 @@
+/* elision-lock.c: Elided pthread mutex lock.
+ Copyright (C) 2011-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread_2_17.h>
+#include "pthreadP_2_17.h"
+#include "lowlevellock_2_17.h"
+#include "hle_2_17.h"
+#include <elision-conf_2_17.h>
+
+#if !defined(LLL_LOCK) && !defined(EXTRAARG)
+/* Make sure the configuration code is always linked in for static
+ libraries. */
+#include "elision-conf_2_17.c"
+#endif
+
+#ifndef EXTRAARG
+#define EXTRAARG
+#endif
+#ifndef LLL_LOCK
+#define LLL_LOCK(a,b) lll_lock(a,b), 0
+#endif
+
+#define aconf __elision_aconf
+
+/* Adaptive lock using transactions.
+ By default the lock region is run as a transaction, and when it
+ aborts or the lock is busy the lock adapts itself. */
+
+int
+__lll_lock_elision (int *futex, short *adapt_count, EXTRAARG int private)
+{
+ /* adapt_count can be accessed concurrently; these accesses can be both
+ inside of transactions (if critical sections are nested and the outer
+ critical section uses lock elision) and outside of transactions. Thus,
+ we need to use atomic accesses to avoid data races. However, the
+ value of adapt_count is just a hint, so relaxed MO accesses are
+ sufficient. */
+ if (atomic_load_relaxed (adapt_count) <= 0)
+ {
+ unsigned status;
+ int try_xbegin;
+
+ for (try_xbegin = aconf.retry_try_xbegin;
+ try_xbegin > 0;
+ try_xbegin--)
+ {
+ if ((status = _xbegin()) == _XBEGIN_STARTED)
+ {
+ if (*futex == 0)
+ return 0;
+
+ /* Lock was busy. Fall back to normal locking.
+ Could also _xend here but xabort with 0xff code
+ is more visible in the profiler. */
+ _xabort (_ABORT_LOCK_BUSY);
+ }
+
+ if (!(status & _XABORT_RETRY))
+ {
+ if ((status & _XABORT_EXPLICIT)
+ && _XABORT_CODE (status) == _ABORT_LOCK_BUSY)
+ {
+ /* Right now we skip here. Better would be to wait a bit
+ and retry. This likely needs some spinning. See
+ above for why relaxed MO is sufficient. */
+ if (atomic_load_relaxed (adapt_count)
+ != aconf.skip_lock_busy)
+ atomic_store_relaxed (adapt_count, aconf.skip_lock_busy);
+ }
+ /* Internal abort. There is no chance for retry.
+ Use the normal locking and next time use lock.
+ Be careful to avoid writing to the lock. See above for why
+ relaxed MO is sufficient. */
+ else if (atomic_load_relaxed (adapt_count)
+ != aconf.skip_lock_internal_abort)
+ atomic_store_relaxed (adapt_count,
+ aconf.skip_lock_internal_abort);
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* Use a normal lock until the threshold counter runs out.
+ Lost updates possible. */
+ atomic_store_relaxed (adapt_count,
+ atomic_load_relaxed (adapt_count) - 1);
+ }
+
+ /* Use a normal lock here. */
+ return LLL_LOCK ((*futex), private);
+}
diff --git a/nptl_2_17/elision-timed_2_17.c b/nptl_2_17/elision-timed_2_17.c
new file mode 100644
index 00000000..b103f9aa
--- /dev/null
+++ b/nptl_2_17/elision-timed_2_17.c
@@ -0,0 +1,26 @@
+/* elision-timed.c: Lock elision timed lock.
+ Copyright (C) 2013-2018 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 <time.h>
+#include <elision-conf_2_17.h>
+#include "lowlevellock_2_17.h"
+#define __lll_lock_elision __lll_timedlock_elision
+#define EXTRAARG const struct timespec *t,
+#undef LLL_LOCK
+#define LLL_LOCK(a, b) lll_timedlock(a, t, b)
+#include "elision-lock_2_17.c"
diff --git a/nptl_2_17/elision-trylock_2_17.c b/nptl_2_17/elision-trylock_2_17.c
new file mode 100644
index 00000000..8ed92198
--- /dev/null
+++ b/nptl_2_17/elision-trylock_2_17.c
@@ -0,0 +1,75 @@
+/* elision-trylock.c: Lock eliding trylock for pthreads.
+ Copyright (C) 2013-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread_2_17.h>
+#include <pthreadP_2_17.h>
+#include <lowlevellock_2_17.h>
+#include "hle_2_17.h"
+#include <elision-conf_2_17.h>
+
+#define aconf __elision_aconf
+
+/* Try to elide a futex trylock. FUTEX is the futex variable. ADAPT_COUNT is
+ the adaptation counter in the mutex. */
+
+int
+__lll_trylock_elision (int *futex, short *adapt_count)
+{
+ /* Implement POSIX semantics by forbiding nesting
+ trylock. Sorry. After the abort the code is re-executed
+ non transactional and if the lock was already locked
+ return an error. */
+ _xabort (_ABORT_NESTED_TRYLOCK);
+
+ /* Only try a transaction if it's worth it. See __lll_lock_elision for
+ why we need atomic accesses. Relaxed MO is sufficient because this is
+ just a hint. */
+ if (atomic_load_relaxed (adapt_count) <= 0)
+ {
+ unsigned status;
+
+ if ((status = _xbegin()) == _XBEGIN_STARTED)
+ {
+ if (*futex == 0)
+ return 0;
+
+ /* Lock was busy. Fall back to normal locking.
+ Could also _xend here but xabort with 0xff code
+ is more visible in the profiler. */
+ _xabort (_ABORT_LOCK_BUSY);
+ }
+
+ if (!(status & _XABORT_RETRY))
+ {
+ /* Internal abort. No chance for retry. For future
+ locks don't try speculation for some time. See above for MO. */
+ if (atomic_load_relaxed (adapt_count)
+ != aconf.skip_lock_internal_abort)
+ atomic_store_relaxed (adapt_count, aconf.skip_lock_internal_abort);
+ }
+ /* Could do some retries here. */
+ }
+ else
+ {
+ /* Lost updates are possible but harmless (see above). */
+ atomic_store_relaxed (adapt_count,
+ atomic_load_relaxed (adapt_count) - 1);
+ }
+
+ return lll_trylock (*futex);
+}
diff --git a/nptl_2_17/elision-unlock_2_17.c b/nptl_2_17/elision-unlock_2_17.c
new file mode 100644
index 00000000..20b658a8
--- /dev/null
+++ b/nptl_2_17/elision-unlock_2_17.c
@@ -0,0 +1,33 @@
+/* elision-unlock.c: Commit an elided pthread lock.
+ Copyright (C) 2013-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP_2_17.h"
+#include "lowlevellock_2_17.h"
+#include "hle_2_17.h"
+
+int
+__lll_unlock_elision(int *lock, int private)
+{
+ /* When the lock was free we're in a transaction.
+ When you crash here you unlocked a free lock. */
+ if (*lock == 0)
+ _xend();
+ else
+ lll_unlock ((*lock), private);
+ return 0;
+}
diff --git a/nptl_2_17/futex-internal_2_17.h b/nptl_2_17/futex-internal_2_17.h
new file mode 100644
index 00000000..b0512da0
--- /dev/null
+++ b/nptl_2_17/futex-internal_2_17.h
@@ -0,0 +1,263 @@
+/* futex operations for glibc-internal use. Linux version.
+ Copyright (C) 2014-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef FUTEX_INTERNAL_H
+#define FUTEX_INTERNAL_H
+
+#include <sysdeps/nptl/futex-internal_2_17.h>
+#include <errno.h>
+#include <lowlevellock-futex_2_17.h>
+#include <pthreadP_2_17.h>
+
+/* See sysdeps/nptl/futex-internal.h for documentation; this file only
+ contains Linux-specific comments.
+
+ The Linux kernel treats provides absolute timeouts based on the
+ CLOCK_REALTIME clock and relative timeouts measured against the
+ CLOCK_MONOTONIC clock.
+
+ We expect a Linux kernel version of 2.6.22 or more recent (since this
+ version, EINTR is not returned on spurious wake-ups anymore). */
+
+/* FUTEX_SHARED is always supported by the Linux kernel. */
+static __always_inline int
+futex_supports_pshared (int pshared)
+{
+ if (__glibc_likely (pshared == PTHREAD_PROCESS_PRIVATE))
+ return 0;
+ else if (pshared == PTHREAD_PROCESS_SHARED)
+ return 0;
+ else
+ return EINVAL;
+}
+
+/* The Linux kernel supports relative timeouts measured against the
+ CLOCK_MONOTONIC clock. */
+static __always_inline bool
+futex_supports_exact_relative_timeouts (void)
+{
+ return true;
+}
+
+/* See sysdeps/nptl/futex-internal.h for details. */
+static __always_inline int
+futex_wait (unsigned int *futex_word, unsigned int expected, int private)
+{
+ int err = lll_futex_timed_wait (futex_word, expected, NULL, private);
+ switch (err)
+ {
+ case 0:
+ case -EAGAIN:
+ case -EINTR:
+ return -err;
+
+ case -ETIMEDOUT: /* Cannot have happened as we provided no timeout. */
+ case -EFAULT: /* Must have been caused by a glibc or application bug. */
+ case -EINVAL: /* Either due to wrong alignment or due to the timeout not
+ being normalized. Must have been caused by a glibc or
+ application bug. */
+ case -ENOSYS: /* Must have been caused by a glibc bug. */
+ /* No other errors are documented at this time. */
+ default:
+ futex_fatal_error ();
+ }
+}
+
+/* See sysdeps/nptl/futex-internal.h for details. */
+static __always_inline int
+futex_wait_cancelable (unsigned int *futex_word, unsigned int expected,
+ int private)
+{
+ int oldtype;
+ oldtype = __pthread_enable_asynccancel ();
+ int err = lll_futex_timed_wait (futex_word, expected, NULL, private);
+ __pthread_disable_asynccancel (oldtype);
+ switch (err)
+ {
+ case 0:
+ case -EAGAIN:
+ case -EINTR:
+ return -err;
+
+ case -ETIMEDOUT: /* Cannot have happened as we provided no timeout. */
+ case -EFAULT: /* Must have been caused by a glibc or application bug. */
+ case -EINVAL: /* Either due to wrong alignment or due to the timeout not
+ being normalized. Must have been caused by a glibc or
+ application bug. */
+ case -ENOSYS: /* Must have been caused by a glibc bug. */
+ /* No other errors are documented at this time. */
+ default:
+ futex_fatal_error ();
+ }
+}
+
+/* See sysdeps/nptl/futex-internal.h for details. */
+static __always_inline int
+futex_reltimed_wait (unsigned int *futex_word, unsigned int expected,
+ const struct timespec *reltime, int private)
+{
+ int err = lll_futex_timed_wait (futex_word, expected, reltime, private);
+ switch (err)
+ {
+ case 0:
+ case -EAGAIN:
+ case -EINTR:
+ case -ETIMEDOUT:
+ return -err;
+
+ case -EFAULT: /* Must have been caused by a glibc or application bug. */
+ case -EINVAL: /* Either due to wrong alignment or due to the timeout not
+ being normalized. Must have been caused by a glibc or
+ application bug. */
+ case -ENOSYS: /* Must have been caused by a glibc bug. */
+ /* No other errors are documented at this time. */
+ default:
+ futex_fatal_error ();
+ }
+}
+
+/* See sysdeps/nptl/futex-internal.h for details. */
+static __always_inline int
+futex_reltimed_wait_cancelable (unsigned int *futex_word,
+ unsigned int expected,
+ const struct timespec *reltime, int private)
+{
+ int oldtype;
+ oldtype = __pthread_enable_asynccancel ();
+ int err = lll_futex_timed_wait (futex_word, expected, reltime, private);
+ __pthread_disable_asynccancel (oldtype);
+ switch (err)
+ {
+ case 0:
+ case -EAGAIN:
+ case -EINTR:
+ case -ETIMEDOUT:
+ return -err;
+
+ case -EFAULT: /* Must have been caused by a glibc or application bug. */
+ case -EINVAL: /* Either due to wrong alignment or due to the timeout not
+ being normalized. Must have been caused by a glibc or
+ application bug. */
+ case -ENOSYS: /* Must have been caused by a glibc bug. */
+ /* No other errors are documented at this time. */
+ default:
+ futex_fatal_error ();
+ }
+}
+
+/* See sysdeps/nptl/futex-internal.h for details. */
+static __always_inline int
+futex_abstimed_supported_clockid (clockid_t clockid)
+{
+ return lll_futex_supported_clockid (clockid);
+}
+
+/* See sysdeps/nptl/futex-internal.h for details. */
+static __always_inline int
+futex_abstimed_wait (unsigned int *futex_word, unsigned int expected,
+ clockid_t clockid,
+ const struct timespec *abstime, int private)
+{
+ /* Work around the fact that the kernel rejects negative timeout values
+ despite them being valid. */
+ if (__glibc_unlikely ((abstime != NULL) && (abstime->tv_sec < 0)))
+ return ETIMEDOUT;
+ int err = lll_futex_clock_wait_bitset (futex_word, expected,
+ clockid, abstime,
+ private);
+ switch (err)
+ {
+ case 0:
+ case -EAGAIN:
+ case -EINTR:
+ case -ETIMEDOUT:
+ return -err;
+
+ case -EFAULT: /* Must have been caused by a glibc or application bug. */
+ case -EINVAL: /* Either due to wrong alignment, unsupported
+ clockid or due to the timeout not being
+ normalized. Must have been caused by a glibc or
+ application bug. */
+ case -ENOSYS: /* Must have been caused by a glibc bug. */
+ /* No other errors are documented at this time. */
+ default:
+ futex_fatal_error ();
+ }
+}
+
+/* See sysdeps/nptl/futex-internal.h for details. */
+static __always_inline int
+futex_abstimed_wait_cancelable (unsigned int *futex_word,
+ unsigned int expected,
+ clockid_t clockid,
+ const struct timespec *abstime, int private)
+{
+ /* Work around the fact that the kernel rejects negative timeout values
+ despite them being valid. */
+ if (__glibc_unlikely ((abstime != NULL) && (abstime->tv_sec < 0)))
+ return ETIMEDOUT;
+ int oldtype;
+ oldtype = __pthread_enable_asynccancel ();
+ int err = lll_futex_clock_wait_bitset (futex_word, expected,
+ clockid, abstime,
+ private);
+ __pthread_disable_asynccancel (oldtype);
+ switch (err)
+ {
+ case 0:
+ case -EAGAIN:
+ case -EINTR:
+ case -ETIMEDOUT:
+ return -err;
+
+ case -EFAULT: /* Must have been caused by a glibc or application bug. */
+ case -EINVAL: /* Either due to wrong alignment or due to the timeout not
+ being normalized. Must have been caused by a glibc or
+ application bug. */
+ case -ENOSYS: /* Must have been caused by a glibc bug. */
+ /* No other errors are documented at this time. */
+ default:
+ futex_fatal_error ();
+ }
+}
+
+/* See sysdeps/nptl/futex-internal.h for details. */
+static __always_inline void
+futex_wake (unsigned int *futex_word, int processes_to_wake, int private)
+{
+ int res = lll_futex_wake (futex_word, processes_to_wake, private);
+ /* No error. Ignore the number of woken processes. */
+ if (res >= 0)
+ return;
+ switch (res)
+ {
+ case -EFAULT: /* Could have happened due to memory reuse. */
+ case -EINVAL: /* Could be either due to incorrect alignment (a bug in
+ glibc or in the application) or due to memory being
+ reused for a PI futex. We cannot distinguish between the
+ two causes, and one of them is correct use, so we do not
+ act in this case. */
+ return;
+ case -ENOSYS: /* Must have been caused by a glibc bug. */
+ /* No other errors are documented at this time. */
+ default:
+ futex_fatal_error ();
+ }
+}
+
+#endif /* futex-internal.h */
diff --git a/nptl_2_17/hle_2_17.h b/nptl_2_17/hle_2_17.h
new file mode 100644
index 00000000..4a7b9e3b
--- /dev/null
+++ b/nptl_2_17/hle_2_17.h
@@ -0,0 +1,75 @@
+/* Shared RTM header. Emulate TSX intrinsics for compilers and assemblers
+ that do not support the intrinsics and instructions yet. */
+#ifndef _HLE_H
+#define _HLE_H 1
+
+#ifdef __ASSEMBLER__
+
+.macro XBEGIN target
+ .byte 0xc7,0xf8
+ .long \target-1f
+1:
+.endm
+
+.macro XEND
+ .byte 0x0f,0x01,0xd5
+.endm
+
+.macro XABORT code
+ .byte 0xc6,0xf8,\code
+.endm
+
+.macro XTEST
+ .byte 0x0f,0x01,0xd6
+.endm
+
+#endif
+
+/* Official RTM intrinsics interface matching gcc/icc, but works
+ on older gcc compatible compilers and binutils.
+ We should somehow detect if the compiler supports it, because
+ it may be able to generate slightly better code. */
+
+#define _XBEGIN_STARTED (~0u)
+#define _XABORT_EXPLICIT (1 << 0)
+#define _XABORT_RETRY (1 << 1)
+#define _XABORT_CONFLICT (1 << 2)
+#define _XABORT_CAPACITY (1 << 3)
+#define _XABORT_DEBUG (1 << 4)
+#define _XABORT_NESTED (1 << 5)
+#define _XABORT_CODE(x) (((x) >> 24) & 0xff)
+
+#define _ABORT_LOCK_BUSY 0xff
+#define _ABORT_LOCK_IS_LOCKED 0xfe
+#define _ABORT_NESTED_TRYLOCK 0xfd
+
+#ifndef __ASSEMBLER__
+
+#define __force_inline __attribute__((__always_inline__)) inline
+
+static __force_inline int _xbegin(void)
+{
+ int ret = _XBEGIN_STARTED;
+ asm volatile (".byte 0xc7,0xf8 ; .long 0" : "+a" (ret) :: "memory");
+ return ret;
+}
+
+static __force_inline void _xend(void)
+{
+ asm volatile (".byte 0x0f,0x01,0xd5" ::: "memory");
+}
+
+static __force_inline void _xabort(const unsigned int status)
+{
+ asm volatile (".byte 0xc6,0xf8,%P0" :: "i" (status) : "memory");
+}
+
+static __force_inline int _xtest(void)
+{
+ unsigned char out;
+ asm volatile (".byte 0x0f,0x01,0xd6 ; setnz %0" : "=r" (out) :: "memory");
+ return out;
+}
+
+#endif
+#endif
diff --git a/nptl_2_17/internaltypes_2_17.h b/nptl_2_17/internaltypes_2_17.h
new file mode 100644
index 00000000..603dc01c
--- /dev/null
+++ b/nptl_2_17/internaltypes_2_17.h
@@ -0,0 +1,179 @@
+/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have 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>
+#include <atomic.h>
+#include <endian.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-COND_CLOCK_BITS: Clock ID. COND_CLOCK_BITS is the number of bits
+ needed to represent the ID of the clock. */
+ int value;
+};
+#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. See pthread_barrier_wait for a description
+ of how these fields are used. */
+struct pthread_barrier
+{
+ unsigned int in;
+ unsigned int current_round;
+ unsigned int count;
+ int shared;
+ unsigned int out;
+};
+/* See pthread_barrier_wait for a description. */
+#define BARRIER_IN_THRESHOLD (UINT_MAX/2)
+
+
+/* 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
+{
+#if __HAVE_64B_ATOMICS
+ /* The data field holds both value (in the least-significant 32 bits) and
+ nwaiters. */
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+# define SEM_VALUE_OFFSET 0
+# elif __BYTE_ORDER == __BIG_ENDIAN
+# define SEM_VALUE_OFFSET 1
+# else
+# error Unsupported byte order.
+# endif
+# define SEM_NWAITERS_SHIFT 32
+# define SEM_VALUE_MASK (~(unsigned int)0)
+ uint64_t data;
+ int private;
+ int pad;
+#else
+# define SEM_VALUE_SHIFT 1
+# define SEM_NWAITERS_MASK ((unsigned int)1)
+ unsigned int value;
+ int private;
+ int pad;
+ unsigned int nwaiters;
+#endif
+};
+
+struct old_sem
+{
+ unsigned int value;
+};
+
+
+/* Compatibility type for old conditional variable interfaces. */
+typedef struct
+{
+ pthread_cond_t *cond;
+} pthread_cond_2_0_t;
+
+#endif /* internaltypes.h */
diff --git a/nptl_2_17/kernel-features_2_17.h b/nptl_2_17/kernel-features_2_17.h
new file mode 100644
index 00000000..299ae0a1
--- /dev/null
+++ b/nptl_2_17/kernel-features_2_17.h
@@ -0,0 +1,162 @@
+/* Set flags signalling availability of kernel features based on given
+ kernel version number.
+ Copyright (C) 1999-2018 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/>. */
+
+/* This file must not contain any C code. At least it must be protected
+ to allow using the file also in assembler files. */
+
+#ifndef __LINUX_KERNEL_VERSION_2_17
+/* We assume the worst; all kernels should be supported. */
+# define __LINUX_KERNEL_VERSION_2_17 0
+#endif
+
+/* We assume for __LINUX_KERNEL_VERSION the same encoding used in
+ linux/version.h. I.e., the major, minor, and subminor all get a
+ byte with the major number being in the highest byte. This means
+ we can do numeric comparisons.
+
+ In the following we will define certain symbols depending on
+ whether the describes kernel feature is available in the kernel
+ version given by __LINUX_KERNEL_VERSION. We are not always exactly
+ recording the correct versions in which the features were
+ introduced. If somebody cares these values can afterwards be
+ corrected. */
+
+/* Some architectures use the socketcall multiplexer for some or all
+ socket-related operations instead of separate syscalls.
+ __ASSUME_SOCKETCALL is defined for such architectures. */
+
+/* The changed st_ino field appeared in 2.4.0-test6. However, SH is lame,
+ and still does not have a 64-bit inode field. */
+#define __ASSUME_ST_INO_64_BIT 1
+
+/* The statfs64 syscalls are available in 2.5.74 (but not for alpha). */
+#define __ASSUME_STATFS64 1
+
+/* pselect/ppoll were introduced just after 2.6.16-rc1. On x86_64 and
+ SH this appeared first in 2.6.19-rc1, on ia64 in 2.6.22-rc1. */
+#define __ASSUME_PSELECT 1
+
+/* The *at syscalls were introduced just after 2.6.16-rc1. On PPC
+ they were introduced in 2.6.17-rc1, on SH in 2.6.19-rc1. */
+#define __ASSUME_ATFCTS 1
+
+/* Support for inter-process robust mutexes was added in 2.6.17 (but
+ some architectures lack futex_atomic_cmpxchg_inatomic in some
+ configurations). */
+#define __ASSUME_SET_ROBUST_LIST 1
+
+/* Support for various CLOEXEC and NONBLOCK flags was added in
+ 2.6.27. */
+#define __ASSUME_IN_NONBLOCK 1
+
+/* Support for the FUTEX_CLOCK_REALTIME flag was added in 2.6.29. */
+#define __ASSUME_FUTEX_CLOCK_REALTIME 1
+
+/* Support for preadv and pwritev was added in 2.6.30. */
+#define __ASSUME_PREADV 1
+#define __ASSUME_PWRITEV 1
+
+
+/* Support for FUTEX_*_REQUEUE_PI was added in 2.6.31 (but some
+ * architectures lack futex_atomic_cmpxchg_inatomic in some
+ * configurations). */
+#define __ASSUME_REQUEUE_PI 1
+
+/* Support for sendmmsg functionality was added in 3.0. */
+#define __ASSUME_SENDMMSG 1
+
+/* On most architectures, most socket syscalls are supported for all
+ supported kernel versions, but on some socketcall architectures
+ separate syscalls were only added later. */
+#define __ASSUME_SENDMSG_SYSCALL 1
+#define __ASSUME_RECVMSG_SYSCALL 1
+#define __ASSUME_ACCEPT_SYSCALL 1
+#define __ASSUME_CONNECT_SYSCALL 1
+#define __ASSUME_RECVFROM_SYSCALL 1
+#define __ASSUME_SENDTO_SYSCALL 1
+#define __ASSUME_ACCEPT4_SYSCALL 1
+#define __ASSUME_RECVMMSG_SYSCALL 1
+#define __ASSUME_SENDMMSG_SYSCALL 1
+
+/* Support for SysV IPC through wired syscalls. All supported architectures
+ either support ipc syscall and/or all the ipc correspondent syscalls. */
+#define __ASSUME_DIRECT_SYSVIPC_SYSCALLS 1
+
+/* Support for p{read,write}v2 was added in 4.6. However Linux default
+ implementation does not assume the __ASSUME_* and instead use a fallback
+ implementation based on p{read,write}v and returning an error for
+ non supported flags. */
+
+/* Support for the renameat2 system call was added in kernel 3.15. */
+#if __LINUX_KERNEL_VERSION >= 0x030F00
+# define __ASSUME_RENAMEAT2
+#endif
+
+/* Support for the execveat syscall was added in 3.19. */
+#if __LINUX_KERNEL_VERSION >= 0x031300
+# define __ASSUME_EXECVEAT 1
+#endif
+
+#if __LINUX_KERNEL_VERSION >= 0x040400
+# define __ASSUME_MLOCK2 1
+#endif
+
+#if __LINUX_KERNEL_VERSION >= 0x040500
+# define __ASSUME_COPY_FILE_RANGE 1
+#endif
+
+/* Support for statx was added in kernel 4.11. */
+#if __LINUX_KERNEL_VERSION >= 0x040B00
+# define __ASSUME_STATX 1
+#endif
+
+/* Support for clone call used on fork. The signature varies across the
+ architectures with current 4 different variants:
+
+ 1. long int clone (unsigned long flags, unsigned long newsp,
+ int *parent_tidptr, unsigned long tls,
+ int *child_tidptr)
+
+ 2. long int clone (unsigned long newsp, unsigned long clone_flags,
+ int *parent_tidptr, int * child_tidptr,
+ unsigned long tls)
+
+ 3. long int clone (unsigned long flags, unsigned long newsp,
+ int stack_size, int *parent_tidptr,
+ int *child_tidptr, unsigned long tls)
+
+ 4. long int clone (unsigned long flags, unsigned long newsp,
+ int *parent_tidptr, int *child_tidptr,
+ unsigned long tls)
+
+ The fourth variant is intended to be used as the default for newer ports,
+ Also IA64 uses the third variant but with __NR_clone2 instead of
+ __NR_clone.
+
+ The macros names to define the variant used for the architecture is
+ similar to kernel:
+
+ - __ASSUME_CLONE_BACKWARDS: for variant 1.
+ - __ASSUME_CLONE_BACKWARDS2: for variant 2 (s390).
+ - __ASSUME_CLONE_BACKWARDS3: for variant 3 (microblaze).
+ - __ASSUME_CLONE_DEFAULT: for variant 4.
+ - __ASSUME_CLONE2: for clone2 with variant 3 (ia64).
+ */
+
+#define __ASSUME_CLONE_DEFAULT 1
diff --git a/nptl_2_17/libpthread-2.17-aarch64.map b/nptl_2_17/libpthread-2.17-aarch64.map
new file mode 100644
index 00000000..d970af06
--- /dev/null
+++ b/nptl_2_17/libpthread-2.17-aarch64.map
@@ -0,0 +1,8 @@
+GLIBC_2.17 {
+ global:
+ pthread_cond_init; pthread_cond_destroy;
+ pthread_cond_signal; pthread_cond_broadcast;
+ pthread_cond_wait; pthread_cond_timedwait;
+ local:
+ *;
+};
diff --git a/nptl_2_17/libpthread-2.17-x86_64.map b/nptl_2_17/libpthread-2.17-x86_64.map
new file mode 100644
index 00000000..d7f23322
--- /dev/null
+++ b/nptl_2_17/libpthread-2.17-x86_64.map
@@ -0,0 +1,8 @@
+GLIBC_2.3.2 {
+ global:
+ pthread_cond_init; pthread_cond_destroy;
+ pthread_cond_signal; pthread_cond_broadcast;
+ pthread_cond_wait; pthread_cond_timedwait;
+ local:
+ *;
+};
diff --git a/nptl_2_17/lll_timedlock_wait_2_17.c b/nptl_2_17/lll_timedlock_wait_2_17.c
new file mode 100644
index 00000000..45ca994e
--- /dev/null
+++ b/nptl_2_17/lll_timedlock_wait_2_17.c
@@ -0,0 +1,59 @@
+/* Timed low level locking for pthread library. Generic futex-using version.
+ Copyright (C) 2003-2018 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 <atomic.h>
+#include <errno.h>
+#include <lowlevellock_2_17.h>
+#include <sys/time.h>
+
+
+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;
+
+ /* If *futex == 2, wait until woken or timeout. */
+ lll_futex_timed_wait (futex, 2, &rt, private);
+ }
+
+ return 0;
+}
diff --git a/nptl_2_17/lowlevellock_2_17.c b/nptl_2_17/lowlevellock_2_17.c
new file mode 100644
index 00000000..9bbcc924
--- /dev/null
+++ b/nptl_2_17/lowlevellock_2_17.c
@@ -0,0 +1,46 @@
+/* low level locking for pthread library. Generic futex-using version.
+ Copyright (C) 2003-2018 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_2_17.h>
+#include <lowlevellock_2_17.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); /* Wait if *futex == 2. */
+
+ while (atomic_exchange_acq (futex, 2) != 0)
+ lll_futex_wait (futex, 2, LLL_PRIVATE); /* Wait if *futex == 2. */
+}
+
+
+/* This function doesn't get included in libc. */
+void
+__lll_lock_wait (int *futex, int private)
+{
+ if (*futex == 2)
+ lll_futex_wait (futex, 2, private); /* Wait if *futex == 2. */
+
+ while (atomic_exchange_acq (futex, 2) != 0)
+ lll_futex_wait (futex, 2, private); /* Wait if *futex == 2. */
+}
diff --git a/nptl_2_17/pthread-functions_2_17.h b/nptl_2_17/pthread-functions_2_17.h
new file mode 100644
index 00000000..9e2a79f5
--- /dev/null
+++ b/nptl_2_17/pthread-functions_2_17.h
@@ -0,0 +1,116 @@
+/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _PTHREAD_FUNCTIONS_H
+#define _PTHREAD_FUNCTIONS_H 1
+
+#include <pthread_2_17.h>
+#include <internaltypes_2_17.h>
+#include <sysdep_2_17.h>
+#include <setjmp.h>
+
+struct xid_command;
+
+/* Data type shared with libc. The libc uses it to pass on calls to
+ the thread functions. */
+struct pthread_functions
+{
+ int (*ptr_pthread_attr_destroy) (pthread_attr_t *);
+ int (*ptr___pthread_attr_init_2_0) (pthread_attr_t *);
+ int (*ptr___pthread_attr_init_2_1) (pthread_attr_t *);
+ int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *);
+ int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int);
+ int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *);
+ int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int);
+ int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *,
+ struct sched_param *);
+ int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *,
+ const struct sched_param *);
+ int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *);
+ int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int);
+ int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *);
+ int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int);
+ int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *);
+ int (*ptr_pthread_condattr_init) (pthread_condattr_t *);
+ int (*ptr___pthread_cond_broadcast) (pthread_cond_t *);
+ int (*ptr___pthread_cond_destroy) (pthread_cond_t *);
+ int (*ptr___pthread_cond_init) (pthread_cond_t *,
+ const pthread_condattr_t *);
+
+ int (*ptr___pthread_cond_signal) (pthread_cond_t *);
+ int (*ptr___pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *);
+ int (*ptr___pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *,
+ const struct timespec *);
+ int (*ptr___pthread_cond_broadcast_2_0) (pthread_cond_2_0_t *);
+ int (*ptr___pthread_cond_destroy_2_0) (pthread_cond_2_0_t *);
+ int (*ptr___pthread_cond_init_2_0) (pthread_cond_2_0_t *,
+ const pthread_condattr_t *);
+ int (*ptr___pthread_cond_signal_2_0) (pthread_cond_2_0_t *);
+ int (*ptr___pthread_cond_wait_2_0) (pthread_cond_2_0_t *, pthread_mutex_t *);
+ int (*ptr___pthread_cond_timedwait_2_0) (pthread_cond_2_0_t *,
+ pthread_mutex_t *,
+ const struct timespec *);
+ int (*ptr_pthread_equal) (pthread_t, pthread_t);
+ void (*ptr___pthread_exit) (void *) __attribute__ ((__noreturn__));
+ int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *);
+ int (*ptr_pthread_setschedparam) (pthread_t, int,
+ const struct sched_param *);
+ int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *);
+ int (*ptr_pthread_mutex_init) (pthread_mutex_t *,
+ const pthread_mutexattr_t *);
+ int (*ptr_pthread_mutex_lock) (pthread_mutex_t *);
+ int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *);
+ int (*ptr___pthread_setcancelstate) (int, int *);
+ int (*ptr_pthread_setcanceltype) (int, int *);
+ void (*ptr___pthread_cleanup_upto) (__jmp_buf, char *);
+ int (*ptr___pthread_once) (pthread_once_t *, void (*) (void));
+ int (*ptr___pthread_rwlock_rdlock) (pthread_rwlock_t *);
+ int (*ptr___pthread_rwlock_wrlock) (pthread_rwlock_t *);
+ int (*ptr___pthread_rwlock_unlock) (pthread_rwlock_t *);
+ int (*ptr___pthread_key_create) (pthread_key_t *, void (*) (void *));
+ void *(*ptr___pthread_getspecific) (pthread_key_t);
+ int (*ptr___pthread_setspecific) (pthread_key_t, const void *);
+ void (*ptr__pthread_cleanup_push_defer) (struct _pthread_cleanup_buffer *,
+ void (*) (void *), void *);
+ void (*ptr__pthread_cleanup_pop_restore) (struct _pthread_cleanup_buffer *,
+ int);
+#define HAVE_PTR_NTHREADS
+ unsigned int *ptr_nthreads;
+ void (*ptr___pthread_unwind) (__pthread_unwind_buf_t *)
+ __attribute ((noreturn)) __cleanup_fct_attribute;
+ void (*ptr__nptl_deallocate_tsd) (void);
+ int (*ptr__nptl_setxid) (struct xid_command *);
+ void (*ptr_set_robust) (struct pthread *);
+};
+
+/* Variable in libc.so. */
+extern struct pthread_functions __libc_pthread_functions attribute_hidden;
+extern int __libc_pthread_functions_init attribute_hidden;
+
+#ifdef PTR_DEMANGLE
+# define PTHFCT_CALL(fct, params) \
+ ({ __typeof (__libc_pthread_functions.fct) __p; \
+ __p = __libc_pthread_functions.fct; \
+ PTR_DEMANGLE (__p); \
+ __p params; })
+#else
+# define PTHFCT_CALL(fct, params) \
+ __libc_pthread_functions.fct params
+#endif
+
+#endif /* pthread-functions.h */
diff --git a/nptl_2_17/pthreadP_2_17.h b/nptl_2_17/pthreadP_2_17.h
new file mode 100644
index 00000000..ee1488c0
--- /dev/null
+++ b/nptl_2_17/pthreadP_2_17.h
@@ -0,0 +1,714 @@
+/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _PTHREADP_H
+#define _PTHREADP_H 1
+
+#include "kernel-features_2_17.h"
+#include "pthread_2_17.h"
+#include <sysdep_2_17.h>
+#include "internaltypes_2_17.h"
+#include <pthread-functions_2_17.h>
+#include "descr_2_17.h"
+#include <lowlevellock_2_17.h>
+
+#include <setjmp.h>
+#include <stdbool.h>
+#include <sys/syscall.h>
+#include <tls.h>
+#include <stackinfo.h>
+#include <atomic.h>
+#include <errno.h>
+
+
+/* Atomic operations on TLS memory. */
+#ifndef THREAD_ATOMIC_CMPXCHG_VAL
+# define THREAD_ATOMIC_CMPXCHG_VAL(descr, member, new, old) \
+ atomic_compare_and_exchange_val_acq (&(descr)->member, new, old)
+#endif
+
+#ifndef THREAD_ATOMIC_BIT_SET
+# define THREAD_ATOMIC_BIT_SET(descr, member, bit) \
+ atomic_bit_set (&(descr)->member, bit)
+#endif
+
+
+/* Adaptive mutex definitions. */
+#ifndef MAX_ADAPTIVE_COUNT
+# define MAX_ADAPTIVE_COUNT 100
+#endif
+
+
+/* Magic cookie representing robust mutex with dead owner. */
+#define PTHREAD_MUTEX_INCONSISTENT INT_MAX
+/* Magic cookie representing not recoverable robust mutex. */
+#define PTHREAD_MUTEX_NOTRECOVERABLE (INT_MAX - 1)
+
+
+/* Internal mutex type value. */
+enum
+{
+ PTHREAD_MUTEX_KIND_MASK_NP = 3,
+
+ PTHREAD_MUTEX_ELISION_NP = 256,
+ PTHREAD_MUTEX_NO_ELISION_NP = 512,
+
+ PTHREAD_MUTEX_ROBUST_NORMAL_NP = 16,
+ PTHREAD_MUTEX_ROBUST_RECURSIVE_NP
+ = PTHREAD_MUTEX_ROBUST_NORMAL_NP | PTHREAD_MUTEX_RECURSIVE_NP,
+ PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP
+ = PTHREAD_MUTEX_ROBUST_NORMAL_NP | PTHREAD_MUTEX_ERRORCHECK_NP,
+ PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP
+ = PTHREAD_MUTEX_ROBUST_NORMAL_NP | PTHREAD_MUTEX_ADAPTIVE_NP,
+ PTHREAD_MUTEX_PRIO_INHERIT_NP = 32,
+ PTHREAD_MUTEX_PI_NORMAL_NP
+ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_NORMAL,
+ PTHREAD_MUTEX_PI_RECURSIVE_NP
+ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_RECURSIVE_NP,
+ PTHREAD_MUTEX_PI_ERRORCHECK_NP
+ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ERRORCHECK_NP,
+ PTHREAD_MUTEX_PI_ADAPTIVE_NP
+ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ADAPTIVE_NP,
+ PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP
+ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_NORMAL_NP,
+ PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP
+ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_RECURSIVE_NP,
+ PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP
+ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP,
+ PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP
+ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP,
+ PTHREAD_MUTEX_PRIO_PROTECT_NP = 64,
+ PTHREAD_MUTEX_PP_NORMAL_NP
+ = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_NORMAL,
+ PTHREAD_MUTEX_PP_RECURSIVE_NP
+ = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_RECURSIVE_NP,
+ PTHREAD_MUTEX_PP_ERRORCHECK_NP
+ = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_ERRORCHECK_NP,
+ PTHREAD_MUTEX_PP_ADAPTIVE_NP
+ = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_ADAPTIVE_NP,
+ PTHREAD_MUTEX_ELISION_FLAGS_NP
+ = PTHREAD_MUTEX_ELISION_NP | PTHREAD_MUTEX_NO_ELISION_NP,
+
+ PTHREAD_MUTEX_TIMED_ELISION_NP =
+ PTHREAD_MUTEX_TIMED_NP | PTHREAD_MUTEX_ELISION_NP,
+ PTHREAD_MUTEX_TIMED_NO_ELISION_NP =
+ PTHREAD_MUTEX_TIMED_NP | PTHREAD_MUTEX_NO_ELISION_NP,
+};
+#define PTHREAD_MUTEX_PSHARED_BIT 128
+
+/* See concurrency notes regarding __kind in struct __pthread_mutex_s
+ in sysdeps/nptl/bits/thread-shared-types.h. */
+#define PTHREAD_MUTEX_TYPE(m) \
+ (atomic_load_relaxed (&((m)->__data.__kind)) & 127)
+/* Don't include NO_ELISION, as that type is always the same
+ as the underlying lock type. */
+#define PTHREAD_MUTEX_TYPE_ELISION(m) \
+ (atomic_load_relaxed (&((m)->__data.__kind)) \
+ & (127 | PTHREAD_MUTEX_ELISION_NP))
+
+#if LLL_PRIVATE == 0 && LLL_SHARED == 128
+# define PTHREAD_MUTEX_PSHARED(m) \
+ (atomic_load_relaxed (&((m)->__data.__kind)) & 128)
+#else
+# define PTHREAD_MUTEX_PSHARED(m) \
+ ((atomic_load_relaxed (&((m)->__data.__kind)) & 128) \
+ ? LLL_SHARED : LLL_PRIVATE)
+#endif
+
+/* The kernel when waking robust mutexes on exit never uses
+ FUTEX_PRIVATE_FLAG FUTEX_WAKE. */
+#define PTHREAD_ROBUST_MUTEX_PSHARED(m) LLL_SHARED
+
+/* Ceiling in __data.__lock. __data.__lock is signed, so don't
+ use the MSB bit in there, but in the mask also include that bit,
+ so that the compiler can optimize & PTHREAD_MUTEX_PRIO_CEILING_MASK
+ masking if the value is then shifted down by
+ PTHREAD_MUTEX_PRIO_CEILING_SHIFT. */
+#define PTHREAD_MUTEX_PRIO_CEILING_SHIFT 19
+#define PTHREAD_MUTEX_PRIO_CEILING_MASK 0xfff80000
+
+
+/* Flags in mutex attr. */
+#define PTHREAD_MUTEXATTR_PROTOCOL_SHIFT 28
+#define PTHREAD_MUTEXATTR_PROTOCOL_MASK 0x30000000
+#define PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT 12
+#define PTHREAD_MUTEXATTR_PRIO_CEILING_MASK 0x00fff000
+#define PTHREAD_MUTEXATTR_FLAG_ROBUST 0x40000000
+#define PTHREAD_MUTEXATTR_FLAG_PSHARED 0x80000000
+#define PTHREAD_MUTEXATTR_FLAG_BITS \
+ (PTHREAD_MUTEXATTR_FLAG_ROBUST | PTHREAD_MUTEXATTR_FLAG_PSHARED \
+ | PTHREAD_MUTEXATTR_PROTOCOL_MASK | PTHREAD_MUTEXATTR_PRIO_CEILING_MASK)
+
+
+/* For the following, see pthread_rwlock_common.c. */
+#define PTHREAD_RWLOCK_WRPHASE 1
+#define PTHREAD_RWLOCK_WRLOCKED 2
+#define PTHREAD_RWLOCK_RWAITING 4
+#define PTHREAD_RWLOCK_READER_SHIFT 3
+#define PTHREAD_RWLOCK_READER_OVERFLOW ((unsigned int) 1 \
+ << (sizeof (unsigned int) * 8 - 1))
+#define PTHREAD_RWLOCK_WRHANDOVER ((unsigned int) 1 \
+ << (sizeof (unsigned int) * 8 - 1))
+#define PTHREAD_RWLOCK_FUTEX_USED 2
+
+
+/* Bits used in robust mutex implementation. */
+#define FUTEX_WAITERS 0x80000000
+#define FUTEX_OWNER_DIED 0x40000000
+#define FUTEX_TID_MASK 0x3fffffff
+
+
+/* pthread_once definitions. See __pthread_once for how these are used. */
+#define __PTHREAD_ONCE_INPROGRESS 1
+#define __PTHREAD_ONCE_DONE 2
+#define __PTHREAD_ONCE_FORK_GEN_INCR 4
+
+/* Attribute to indicate thread creation was issued from C11 thrd_create. */
+#define ATTR_C11_THREAD ((void*)(uintptr_t)-1)
+
+#if 0
+/* Condition variable definitions. See __pthread_cond_wait_common.
+ Need to be defined here so there is one place from which
+ nptl_lock_constants can grab them. */
+#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
+#define __PTHREAD_COND_SHARED_MASK 1
+#endif
+
+/* Internal variables. */
+
+
+/* Default pthread attributes. */
+extern struct pthread_attr __default_pthread_attr attribute_hidden;
+extern int __default_pthread_attr_lock attribute_hidden;
+
+/* Size and alignment of static TLS block. */
+extern size_t __static_tls_size attribute_hidden;
+extern size_t __static_tls_align_m1 attribute_hidden;
+
+/* Flag whether the machine is SMP or not. */
+extern int __is_smp attribute_hidden;
+
+/* Thread descriptor handling. */
+extern list_t __stack_user;
+hidden_proto (__stack_user)
+
+/* Attribute handling. */
+extern struct pthread_attr *__attr_list attribute_hidden;
+extern int __attr_list_lock attribute_hidden;
+
+/* Concurrency handling. */
+extern int __concurrency_level attribute_hidden;
+
+/* Thread-local data key handling. */
+extern struct pthread_key_struct __pthread_keys[PTHREAD_KEYS_MAX];
+hidden_proto (__pthread_keys)
+
+/* Number of threads running. */
+extern unsigned int __nptl_nthreads attribute_hidden;
+
+#ifndef __ASSUME_SET_ROBUST_LIST
+/* Negative if we do not have the system call and we can use it. */
+extern int __set_robust_list_avail attribute_hidden;
+#endif
+
+/* Thread Priority Protection. */
+extern int __sched_fifo_min_prio attribute_hidden;
+extern int __sched_fifo_max_prio attribute_hidden;
+extern void __init_sched_fifo_prio (void) attribute_hidden;
+extern int __pthread_tpp_change_priority (int prev_prio, int new_prio)
+ attribute_hidden;
+extern int __pthread_current_priority (void) attribute_hidden;
+
+/* The library can run in debugging mode where it performs a lot more
+ tests. */
+extern int __pthread_debug attribute_hidden;
+/** For now disable debugging support. */
+#if 0
+# define DEBUGGING_P __builtin_expect (__pthread_debug, 0)
+# define INVALID_TD_P(pd) (DEBUGGING_P && __find_in_stack_list (pd) == NULL)
+# define INVALID_NOT_TERMINATED_TD_P(pd) INVALID_TD_P (pd)
+#else
+# define DEBUGGING_P 0
+/* Simplified test. This will not catch all invalid descriptors but
+ is better than nothing. And if the test triggers the thread
+ descriptor is guaranteed to be invalid. */
+# define INVALID_TD_P(pd) __builtin_expect ((pd)->tid <= 0, 0)
+# define INVALID_NOT_TERMINATED_TD_P(pd) __builtin_expect ((pd)->tid < 0, 0)
+#endif
+
+
+/* Cancellation test. */
+#define CANCELLATION_P(self) \
+ do { \
+ int cancelhandling = THREAD_GETMEM (self, cancelhandling); \
+ if (CANCEL_ENABLED_AND_CANCELED (cancelhandling)) \
+ { \
+ THREAD_SETMEM (self, result, PTHREAD_CANCELED); \
+ __do_cancel (); \
+ } \
+ } while (0)
+
+
+extern void __pthread_unwind (__pthread_unwind_buf_t *__buf)
+ __cleanup_fct_attribute __attribute ((__noreturn__))
+ weak_function
+ ;
+extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf)
+ __cleanup_fct_attribute __attribute ((__noreturn__))
+#ifndef SHARED
+ weak_function
+#endif
+ ;
+extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf)
+ __cleanup_fct_attribute;
+extern void __pthread_unregister_cancel (__pthread_unwind_buf_t *__buf)
+ __cleanup_fct_attribute;
+hidden_proto (__pthread_unwind)
+hidden_proto (__pthread_unwind_next)
+hidden_proto (__pthread_register_cancel)
+hidden_proto (__pthread_unregister_cancel)
+# ifdef SHARED
+extern void attribute_hidden pthread_cancel_init (void);
+# endif
+extern void __nptl_unwind_freeres (void) attribute_hidden;
+
+
+/* Called when a thread reacts on a cancellation request. */
+static inline void
+__attribute ((noreturn, always_inline))
+__do_cancel (void)
+{
+ struct pthread *self = THREAD_SELF;
+
+ /* Make sure we get no more cancellations. */
+ THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT);
+
+ __pthread_unwind ((__pthread_unwind_buf_t *)
+ THREAD_GETMEM (self, cleanup_jmp_buf));
+}
+
+
+/* Set cancellation mode to asynchronous. */
+#define CANCEL_ASYNC() \
+ __pthread_enable_asynccancel ()
+/* Reset to previous cancellation mode. */
+#define CANCEL_RESET(oldtype) \
+ __pthread_disable_asynccancel (oldtype)
+
+# ifdef LIBC_CANCEL_ASYNC
+# undef LIBC_CANCEL_ASYNC
+# define LIBC_CANCEL_ASYNC() CANCEL_ASYNC ()
+# endif
+# ifdef LIBC_CANCEL_RESET
+# undef LIBC_CANCEL_RESET
+# define LIBC_CANCEL_RESET(val) CANCEL_RESET (val)
+# endif
+# define LIBC_CANCEL_HANDLED() \
+ __asm (".globl " __SYMBOL_PREFIX "__pthread_enable_asynccancel"); \
+ __asm (".globl " __SYMBOL_PREFIX "__pthread_disable_asynccancel")
+
+
+/* Internal prototypes. */
+
+/* Thread list handling. */
+extern struct pthread *__find_in_stack_list (struct pthread *pd)
+ attribute_hidden;
+
+/* Deallocate a thread's stack after optionally making sure the thread
+ descriptor is still valid. */
+extern void __free_tcb (struct pthread *pd) attribute_hidden;
+
+/* Free allocated stack. */
+extern void __deallocate_stack (struct pthread *pd) attribute_hidden;
+
+/* Mark all the stacks except for the current one as available. This
+ function also re-initializes the lock for the stack cache. */
+extern void __reclaim_stacks (void) attribute_hidden;
+
+/* Make all threads's stacks executable. */
+extern int __make_stacks_executable (void **stack_endp) attribute_hidden;
+
+/* longjmp handling. */
+extern void __pthread_cleanup_upto (__jmp_buf target, char *targetframe);
+hidden_proto (__pthread_cleanup_upto)
+
+
+/* Functions with versioned interfaces. */
+extern int __pthread_create_2_1 (pthread_t *newthread,
+ const pthread_attr_t *attr,
+ void *(*start_routine) (void *), void *arg);
+extern int __pthread_create_2_0 (pthread_t *newthread,
+ const pthread_attr_t *attr,
+ void *(*start_routine) (void *), void *arg);
+extern int __pthread_attr_init_2_1 (pthread_attr_t *attr);
+extern int __pthread_attr_init_2_0 (pthread_attr_t *attr);
+
+
+/* Event handlers for libthread_db interface. */
+extern void __nptl_create_event (void);
+extern void __nptl_death_event (void);
+hidden_proto (__nptl_create_event)
+hidden_proto (__nptl_death_event)
+
+/* Register the generation counter in the libpthread with the libc. */
+#ifdef TLS_MULTIPLE_THREADS_IN_TCB
+extern void __libc_pthread_init (unsigned long int *ptr,
+ void (*reclaim) (void),
+ const struct pthread_functions *functions);
+#else
+extern int *__libc_pthread_init (unsigned long int *ptr,
+ void (*reclaim) (void),
+ const struct pthread_functions *functions);
+
+/* Variable set to a nonzero value either if more than one thread runs or ran,
+ or if a single-threaded process is trying to cancel itself. See
+ nptl/descr.h for more context on the single-threaded process case. */
+extern int __pthread_multiple_threads attribute_hidden;
+/* Pointer to the corresponding variable in libc. */
+extern int *__libc_multiple_threads_ptr attribute_hidden;
+#endif
+
+/* Find a thread given its TID. */
+extern struct pthread *__find_thread_by_id (pid_t tid) attribute_hidden
+#ifdef SHARED
+;
+#else
+weak_function;
+#define __find_thread_by_id(tid) \
+ (__find_thread_by_id ? (__find_thread_by_id) (tid) : (struct pthread *) NULL)
+#endif
+
+extern void __pthread_init_static_tls (struct link_map *) attribute_hidden;
+
+extern size_t __pthread_get_minstack (const pthread_attr_t *attr);
+
+/* Namespace save aliases. */
+extern int __pthread_getschedparam (pthread_t thread_id, int *policy,
+ struct sched_param *param);
+extern int __pthread_setschedparam (pthread_t thread_id, int policy,
+ const struct sched_param *param);
+extern int __pthread_setcancelstate (int state, int *oldstate);
+extern int __pthread_mutex_init (pthread_mutex_t *__mutex,
+ const pthread_mutexattr_t *__mutexattr);
+extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex);
+extern int __pthread_mutex_trylock (pthread_mutex_t *_mutex);
+extern int __pthread_mutex_lock (pthread_mutex_t *__mutex);
+extern int __pthread_mutex_timedlock (pthread_mutex_t *__mutex,
+ const struct timespec *__abstime);
+extern int __pthread_mutex_cond_lock (pthread_mutex_t *__mutex)
+ attribute_hidden;
+extern void __pthread_mutex_cond_lock_adjust (pthread_mutex_t *__mutex)
+ attribute_hidden;
+extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex);
+extern int __pthread_mutex_unlock_usercnt (pthread_mutex_t *__mutex,
+ int __decr) attribute_hidden;
+extern int __pthread_mutexattr_init (pthread_mutexattr_t *attr);
+extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *attr);
+extern int __pthread_mutexattr_settype (pthread_mutexattr_t *attr, int kind);
+extern int __pthread_attr_destroy (pthread_attr_t *attr);
+extern int __pthread_attr_getdetachstate (const pthread_attr_t *attr,
+ int *detachstate);
+extern int __pthread_attr_setdetachstate (pthread_attr_t *attr,
+ int detachstate);
+extern int __pthread_attr_getinheritsched (const pthread_attr_t *attr,
+ int *inherit);
+extern int __pthread_attr_setinheritsched (pthread_attr_t *attr, int inherit);
+extern int __pthread_attr_getschedparam (const pthread_attr_t *attr,
+ struct sched_param *param);
+extern int __pthread_attr_setschedparam (pthread_attr_t *attr,
+ const struct sched_param *param);
+extern int __pthread_attr_getschedpolicy (const pthread_attr_t *attr,
+ int *policy);
+extern int __pthread_attr_setschedpolicy (pthread_attr_t *attr, int policy);
+extern int __pthread_attr_getscope (const pthread_attr_t *attr, int *scope);
+extern int __pthread_attr_setscope (pthread_attr_t *attr, int scope);
+extern int __pthread_attr_getstackaddr (const pthread_attr_t *__restrict
+ __attr, void **__restrict __stackaddr);
+extern int __pthread_attr_setstackaddr (pthread_attr_t *__attr,
+ void *__stackaddr);
+extern int __pthread_attr_getstacksize (const pthread_attr_t *__restrict
+ __attr,
+ size_t *__restrict __stacksize);
+extern int __pthread_attr_setstacksize (pthread_attr_t *__attr,
+ size_t __stacksize);
+extern int __pthread_attr_getstack (const pthread_attr_t *__restrict __attr,
+ void **__restrict __stackaddr,
+ size_t *__restrict __stacksize);
+extern int __pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr,
+ size_t __stacksize);
+extern int __pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock,
+ const pthread_rwlockattr_t *__restrict
+ __attr);
+extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock);
+extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock);
+extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock);
+extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock);
+extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock);
+extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock);
+extern int __pthread_cond_broadcast (pthread_cond_t *cond);
+extern int __pthread_cond_destroy (pthread_cond_t *cond);
+extern int __pthread_cond_init (pthread_cond_t *cond,
+ const pthread_condattr_t *cond_attr);
+extern int __pthread_cond_signal (pthread_cond_t *cond);
+extern int __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex);
+extern int __pthread_cond_timedwait (pthread_cond_t *cond,
+ pthread_mutex_t *mutex,
+ const struct timespec *abstime);
+extern int __pthread_condattr_destroy (pthread_condattr_t *attr);
+extern int __pthread_condattr_init (pthread_condattr_t *attr);
+extern int __pthread_key_create (pthread_key_t *key, void (*destr) (void *));
+extern int __pthread_key_delete (pthread_key_t key);
+extern void *__pthread_getspecific (pthread_key_t key);
+extern int __pthread_setspecific (pthread_key_t key, const void *value);
+extern int __pthread_once (pthread_once_t *once_control,
+ void (*init_routine) (void));
+extern int __pthread_atfork (void (*prepare) (void), void (*parent) (void),
+ void (*child) (void));
+extern pthread_t __pthread_self (void);
+extern int __pthread_equal (pthread_t thread1, pthread_t thread2);
+extern int __pthread_detach (pthread_t th);
+extern int __pthread_cancel (pthread_t th);
+extern int __pthread_kill (pthread_t threadid, int signo);
+extern void __pthread_exit (void *value) __attribute__ ((__noreturn__));
+extern int __pthread_join (pthread_t threadid, void **thread_return);
+extern int __pthread_setcanceltype (int type, int *oldtype);
+extern int __pthread_enable_asynccancel (void) attribute_hidden;
+extern void __pthread_disable_asynccancel (int oldtype) attribute_hidden;
+extern void __pthread_testcancel (void);
+extern int __pthread_timedjoin_ex (pthread_t, void **, const struct timespec *,
+ bool);
+
+hidden_proto (__pthread_mutex_init)
+hidden_proto (__pthread_mutex_destroy)
+hidden_proto (__pthread_mutex_lock)
+hidden_proto (__pthread_mutex_trylock)
+hidden_proto (__pthread_mutex_unlock)
+hidden_proto (__pthread_rwlock_rdlock)
+hidden_proto (__pthread_rwlock_wrlock)
+hidden_proto (__pthread_rwlock_unlock)
+hidden_proto (__pthread_key_create)
+hidden_proto (__pthread_getspecific)
+hidden_proto (__pthread_setspecific)
+hidden_proto (__pthread_once)
+hidden_proto (__pthread_setcancelstate)
+hidden_proto (__pthread_testcancel)
+hidden_proto (__pthread_mutexattr_init)
+hidden_proto (__pthread_mutexattr_settype)
+hidden_proto (__pthread_timedjoin_ex)
+
+extern int __pthread_cond_broadcast_2_0 (pthread_cond_2_0_t *cond);
+extern int __pthread_cond_destroy_2_0 (pthread_cond_2_0_t *cond);
+extern int __pthread_cond_init_2_0 (pthread_cond_2_0_t *cond,
+ const pthread_condattr_t *cond_attr);
+extern int __pthread_cond_signal_2_0 (pthread_cond_2_0_t *cond);
+extern int __pthread_cond_timedwait_2_0 (pthread_cond_2_0_t *cond,
+ pthread_mutex_t *mutex,
+ const struct timespec *abstime);
+extern int __pthread_cond_wait_2_0 (pthread_cond_2_0_t *cond,
+ pthread_mutex_t *mutex);
+
+extern int __pthread_getaffinity_np (pthread_t th, size_t cpusetsize,
+ cpu_set_t *cpuset);
+
+/* The two functions are in libc.so and not exported. */
+extern int __libc_enable_asynccancel (void) attribute_hidden;
+extern void __libc_disable_asynccancel (int oldtype) attribute_hidden;
+
+
+/* The two functions are in librt.so and not exported. */
+extern int __librt_enable_asynccancel (void) attribute_hidden;
+extern void __librt_disable_asynccancel (int oldtype) attribute_hidden;
+
+/* Special versions which use non-exported functions. */
+extern void __pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer,
+ void (*routine) (void *), void *arg)
+ attribute_hidden;
+
+/* Replace cleanup macros defined in <pthread.h> with internal
+ versions that don't depend on unwind info and better support
+ cancellation. */
+# undef pthread_cleanup_push
+# define pthread_cleanup_push(routine,arg) \
+ { struct _pthread_cleanup_buffer _buffer; \
+ __pthread_cleanup_push (&_buffer, (routine), (arg));
+
+extern void __pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer,
+ int execute) attribute_hidden;
+# undef pthread_cleanup_pop
+# define pthread_cleanup_pop(execute) \
+ __pthread_cleanup_pop (&_buffer, (execute)); }
+
+# if defined __EXCEPTIONS && !defined __cplusplus
+/* Structure to hold the cleanup handler information. */
+struct __pthread_cleanup_combined_frame
+{
+ void (*__cancel_routine) (void *);
+ void *__cancel_arg;
+ int __do_it;
+ struct _pthread_cleanup_buffer __buffer;
+};
+
+/* Special cleanup macros which register cleanup both using
+ __pthread_cleanup_{push,pop} and using cleanup attribute. This is needed
+ for pthread_once, so that it supports both throwing exceptions from the
+ pthread_once callback (only cleanup attribute works there) and cancellation
+ of the thread running the callback if the callback or some routines it
+ calls don't have unwind information. */
+
+static __always_inline void
+__pthread_cleanup_combined_routine (struct __pthread_cleanup_combined_frame
+ *__frame)
+{
+ if (__frame->__do_it)
+ {
+ __frame->__cancel_routine (__frame->__cancel_arg);
+ __frame->__do_it = 0;
+ __pthread_cleanup_pop (&__frame->__buffer, 0);
+ }
+}
+
+static inline void
+__pthread_cleanup_combined_routine_voidptr (void *__arg)
+{
+ struct __pthread_cleanup_combined_frame *__frame
+ = (struct __pthread_cleanup_combined_frame *) __arg;
+ if (__frame->__do_it)
+ {
+ __frame->__cancel_routine (__frame->__cancel_arg);
+ __frame->__do_it = 0;
+ }
+}
+
+# define pthread_cleanup_combined_push(routine, arg) \
+ do { \
+ void (*__cancel_routine) (void *) = (routine); \
+ struct __pthread_cleanup_combined_frame __clframe \
+ __attribute__ ((__cleanup__ (__pthread_cleanup_combined_routine))) \
+ = { .__cancel_routine = __cancel_routine, .__cancel_arg = (arg), \
+ .__do_it = 1 }; \
+ __pthread_cleanup_push (&__clframe.__buffer, \
+ __pthread_cleanup_combined_routine_voidptr, \
+ &__clframe);
+
+# define pthread_cleanup_combined_pop(execute) \
+ __pthread_cleanup_pop (&__clframe.__buffer, 0); \
+ __clframe.__do_it = 0; \
+ if (execute) \
+ __cancel_routine (__clframe.__cancel_arg); \
+ } while (0)
+
+# endif
+
+extern void __pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer,
+ void (*routine) (void *), void *arg);
+extern void __pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer,
+ int execute);
+
+/* Old cleanup interfaces, still used in libc.so. */
+extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer,
+ void (*routine) (void *), void *arg);
+extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer,
+ int execute);
+extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer,
+ void (*routine) (void *), void *arg);
+extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer,
+ int execute);
+
+extern void __nptl_deallocate_tsd (void) attribute_hidden;
+
+extern void __nptl_setxid_error (struct xid_command *cmdp, int error)
+ attribute_hidden;
+extern int __nptl_setxid (struct xid_command *cmdp) attribute_hidden;
+#ifndef SHARED
+extern void __nptl_set_robust (struct pthread *self);
+#endif
+
+extern void __nptl_stacks_freeres (void) attribute_hidden;
+extern void __shm_directory_freeres (void) attribute_hidden;
+
+extern void __wait_lookup_done (void) attribute_hidden;
+
+#ifdef SHARED
+# define PTHREAD_STATIC_FN_REQUIRE(name)
+#else
+# define PTHREAD_STATIC_FN_REQUIRE(name) __asm (".globl " #name);
+#endif
+
+/* Test if the mutex is suitable for the FUTEX_WAIT_REQUEUE_PI operation. */
+#if (defined lll_futex_wait_requeue_pi \
+ && defined __ASSUME_REQUEUE_PI)
+# define USE_REQUEUE_PI(mut) \
+ ((mut) && (mut) != (void *) ~0l \
+ && (((mut)->__data.__kind \
+ & (PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_NORMAL_NP)) \
+ == PTHREAD_MUTEX_PRIO_INHERIT_NP))
+#else
+# define USE_REQUEUE_PI(mut) 0
+#endif
+
+
+/* Returns 0 if POL is a valid scheduling policy. */
+static inline int
+check_sched_policy_attr (int pol)
+{
+ if (pol == SCHED_OTHER || pol == SCHED_FIFO || pol == SCHED_RR)
+ return 0;
+
+ return EINVAL;
+}
+
+/* Returns 0 if PR is within the accepted range of priority values for
+ the scheduling policy POL or EINVAL otherwise. */
+static inline int
+check_sched_priority_attr (int pr, int pol)
+{
+ int min = __sched_get_priority_min (pol);
+ int max = __sched_get_priority_max (pol);
+
+ if (min >= 0 && max >= 0 && pr >= min && pr <= max)
+ return 0;
+
+ return EINVAL;
+}
+
+/* Returns 0 if ST is a valid stack size for a thread stack and EINVAL
+ otherwise. */
+static inline int
+check_stacksize_attr (size_t st)
+{
+ if (st >= PTHREAD_STACK_MIN)
+ return 0;
+
+ return EINVAL;
+}
+
+#define ASSERT_TYPE_SIZE(type, size) \
+ _Static_assert (sizeof (type) == size, \
+ "sizeof (" #type ") != " #size)
+
+#define ASSERT_PTHREAD_INTERNAL_SIZE(type, internal) \
+ _Static_assert (sizeof ((type) { { 0 } }).__size >= sizeof (internal),\
+ "sizeof (" #type ".__size) < sizeof (" #internal ")")
+
+#define ASSERT_PTHREAD_STRING(x) __STRING (x)
+#define ASSERT_PTHREAD_INTERNAL_OFFSET(type, member, offset) \
+ _Static_assert (offsetof (type, member) == offset, \
+ "offset of " #member " field of " #type " != " \
+ ASSERT_PTHREAD_STRING (offset))
+
+#endif /* pthreadP.h */
diff --git a/nptl_2_17/pthread_2_17.h b/nptl_2_17/pthread_2_17.h
new file mode 100644
index 00000000..f2d9c226
--- /dev/null
+++ b/nptl_2_17/pthread_2_17.h
@@ -0,0 +1,1162 @@
+/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _PTHREAD_H
+#define _PTHREAD_H 1
+
+#include "bits/pthreadtypes_2_17.h"
+
+#include <features.h>
+#include <endian.h>
+#include <sched.h>
+#include <time.h>
+
+#include <bits/setjmp.h>
+#include <bits/wordsize.h>
+#include <bits/types/struct_timespec.h>
+
+
+/* Detach state. */
+enum
+{
+ PTHREAD_CREATE_JOINABLE,
+#define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_JOINABLE
+ PTHREAD_CREATE_DETACHED
+#define PTHREAD_CREATE_DETACHED PTHREAD_CREATE_DETACHED
+};
+
+
+/* Mutex types. */
+enum
+{
+ PTHREAD_MUTEX_TIMED_NP,
+ PTHREAD_MUTEX_RECURSIVE_NP,
+ PTHREAD_MUTEX_ERRORCHECK_NP,
+ PTHREAD_MUTEX_ADAPTIVE_NP
+#if defined __USE_UNIX98 || defined __USE_XOPEN2K8
+ ,
+ PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP,
+ PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
+ PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
+ PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
+#endif
+#ifdef __USE_GNU
+ /* For compatibility. */
+ , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_TIMED_NP
+#endif
+};
+
+
+#ifdef __USE_XOPEN2K
+/* Robust mutex or not flags. */
+enum
+{
+ PTHREAD_MUTEX_STALLED,
+ PTHREAD_MUTEX_STALLED_NP = PTHREAD_MUTEX_STALLED,
+ PTHREAD_MUTEX_ROBUST,
+ PTHREAD_MUTEX_ROBUST_NP = PTHREAD_MUTEX_ROBUST
+};
+#endif
+
+
+#if defined __USE_POSIX199506 || defined __USE_UNIX98
+/* Mutex protocols. */
+enum
+{
+ PTHREAD_PRIO_NONE,
+ PTHREAD_PRIO_INHERIT,
+ PTHREAD_PRIO_PROTECT
+};
+#endif
+
+
+#if __PTHREAD_MUTEX_HAVE_PREV
+# define PTHREAD_MUTEX_INITIALIZER \
+ { { 0, 0, 0, 0, 0, __PTHREAD_SPINS, { 0, 0 } } }
+# ifdef __USE_GNU
+# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \
+ { { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, __PTHREAD_SPINS, { 0, 0 } } }
+# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \
+ { { 0, 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, __PTHREAD_SPINS, { 0, 0 } } }
+# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \
+ { { 0, 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, __PTHREAD_SPINS, { 0, 0 } } }
+
+# endif
+#else
+# define PTHREAD_MUTEX_INITIALIZER \
+ { { 0, 0, 0, 0, 0, { __PTHREAD_SPINS } } }
+# ifdef __USE_GNU
+# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \
+ { { 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, { __PTHREAD_SPINS } } }
+# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \
+ { { 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, 0, { __PTHREAD_SPINS } } }
+# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \
+ { { 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, 0, { __PTHREAD_SPINS } } }
+
+# endif
+#endif
+
+
+/* Read-write lock types. */
+#if defined __USE_UNIX98 || defined __USE_XOPEN2K
+enum
+{
+ PTHREAD_RWLOCK_PREFER_READER_NP,
+ PTHREAD_RWLOCK_PREFER_WRITER_NP,
+ PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,
+ PTHREAD_RWLOCK_DEFAULT_NP = PTHREAD_RWLOCK_PREFER_READER_NP
+};
+
+/* Define __PTHREAD_RWLOCK_INT_FLAGS_SHARED to 1 if pthread_rwlock_t
+ has the shared field. All 64-bit architectures have the shared field
+ in pthread_rwlock_t. */
+#ifndef __PTHREAD_RWLOCK_INT_FLAGS_SHARED
+# if __WORDSIZE == 64
+# define __PTHREAD_RWLOCK_INT_FLAGS_SHARED 1
+# endif
+#endif
+
+/* Read-write lock initializers. */
+# define PTHREAD_RWLOCK_INITIALIZER \
+ { { 0, 0, 0, 0, 0, 0, 0, 0, __PTHREAD_RWLOCK_ELISION_EXTRA, 0, 0 } }
+# ifdef __USE_GNU
+# ifdef __PTHREAD_RWLOCK_INT_FLAGS_SHARED
+# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \
+ { { 0, 0, 0, 0, 0, 0, 0, 0, __PTHREAD_RWLOCK_ELISION_EXTRA, 0, \
+ PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP } }
+# else
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \
+ { { 0, 0, 0, 0, 0, 0, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, \
+ 0, __PTHREAD_RWLOCK_ELISION_EXTRA, 0, 0 } }
+# else
+# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \
+ { { 0, 0, 0, 0, 0, 0, 0, 0, 0, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,\
+ 0 } }
+# endif
+# endif
+# endif
+#endif /* Unix98 or XOpen2K */
+
+
+/* Scheduler inheritance. */
+enum
+{
+ PTHREAD_INHERIT_SCHED,
+#define PTHREAD_INHERIT_SCHED PTHREAD_INHERIT_SCHED
+ PTHREAD_EXPLICIT_SCHED
+#define PTHREAD_EXPLICIT_SCHED PTHREAD_EXPLICIT_SCHED
+};
+
+
+/* Scope handling. */
+enum
+{
+ PTHREAD_SCOPE_SYSTEM,
+#define PTHREAD_SCOPE_SYSTEM PTHREAD_SCOPE_SYSTEM
+ PTHREAD_SCOPE_PROCESS
+#define PTHREAD_SCOPE_PROCESS PTHREAD_SCOPE_PROCESS
+};
+
+
+/* Process shared or private flag. */
+enum
+{
+ PTHREAD_PROCESS_PRIVATE,
+#define PTHREAD_PROCESS_PRIVATE PTHREAD_PROCESS_PRIVATE
+ PTHREAD_PROCESS_SHARED
+#define PTHREAD_PROCESS_SHARED PTHREAD_PROCESS_SHARED
+};
+
+
+
+/* Conditional variable handling. */
+#define PTHREAD_COND_INITIALIZER { { 0, 0, 0, 0, 0, (void *) 0, 0, 0 } }
+
+/* Cleanup buffers */
+struct _pthread_cleanup_buffer
+{
+ void (*__routine) (void *); /* Function to call. */
+ void *__arg; /* Its argument. */
+ int __canceltype; /* Saved cancellation type. */
+ struct _pthread_cleanup_buffer *__prev; /* Chaining of cleanup functions. */
+};
+
+/* Cancellation */
+enum
+{
+ PTHREAD_CANCEL_ENABLE,
+#define PTHREAD_CANCEL_ENABLE PTHREAD_CANCEL_ENABLE
+ PTHREAD_CANCEL_DISABLE
+#define PTHREAD_CANCEL_DISABLE PTHREAD_CANCEL_DISABLE
+};
+enum
+{
+ PTHREAD_CANCEL_DEFERRED,
+#define PTHREAD_CANCEL_DEFERRED PTHREAD_CANCEL_DEFERRED
+ PTHREAD_CANCEL_ASYNCHRONOUS
+#define PTHREAD_CANCEL_ASYNCHRONOUS PTHREAD_CANCEL_ASYNCHRONOUS
+};
+#define PTHREAD_CANCELED ((void *) -1)
+
+
+/* Single execution handling. */
+#define PTHREAD_ONCE_INIT 0
+
+
+#ifdef __USE_XOPEN2K
+/* Value returned by 'pthread_barrier_wait' for one of the threads after
+ the required number of threads have called this function.
+ -1 is distinct from 0 and all errno constants */
+# define PTHREAD_BARRIER_SERIAL_THREAD -1
+#endif
+
+
+__BEGIN_DECLS
+
+/* Create a new thread, starting with execution of START-ROUTINE
+ getting passed ARG. Creation attributed come from ATTR. The new
+ handle is stored in *NEWTHREAD. */
+extern int pthread_create (pthread_t *__restrict __newthread,
+ const pthread_attr_t *__restrict __attr,
+ void *(*__start_routine) (void *),
+ void *__restrict __arg) __THROWNL __nonnull ((1, 3));
+
+/* Terminate calling thread.
+
+ The registered cleanup handlers are called via exception handling
+ so we cannot mark this function with __THROW.*/
+extern void pthread_exit (void *__retval) __attribute__ ((__noreturn__));
+
+/* Make calling thread wait for termination of the thread TH. The
+ exit status of the thread is stored in *THREAD_RETURN, if THREAD_RETURN
+ is not NULL.
+
+ This function is a cancellation point and therefore not marked with
+ __THROW. */
+extern int pthread_join (pthread_t __th, void **__thread_return);
+
+#ifdef __USE_GNU
+/* Check whether thread TH has terminated. If yes return the status of
+ the thread in *THREAD_RETURN, if THREAD_RETURN is not NULL. */
+extern int pthread_tryjoin_np (pthread_t __th, void **__thread_return) __THROW;
+
+/* Make calling thread wait for termination of the thread TH, but only
+ until TIMEOUT. The exit status of the thread is stored in
+ *THREAD_RETURN, if THREAD_RETURN is not NULL.
+
+ This function is a cancellation point and therefore not marked with
+ __THROW. */
+extern int pthread_timedjoin_np (pthread_t __th, void **__thread_return,
+ const struct timespec *__abstime);
+#endif
+
+/* Indicate that the thread TH is never to be joined with PTHREAD_JOIN.
+ The resources of TH will therefore be freed immediately when it
+ terminates, instead of waiting for another thread to perform PTHREAD_JOIN
+ on it. */
+extern int pthread_detach (pthread_t __th) __THROW;
+
+
+/* Obtain the identifier of the current thread. */
+extern pthread_t pthread_self (void) __THROW __attribute__ ((__const__));
+
+/* Compare two thread identifiers. */
+extern int pthread_equal (pthread_t __thread1, pthread_t __thread2)
+ __THROW __attribute__ ((__const__));
+
+
+/* Thread attribute handling. */
+
+/* Initialize thread attribute *ATTR with default attributes
+ (detachstate is PTHREAD_JOINABLE, scheduling policy is SCHED_OTHER,
+ no user-provided stack). */
+extern int pthread_attr_init (pthread_attr_t *__attr) __THROW __nonnull ((1));
+
+/* Destroy thread attribute *ATTR. */
+extern int pthread_attr_destroy (pthread_attr_t *__attr)
+ __THROW __nonnull ((1));
+
+/* Get detach state attribute. */
+extern int pthread_attr_getdetachstate (const pthread_attr_t *__attr,
+ int *__detachstate)
+ __THROW __nonnull ((1, 2));
+
+/* Set detach state attribute. */
+extern int pthread_attr_setdetachstate (pthread_attr_t *__attr,
+ int __detachstate)
+ __THROW __nonnull ((1));
+
+
+/* Get the size of the guard area created for stack overflow protection. */
+extern int pthread_attr_getguardsize (const pthread_attr_t *__attr,
+ size_t *__guardsize)
+ __THROW __nonnull ((1, 2));
+
+/* Set the size of the guard area created for stack overflow protection. */
+extern int pthread_attr_setguardsize (pthread_attr_t *__attr,
+ size_t __guardsize)
+ __THROW __nonnull ((1));
+
+
+/* Return in *PARAM the scheduling parameters of *ATTR. */
+extern int pthread_attr_getschedparam (const pthread_attr_t *__restrict __attr,
+ struct sched_param *__restrict __param)
+ __THROW __nonnull ((1, 2));
+
+/* Set scheduling parameters (priority, etc) in *ATTR according to PARAM. */
+extern int pthread_attr_setschedparam (pthread_attr_t *__restrict __attr,
+ const struct sched_param *__restrict
+ __param) __THROW __nonnull ((1, 2));
+
+/* Return in *POLICY the scheduling policy of *ATTR. */
+extern int pthread_attr_getschedpolicy (const pthread_attr_t *__restrict
+ __attr, int *__restrict __policy)
+ __THROW __nonnull ((1, 2));
+
+/* Set scheduling policy in *ATTR according to POLICY. */
+extern int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy)
+ __THROW __nonnull ((1));
+
+/* Return in *INHERIT the scheduling inheritance mode of *ATTR. */
+extern int pthread_attr_getinheritsched (const pthread_attr_t *__restrict
+ __attr, int *__restrict __inherit)
+ __THROW __nonnull ((1, 2));
+
+/* Set scheduling inheritance mode in *ATTR according to INHERIT. */
+extern int pthread_attr_setinheritsched (pthread_attr_t *__attr,
+ int __inherit)
+ __THROW __nonnull ((1));
+
+
+/* Return in *SCOPE the scheduling contention scope of *ATTR. */
+extern int pthread_attr_getscope (const pthread_attr_t *__restrict __attr,
+ int *__restrict __scope)
+ __THROW __nonnull ((1, 2));
+
+/* Set scheduling contention scope in *ATTR according to SCOPE. */
+extern int pthread_attr_setscope (pthread_attr_t *__attr, int __scope)
+ __THROW __nonnull ((1));
+
+/* Return the previously set address for the stack. */
+extern int pthread_attr_getstackaddr (const pthread_attr_t *__restrict
+ __attr, void **__restrict __stackaddr)
+ __THROW __nonnull ((1, 2)) __attribute_deprecated__;
+
+/* Set the starting address of the stack of the thread to be created.
+ Depending on whether the stack grows up or down the value must either
+ be higher or lower than all the address in the memory block. The
+ minimal size of the block must be PTHREAD_STACK_MIN. */
+extern int pthread_attr_setstackaddr (pthread_attr_t *__attr,
+ void *__stackaddr)
+ __THROW __nonnull ((1)) __attribute_deprecated__;
+
+/* Return the currently used minimal stack size. */
+extern int pthread_attr_getstacksize (const pthread_attr_t *__restrict
+ __attr, size_t *__restrict __stacksize)
+ __THROW __nonnull ((1, 2));
+
+/* Add information about the minimum stack size needed for the thread
+ to be started. This size must never be less than PTHREAD_STACK_MIN
+ and must also not exceed the system limits. */
+extern int pthread_attr_setstacksize (pthread_attr_t *__attr,
+ size_t __stacksize)
+ __THROW __nonnull ((1));
+
+#ifdef __USE_XOPEN2K
+/* Return the previously set address for the stack. */
+extern int pthread_attr_getstack (const pthread_attr_t *__restrict __attr,
+ void **__restrict __stackaddr,
+ size_t *__restrict __stacksize)
+ __THROW __nonnull ((1, 2, 3));
+
+/* The following two interfaces are intended to replace the last two. They
+ require setting the address as well as the size since only setting the
+ address will make the implementation on some architectures impossible. */
+extern int pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr,
+ size_t __stacksize) __THROW __nonnull ((1));
+#endif
+
+#ifdef __USE_GNU
+/* Thread created with attribute ATTR will be limited to run only on
+ the processors represented in CPUSET. */
+extern int pthread_attr_setaffinity_np (pthread_attr_t *__attr,
+ size_t __cpusetsize,
+ const cpu_set_t *__cpuset)
+ __THROW __nonnull ((1, 3));
+
+/* Get bit set in CPUSET representing the processors threads created with
+ ATTR can run on. */
+extern int pthread_attr_getaffinity_np (const pthread_attr_t *__attr,
+ size_t __cpusetsize,
+ cpu_set_t *__cpuset)
+ __THROW __nonnull ((1, 3));
+
+/* Get the default attributes used by pthread_create in this process. */
+extern int pthread_getattr_default_np (pthread_attr_t *__attr)
+ __THROW __nonnull ((1));
+
+/* Set the default attributes to be used by pthread_create in this
+ process. */
+extern int pthread_setattr_default_np (const pthread_attr_t *__attr)
+ __THROW __nonnull ((1));
+
+/* Initialize thread attribute *ATTR with attributes corresponding to the
+ already running thread TH. It shall be called on uninitialized ATTR
+ and destroyed with pthread_attr_destroy when no longer needed. */
+extern int pthread_getattr_np (pthread_t __th, pthread_attr_t *__attr)
+ __THROW __nonnull ((2));
+#endif
+
+
+/* Functions for scheduling control. */
+
+/* Set the scheduling parameters for TARGET_THREAD according to POLICY
+ and *PARAM. */
+extern int pthread_setschedparam (pthread_t __target_thread, int __policy,
+ const struct sched_param *__param)
+ __THROW __nonnull ((3));
+
+/* Return in *POLICY and *PARAM the scheduling parameters for TARGET_THREAD. */
+extern int pthread_getschedparam (pthread_t __target_thread,
+ int *__restrict __policy,
+ struct sched_param *__restrict __param)
+ __THROW __nonnull ((2, 3));
+
+/* Set the scheduling priority for TARGET_THREAD. */
+extern int pthread_setschedprio (pthread_t __target_thread, int __prio)
+ __THROW;
+
+
+#ifdef __USE_GNU
+/* Get thread name visible in the kernel and its interfaces. */
+extern int pthread_getname_np (pthread_t __target_thread, char *__buf,
+ size_t __buflen)
+ __THROW __nonnull ((2));
+
+/* Set thread name visible in the kernel and its interfaces. */
+extern int pthread_setname_np (pthread_t __target_thread, const char *__name)
+ __THROW __nonnull ((2));
+#endif
+
+
+#ifdef __USE_UNIX98
+/* Determine level of concurrency. */
+extern int pthread_getconcurrency (void) __THROW;
+
+/* Set new concurrency level to LEVEL. */
+extern int pthread_setconcurrency (int __level) __THROW;
+#endif
+
+#ifdef __USE_GNU
+/* Yield the processor to another thread or process.
+ This function is similar to the POSIX `sched_yield' function but
+ might be differently implemented in the case of a m-on-n thread
+ implementation. */
+extern int pthread_yield (void) __THROW;
+
+
+/* Limit specified thread TH to run only on the processors represented
+ in CPUSET. */
+extern int pthread_setaffinity_np (pthread_t __th, size_t __cpusetsize,
+ const cpu_set_t *__cpuset)
+ __THROW __nonnull ((3));
+
+/* Get bit set in CPUSET representing the processors TH can run on. */
+extern int pthread_getaffinity_np (pthread_t __th, size_t __cpusetsize,
+ cpu_set_t *__cpuset)
+ __THROW __nonnull ((3));
+#endif
+
+
+/* Functions for handling initialization. */
+
+/* Guarantee that the initialization function INIT_ROUTINE will be called
+ only once, even if pthread_once is executed several times with the
+ same ONCE_CONTROL argument. ONCE_CONTROL must point to a static or
+ extern variable initialized to PTHREAD_ONCE_INIT.
+
+ The initialization functions might throw exception which is why
+ this function is not marked with __THROW. */
+extern int pthread_once (pthread_once_t *__once_control,
+ void (*__init_routine) (void)) __nonnull ((1, 2));
+
+
+/* Functions for handling cancellation.
+
+ Note that these functions are explicitly not marked to not throw an
+ exception in C++ code. If cancellation is implemented by unwinding
+ this is necessary to have the compiler generate the unwind information. */
+
+/* Set cancelability state of current thread to STATE, returning old
+ state in *OLDSTATE if OLDSTATE is not NULL. */
+extern int pthread_setcancelstate (int __state, int *__oldstate);
+
+/* Set cancellation state of current thread to TYPE, returning the old
+ type in *OLDTYPE if OLDTYPE is not NULL. */
+extern int pthread_setcanceltype (int __type, int *__oldtype);
+
+/* Cancel THREAD immediately or at the next possibility. */
+extern int pthread_cancel (pthread_t __th);
+
+/* Test for pending cancellation for the current thread and terminate
+ the thread as per pthread_exit(PTHREAD_CANCELED) if it has been
+ cancelled. */
+extern void pthread_testcancel (void);
+
+
+/* Cancellation handling with integration into exception handling. */
+
+typedef struct
+{
+ struct
+ {
+ __jmp_buf __cancel_jmp_buf;
+ int __mask_was_saved;
+ } __cancel_jmp_buf[1];
+ void *__pad[4];
+} __pthread_unwind_buf_t __attribute__ ((__aligned__));
+
+/* No special attributes by default. */
+#ifndef __cleanup_fct_attribute
+# define __cleanup_fct_attribute
+#endif
+
+
+/* Structure to hold the cleanup handler information. */
+struct __pthread_cleanup_frame
+{
+ void (*__cancel_routine) (void *);
+ void *__cancel_arg;
+ int __do_it;
+ int __cancel_type;
+};
+
+#if defined __GNUC__ && defined __EXCEPTIONS
+# ifdef __cplusplus
+/* Class to handle cancellation handler invocation. */
+class __pthread_cleanup_class
+{
+ void (*__cancel_routine) (void *);
+ void *__cancel_arg;
+ int __do_it;
+ int __cancel_type;
+
+ public:
+ __pthread_cleanup_class (void (*__fct) (void *), void *__arg)
+ : __cancel_routine (__fct), __cancel_arg (__arg), __do_it (1) { }
+ ~__pthread_cleanup_class () { if (__do_it) __cancel_routine (__cancel_arg); }
+ void __setdoit (int __newval) { __do_it = __newval; }
+ void __defer () { pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED,
+ &__cancel_type); }
+ void __restore () const { pthread_setcanceltype (__cancel_type, 0); }
+};
+
+/* Install a cleanup handler: ROUTINE will be called with arguments ARG
+ when the thread is canceled or calls pthread_exit. ROUTINE will also
+ be called with arguments ARG when the matching pthread_cleanup_pop
+ is executed with non-zero EXECUTE argument.
+
+ pthread_cleanup_push and pthread_cleanup_pop are macros and must always
+ be used in matching pairs at the same nesting level of braces. */
+# define pthread_cleanup_push(routine, arg) \
+ do { \
+ __pthread_cleanup_class __clframe (routine, arg)
+
+/* Remove a cleanup handler installed by the matching pthread_cleanup_push.
+ If EXECUTE is non-zero, the handler function is called. */
+# define pthread_cleanup_pop(execute) \
+ __clframe.__setdoit (execute); \
+ } while (0)
+
+# ifdef __USE_GNU
+/* Install a cleanup handler as pthread_cleanup_push does, but also
+ saves the current cancellation type and sets it to deferred
+ cancellation. */
+# define pthread_cleanup_push_defer_np(routine, arg) \
+ do { \
+ __pthread_cleanup_class __clframe (routine, arg); \
+ __clframe.__defer ()
+
+/* Remove a cleanup handler as pthread_cleanup_pop does, but also
+ restores the cancellation type that was in effect when the matching
+ pthread_cleanup_push_defer was called. */
+# define pthread_cleanup_pop_restore_np(execute) \
+ __clframe.__restore (); \
+ __clframe.__setdoit (execute); \
+ } while (0)
+# endif
+# else
+/* Function called to call the cleanup handler. As an extern inline
+ function the compiler is free to decide inlining the change when
+ needed or fall back on the copy which must exist somewhere
+ else. */
+__extern_inline void
+__pthread_cleanup_routine (struct __pthread_cleanup_frame *__frame)
+{
+ if (__frame->__do_it)
+ __frame->__cancel_routine (__frame->__cancel_arg);
+}
+
+/* Install a cleanup handler: ROUTINE will be called with arguments ARG
+ when the thread is canceled or calls pthread_exit. ROUTINE will also
+ be called with arguments ARG when the matching pthread_cleanup_pop
+ is executed with non-zero EXECUTE argument.
+
+ pthread_cleanup_push and pthread_cleanup_pop are macros and must always
+ be used in matching pairs at the same nesting level of braces. */
+# define pthread_cleanup_push(routine, arg) \
+ do { \
+ struct __pthread_cleanup_frame __clframe \
+ __attribute__ ((__cleanup__ (__pthread_cleanup_routine))) \
+ = { .__cancel_routine = (routine), .__cancel_arg = (arg), \
+ .__do_it = 1 };
+
+/* Remove a cleanup handler installed by the matching pthread_cleanup_push.
+ If EXECUTE is non-zero, the handler function is called. */
+# define pthread_cleanup_pop(execute) \
+ __clframe.__do_it = (execute); \
+ } while (0)
+
+# ifdef __USE_GNU
+/* Install a cleanup handler as pthread_cleanup_push does, but also
+ saves the current cancellation type and sets it to deferred
+ cancellation. */
+# define pthread_cleanup_push_defer_np(routine, arg) \
+ do { \
+ struct __pthread_cleanup_frame __clframe \
+ __attribute__ ((__cleanup__ (__pthread_cleanup_routine))) \
+ = { .__cancel_routine = (routine), .__cancel_arg = (arg), \
+ .__do_it = 1 }; \
+ (void) pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, \
+ &__clframe.__cancel_type)
+
+/* Remove a cleanup handler as pthread_cleanup_pop does, but also
+ restores the cancellation type that was in effect when the matching
+ pthread_cleanup_push_defer was called. */
+# define pthread_cleanup_pop_restore_np(execute) \
+ (void) pthread_setcanceltype (__clframe.__cancel_type, NULL); \
+ __clframe.__do_it = (execute); \
+ } while (0)
+# endif
+# endif
+#else
+/* Install a cleanup handler: ROUTINE will be called with arguments ARG
+ when the thread is canceled or calls pthread_exit. ROUTINE will also
+ be called with arguments ARG when the matching pthread_cleanup_pop
+ is executed with non-zero EXECUTE argument.
+
+ pthread_cleanup_push and pthread_cleanup_pop are macros and must always
+ be used in matching pairs at the same nesting level of braces. */
+# define pthread_cleanup_push(routine, arg) \
+ do { \
+ __pthread_unwind_buf_t __cancel_buf; \
+ void (*__cancel_routine) (void *) = (routine); \
+ void *__cancel_arg = (arg); \
+ int __not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *) \
+ __cancel_buf.__cancel_jmp_buf, 0); \
+ if (__glibc_unlikely (__not_first_call)) \
+ { \
+ __cancel_routine (__cancel_arg); \
+ __pthread_unwind_next (&__cancel_buf); \
+ /* NOTREACHED */ \
+ } \
+ \
+ __pthread_register_cancel (&__cancel_buf); \
+ do {
+extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf)
+ __cleanup_fct_attribute;
+
+/* Remove a cleanup handler installed by the matching pthread_cleanup_push.
+ If EXECUTE is non-zero, the handler function is called. */
+# define pthread_cleanup_pop(execute) \
+ do { } while (0);/* Empty to allow label before pthread_cleanup_pop. */\
+ } while (0); \
+ __pthread_unregister_cancel (&__cancel_buf); \
+ if (execute) \
+ __cancel_routine (__cancel_arg); \
+ } while (0)
+extern void __pthread_unregister_cancel (__pthread_unwind_buf_t *__buf)
+ __cleanup_fct_attribute;
+
+# ifdef __USE_GNU
+/* Install a cleanup handler as pthread_cleanup_push does, but also
+ saves the current cancellation type and sets it to deferred
+ cancellation. */
+# define pthread_cleanup_push_defer_np(routine, arg) \
+ do { \
+ __pthread_unwind_buf_t __cancel_buf; \
+ void (*__cancel_routine) (void *) = (routine); \
+ void *__cancel_arg = (arg); \
+ int __not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *) \
+ __cancel_buf.__cancel_jmp_buf, 0); \
+ if (__glibc_unlikely (__not_first_call)) \
+ { \
+ __cancel_routine (__cancel_arg); \
+ __pthread_unwind_next (&__cancel_buf); \
+ /* NOTREACHED */ \
+ } \
+ \
+ __pthread_register_cancel_defer (&__cancel_buf); \
+ do {
+extern void __pthread_register_cancel_defer (__pthread_unwind_buf_t *__buf)
+ __cleanup_fct_attribute;
+
+/* Remove a cleanup handler as pthread_cleanup_pop does, but also
+ restores the cancellation type that was in effect when the matching
+ pthread_cleanup_push_defer was called. */
+# define pthread_cleanup_pop_restore_np(execute) \
+ do { } while (0);/* Empty to allow label before pthread_cleanup_pop. */\
+ } while (0); \
+ __pthread_unregister_cancel_restore (&__cancel_buf); \
+ if (execute) \
+ __cancel_routine (__cancel_arg); \
+ } while (0)
+extern void __pthread_unregister_cancel_restore (__pthread_unwind_buf_t *__buf)
+ __cleanup_fct_attribute;
+# endif
+
+/* Internal interface to initiate cleanup. */
+extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf)
+ __cleanup_fct_attribute __attribute__ ((__noreturn__))
+# ifndef SHARED
+ __attribute__ ((__weak__))
+# endif
+ ;
+#endif
+
+/* Function used in the macros. */
+struct __jmp_buf_tag;
+extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __THROWNL;
+
+
+/* Mutex handling. */
+
+/* Initialize a mutex. */
+extern int pthread_mutex_init (pthread_mutex_t *__mutex,
+ const pthread_mutexattr_t *__mutexattr)
+ __THROW __nonnull ((1));
+
+/* Destroy a mutex. */
+extern int pthread_mutex_destroy (pthread_mutex_t *__mutex)
+ __THROW __nonnull ((1));
+
+/* Try locking a mutex. */
+extern int pthread_mutex_trylock (pthread_mutex_t *__mutex)
+ __THROWNL __nonnull ((1));
+
+/* Lock a mutex. */
+extern int pthread_mutex_lock (pthread_mutex_t *__mutex)
+ __THROWNL __nonnull ((1));
+
+#ifdef __USE_XOPEN2K
+/* Wait until lock becomes available, or specified time passes. */
+extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex,
+ const struct timespec *__restrict
+ __abstime) __THROWNL __nonnull ((1, 2));
+#endif
+
+/* Unlock a mutex. */
+extern int pthread_mutex_unlock (pthread_mutex_t *__mutex)
+ __THROWNL __nonnull ((1));
+
+
+/* Get the priority ceiling of MUTEX. */
+extern int pthread_mutex_getprioceiling (const pthread_mutex_t *
+ __restrict __mutex,
+ int *__restrict __prioceiling)
+ __THROW __nonnull ((1, 2));
+
+/* Set the priority ceiling of MUTEX to PRIOCEILING, return old
+ priority ceiling value in *OLD_CEILING. */
+extern int pthread_mutex_setprioceiling (pthread_mutex_t *__restrict __mutex,
+ int __prioceiling,
+ int *__restrict __old_ceiling)
+ __THROW __nonnull ((1, 3));
+
+
+#ifdef __USE_XOPEN2K8
+/* Declare the state protected by MUTEX as consistent. */
+extern int pthread_mutex_consistent (pthread_mutex_t *__mutex)
+ __THROW __nonnull ((1));
+# ifdef __USE_GNU
+extern int pthread_mutex_consistent_np (pthread_mutex_t *__mutex)
+ __THROW __nonnull ((1));
+# endif
+#endif
+
+
+/* Functions for handling mutex attributes. */
+
+/* Initialize mutex attribute object ATTR with default attributes
+ (kind is PTHREAD_MUTEX_TIMED_NP). */
+extern int pthread_mutexattr_init (pthread_mutexattr_t *__attr)
+ __THROW __nonnull ((1));
+
+/* Destroy mutex attribute object ATTR. */
+extern int pthread_mutexattr_destroy (pthread_mutexattr_t *__attr)
+ __THROW __nonnull ((1));
+
+/* Get the process-shared flag of the mutex attribute ATTR. */
+extern int pthread_mutexattr_getpshared (const pthread_mutexattr_t *
+ __restrict __attr,
+ int *__restrict __pshared)
+ __THROW __nonnull ((1, 2));
+
+/* Set the process-shared flag of the mutex attribute ATTR. */
+extern int pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr,
+ int __pshared)
+ __THROW __nonnull ((1));
+
+#if defined __USE_UNIX98 || defined __USE_XOPEN2K8
+/* Return in *KIND the mutex kind attribute in *ATTR. */
+extern int pthread_mutexattr_gettype (const pthread_mutexattr_t *__restrict
+ __attr, int *__restrict __kind)
+ __THROW __nonnull ((1, 2));
+
+/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL,
+ PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or
+ PTHREAD_MUTEX_DEFAULT). */
+extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind)
+ __THROW __nonnull ((1));
+#endif
+
+/* Return in *PROTOCOL the mutex protocol attribute in *ATTR. */
+extern int pthread_mutexattr_getprotocol (const pthread_mutexattr_t *
+ __restrict __attr,
+ int *__restrict __protocol)
+ __THROW __nonnull ((1, 2));
+
+/* Set the mutex protocol attribute in *ATTR to PROTOCOL (either
+ PTHREAD_PRIO_NONE, PTHREAD_PRIO_INHERIT, or PTHREAD_PRIO_PROTECT). */
+extern int pthread_mutexattr_setprotocol (pthread_mutexattr_t *__attr,
+ int __protocol)
+ __THROW __nonnull ((1));
+
+/* Return in *PRIOCEILING the mutex prioceiling attribute in *ATTR. */
+extern int pthread_mutexattr_getprioceiling (const pthread_mutexattr_t *
+ __restrict __attr,
+ int *__restrict __prioceiling)
+ __THROW __nonnull ((1, 2));
+
+/* Set the mutex prioceiling attribute in *ATTR to PRIOCEILING. */
+extern int pthread_mutexattr_setprioceiling (pthread_mutexattr_t *__attr,
+ int __prioceiling)
+ __THROW __nonnull ((1));
+
+#ifdef __USE_XOPEN2K
+/* Get the robustness flag of the mutex attribute ATTR. */
+extern int pthread_mutexattr_getrobust (const pthread_mutexattr_t *__attr,
+ int *__robustness)
+ __THROW __nonnull ((1, 2));
+# ifdef __USE_GNU
+extern int pthread_mutexattr_getrobust_np (const pthread_mutexattr_t *__attr,
+ int *__robustness)
+ __THROW __nonnull ((1, 2));
+# endif
+
+/* Set the robustness flag of the mutex attribute ATTR. */
+extern int pthread_mutexattr_setrobust (pthread_mutexattr_t *__attr,
+ int __robustness)
+ __THROW __nonnull ((1));
+# ifdef __USE_GNU
+extern int pthread_mutexattr_setrobust_np (pthread_mutexattr_t *__attr,
+ int __robustness)
+ __THROW __nonnull ((1));
+# endif
+#endif
+
+
+#if defined __USE_UNIX98 || defined __USE_XOPEN2K
+/* Functions for handling read-write locks. */
+
+/* Initialize read-write lock RWLOCK using attributes ATTR, or use
+ the default values if later is NULL. */
+extern int pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock,
+ const pthread_rwlockattr_t *__restrict
+ __attr) __THROW __nonnull ((1));
+
+/* Destroy read-write lock RWLOCK. */
+extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock)
+ __THROW __nonnull ((1));
+
+/* Acquire read lock for RWLOCK. */
+extern int pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock)
+ __THROWNL __nonnull ((1));
+
+/* Try to acquire read lock for RWLOCK. */
+extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock)
+ __THROWNL __nonnull ((1));
+
+# ifdef __USE_XOPEN2K
+/* Try to acquire read lock for RWLOCK or return after specfied time. */
+extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock,
+ const struct timespec *__restrict
+ __abstime) __THROWNL __nonnull ((1, 2));
+# endif
+
+/* Acquire write lock for RWLOCK. */
+extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock)
+ __THROWNL __nonnull ((1));
+
+/* Try to acquire write lock for RWLOCK. */
+extern int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock)
+ __THROWNL __nonnull ((1));
+
+# ifdef __USE_XOPEN2K
+/* Try to acquire write lock for RWLOCK or return after specfied time. */
+extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock,
+ const struct timespec *__restrict
+ __abstime) __THROWNL __nonnull ((1, 2));
+# endif
+
+/* Unlock RWLOCK. */
+extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock)
+ __THROWNL __nonnull ((1));
+
+
+/* Functions for handling read-write lock attributes. */
+
+/* Initialize attribute object ATTR with default values. */
+extern int pthread_rwlockattr_init (pthread_rwlockattr_t *__attr)
+ __THROW __nonnull ((1));
+
+/* Destroy attribute object ATTR. */
+extern int pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr)
+ __THROW __nonnull ((1));
+
+/* Return current setting of process-shared attribute of ATTR in PSHARED. */
+extern int pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *
+ __restrict __attr,
+ int *__restrict __pshared)
+ __THROW __nonnull ((1, 2));
+
+/* Set process-shared attribute of ATTR to PSHARED. */
+extern int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *__attr,
+ int __pshared)
+ __THROW __nonnull ((1));
+
+/* Return current setting of reader/writer preference. */
+extern int pthread_rwlockattr_getkind_np (const pthread_rwlockattr_t *
+ __restrict __attr,
+ int *__restrict __pref)
+ __THROW __nonnull ((1, 2));
+
+/* Set reader/write preference. */
+extern int pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *__attr,
+ int __pref) __THROW __nonnull ((1));
+#endif
+
+
+/* Functions for handling conditional variables. */
+
+/* Initialize condition variable COND using attributes ATTR, or use
+ the default values if later is NULL. */
+extern int pthread_cond_init (pthread_cond_t *__restrict __cond,
+ const pthread_condattr_t *__restrict __cond_attr)
+ __THROW __nonnull ((1));
+
+/* Destroy condition variable COND. */
+extern int pthread_cond_destroy (pthread_cond_t *__cond)
+ __THROW __nonnull ((1));
+
+/* Wake up one thread waiting for condition variable COND. */
+extern int pthread_cond_signal (pthread_cond_t *__cond)
+ __THROWNL __nonnull ((1));
+
+/* Wake up all threads waiting for condition variables COND. */
+extern int pthread_cond_broadcast (pthread_cond_t *__cond)
+ __THROWNL __nonnull ((1));
+
+/* Wait for condition variable COND to be signaled or broadcast.
+ MUTEX is assumed to be locked before.
+
+ This function is a cancellation point and therefore not marked with
+ __THROW. */
+extern int pthread_cond_wait (pthread_cond_t *__restrict __cond,
+ pthread_mutex_t *__restrict __mutex)
+ __nonnull ((1, 2));
+
+/* Wait for condition variable COND to be signaled or broadcast until
+ ABSTIME. MUTEX is assumed to be locked before. ABSTIME is an
+ absolute time specification; zero is the beginning of the epoch
+ (00:00:00 GMT, January 1, 1970).
+
+ This function is a cancellation point and therefore not marked with
+ __THROW. */
+extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond,
+ pthread_mutex_t *__restrict __mutex,
+ const struct timespec *__restrict __abstime)
+ __nonnull ((1, 2, 3));
+
+/* Functions for handling condition variable attributes. */
+
+/* Initialize condition variable attribute ATTR. */
+extern int pthread_condattr_init (pthread_condattr_t *__attr)
+ __THROW __nonnull ((1));
+
+/* Destroy condition variable attribute ATTR. */
+extern int pthread_condattr_destroy (pthread_condattr_t *__attr)
+ __THROW __nonnull ((1));
+
+/* Get the process-shared flag of the condition variable attribute ATTR. */
+extern int pthread_condattr_getpshared (const pthread_condattr_t *
+ __restrict __attr,
+ int *__restrict __pshared)
+ __THROW __nonnull ((1, 2));
+
+/* Set the process-shared flag of the condition variable attribute ATTR. */
+extern int pthread_condattr_setpshared (pthread_condattr_t *__attr,
+ int __pshared) __THROW __nonnull ((1));
+
+#ifdef __USE_XOPEN2K
+/* Get the clock selected for the condition variable attribute ATTR. */
+extern int pthread_condattr_getclock (const pthread_condattr_t *
+ __restrict __attr,
+ __clockid_t *__restrict __clock_id)
+ __THROW __nonnull ((1, 2));
+
+/* Set the clock selected for the condition variable attribute ATTR. */
+extern int pthread_condattr_setclock (pthread_condattr_t *__attr,
+ __clockid_t __clock_id)
+ __THROW __nonnull ((1));
+#endif
+
+
+#ifdef __USE_XOPEN2K
+/* Functions to handle spinlocks. */
+
+/* Initialize the spinlock LOCK. If PSHARED is nonzero the spinlock can
+ be shared between different processes. */
+extern int pthread_spin_init (pthread_spinlock_t *__lock, int __pshared)
+ __THROW __nonnull ((1));
+
+/* Destroy the spinlock LOCK. */
+extern int pthread_spin_destroy (pthread_spinlock_t *__lock)
+ __THROW __nonnull ((1));
+
+/* Wait until spinlock LOCK is retrieved. */
+extern int pthread_spin_lock (pthread_spinlock_t *__lock)
+ __THROWNL __nonnull ((1));
+
+/* Try to lock spinlock LOCK. */
+extern int pthread_spin_trylock (pthread_spinlock_t *__lock)
+ __THROWNL __nonnull ((1));
+
+/* Release spinlock LOCK. */
+extern int pthread_spin_unlock (pthread_spinlock_t *__lock)
+ __THROWNL __nonnull ((1));
+
+
+/* Functions to handle barriers. */
+
+/* Initialize BARRIER with the attributes in ATTR. The barrier is
+ opened when COUNT waiters arrived. */
+extern int pthread_barrier_init (pthread_barrier_t *__restrict __barrier,
+ const pthread_barrierattr_t *__restrict
+ __attr, unsigned int __count)
+ __THROW __nonnull ((1));
+
+/* Destroy a previously dynamically initialized barrier BARRIER. */
+extern int pthread_barrier_destroy (pthread_barrier_t *__barrier)
+ __THROW __nonnull ((1));
+
+/* Wait on barrier BARRIER. */
+extern int pthread_barrier_wait (pthread_barrier_t *__barrier)
+ __THROWNL __nonnull ((1));
+
+
+/* Initialize barrier attribute ATTR. */
+extern int pthread_barrierattr_init (pthread_barrierattr_t *__attr)
+ __THROW __nonnull ((1));
+
+/* Destroy previously dynamically initialized barrier attribute ATTR. */
+extern int pthread_barrierattr_destroy (pthread_barrierattr_t *__attr)
+ __THROW __nonnull ((1));
+
+/* Get the process-shared flag of the barrier attribute ATTR. */
+extern int pthread_barrierattr_getpshared (const pthread_barrierattr_t *
+ __restrict __attr,
+ int *__restrict __pshared)
+ __THROW __nonnull ((1, 2));
+
+/* Set the process-shared flag of the barrier attribute ATTR. */
+extern int pthread_barrierattr_setpshared (pthread_barrierattr_t *__attr,
+ int __pshared)
+ __THROW __nonnull ((1));
+#endif
+
+
+/* Functions for handling thread-specific data. */
+
+/* Create a key value identifying a location in the thread-specific
+ data area. Each thread maintains a distinct thread-specific data
+ area. DESTR_FUNCTION, if non-NULL, is called with the value
+ associated to that key when the key is destroyed.
+ DESTR_FUNCTION is not called if the value associated is NULL when
+ the key is destroyed. */
+extern int pthread_key_create (pthread_key_t *__key,
+ void (*__destr_function) (void *))
+ __THROW __nonnull ((1));
+
+/* Destroy KEY. */
+extern int pthread_key_delete (pthread_key_t __key) __THROW;
+
+/* Return current value of the thread-specific data slot identified by KEY. */
+extern void *pthread_getspecific (pthread_key_t __key) __THROW;
+
+/* Store POINTER in the thread-specific data slot identified by KEY. */
+extern int pthread_setspecific (pthread_key_t __key,
+ const void *__pointer) __THROW ;
+
+
+#ifdef __USE_XOPEN2K
+/* Get ID of CPU-time clock for thread THREAD_ID. */
+extern int pthread_getcpuclockid (pthread_t __thread_id,
+ __clockid_t *__clock_id)
+ __THROW __nonnull ((2));
+#endif
+
+
+/* Install handlers to be called when a new process is created with FORK.
+ The PREPARE handler is called in the parent process just before performing
+ FORK. The PARENT handler is called in the parent process just after FORK.
+ The CHILD handler is called in the child process. Each of the three
+ handlers can be NULL, meaning that no handler needs to be called at that
+ point.
+ PTHREAD_ATFORK can be called several times, in which case the PREPARE
+ handlers are called in LIFO order (last added with PTHREAD_ATFORK,
+ first called before FORK), and the PARENT and CHILD handlers are called
+ in FIFO (first added, first called). */
+
+extern int pthread_atfork (void (*__prepare) (void),
+ void (*__parent) (void),
+ void (*__child) (void)) __THROW;
+
+
+#ifdef __USE_EXTERN_INLINES
+/* Optimizations. */
+__extern_inline int
+__NTH (pthread_equal (pthread_t __thread1, pthread_t __thread2))
+{
+ return __thread1 == __thread2;
+}
+#endif
+
+__END_DECLS
+
+#endif /* pthread.h */
diff --git a/nptl_2_17/pthread_cond_broadcast_2_17.c b/nptl_2_17/pthread_cond_broadcast_2_17.c
new file mode 100644
index 00000000..d9b68f79
--- /dev/null
+++ b/nptl_2_17/pthread_cond_broadcast_2_17.c
@@ -0,0 +1,98 @@
+/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "kernel-features_2_17.h"
+#include "pthread_2_17.h"
+#include "pthreadP_2_17.h"
+#include <lowlevellock_2_17.h>
+
+#include <endian.h>
+#include <errno.h>
+#include <stap-probe.h>
+#include <atomic.h>
+
+#include <shlib-compat.h>
+
+/* We do the following steps from __pthread_cond_signal in one critical
+ section: (1) signal all waiters in G1, (2) close G1 so that it can become
+ the new G2 and make G2 the new G1, and (3) signal all waiters in the new
+ G1. We don't need to do all these steps if there are no waiters in G1
+ and/or G2. See __pthread_cond_signal for further details. */
+int
+__pthread_cond_broadcast (pthread_cond_t *cond)
+{
+ LIBC_PROBE (cond_broadcast, 1, cond);
+
+ int pshared = (cond->__data.__mutex == (void *) ~0l)
+ ? LLL_SHARED : LLL_PRIVATE;
+ /* Make sure we are alone. */
+ lll_lock (cond->__data.__lock, pshared);
+
+ /* Are there any waiters to be woken? */
+ if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
+
+ {
+ /* Yes. Mark them all as woken. */
+ cond->__data.__wakeup_seq = cond->__data.__total_seq;
+ cond->__data.__woken_seq = cond->__data.__total_seq;
+ cond->__data.__futex = (unsigned int) cond->__data.__total_seq * 2;
+ int futex_val = cond->__data.__futex;
+ /* Signal that a broadcast happened. */
+ ++cond->__data.__broadcast_seq;
+
+ /* We are done. */
+ lll_unlock (cond->__data.__lock, pshared);
+
+ /* Wake everybody. */
+ pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex;
+
+ /* Do not use requeue for pshared condvars. */
+ if (mut == (void *) ~0l
+ || PTHREAD_MUTEX_PSHARED (mut) & PTHREAD_MUTEX_PSHARED_BIT)
+ goto wake_all;
+
+#if (defined lll_futex_cmp_requeue_pi \
+ && defined __ASSUME_REQUEUE_PI)
+ if (USE_REQUEUE_PI (mut))
+ {
+ if (lll_futex_cmp_requeue_pi (&cond->__data.__futex, 1, INT_MAX,
+ &mut->__data.__lock, futex_val,
+ LLL_PRIVATE) == 0)
+ return 0;
+ }
+ else
+#endif
+ /* lll_futex_requeue returns 0 for success and non-zero
+ for errors. */
+ if (!__builtin_expect (lll_futex_requeue (&cond->__data.__futex, 1,
+ INT_MAX, &mut->__data.__lock,
+ futex_val, LLL_PRIVATE), 0))
+ return 0;
+
+wake_all:
+ lll_futex_wake (&cond->__data.__futex, INT_MAX, pshared);
+ return 0;
+ }
+ /* We are done. */
+ lll_unlock (cond->__data.__lock, pshared);
+
+ return 0;
+}
+
+versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast,
+ GLIBC_2_3_2);
diff --git a/nptl_2_17/pthread_cond_destroy_2_17.c b/nptl_2_17/pthread_cond_destroy_2_17.c
new file mode 100644
index 00000000..f5bd7ade
--- /dev/null
+++ b/nptl_2_17/pthread_cond_destroy_2_17.c
@@ -0,0 +1,85 @@
+/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received 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_2_17.h"
+#include <errno.h>
+#include <shlib-compat.h>
+#include <stap-probe.h>
+int
+__pthread_cond_destroy (pthread_cond_t *cond)
+{
+ int pshared = (cond->__data.__mutex == (void *) ~0l)
+ ? LLL_SHARED : LLL_PRIVATE;
+
+ LIBC_PROBE (cond_destroy, 1, cond);
+
+ /* Make sure we are alone. */
+ lll_lock (cond->__data.__lock, pshared);
+
+ if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
+ {
+ /* If there are still some waiters which have not been
+ woken up, this is an application bug. */
+ lll_unlock (cond->__data.__lock, pshared);
+ return EBUSY;
+ }
+
+ /* Tell pthread_cond_*wait that this condvar is being destroyed. */
+ cond->__data.__total_seq = -1ULL;
+
+ /* If there are waiters which have been already signalled or
+ broadcasted, but still are using the pthread_cond_t structure,
+ pthread_cond_destroy needs to wait for them. */
+ unsigned int nwaiters = cond->__data.__nwaiters;
+
+ if (nwaiters >= (1 << COND_NWAITERS_SHIFT))
+
+ {
+ /* Wake everybody on the associated mutex in case there are
+ threads that have been requeued to it.
+ Without this, pthread_cond_destroy could block potentially
+ for a long time or forever, as it would depend on other
+ thread's using the mutex.
+ When all threads waiting on the mutex are woken up, pthread_cond_wait
+ only waits for threads to acquire and release the internal
+ condvar lock. */
+ if (cond->__data.__mutex != NULL
+ && cond->__data.__mutex != (void *) ~0l)
+ {
+ pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex;
+ lll_futex_wake (&mut->__data.__lock, INT_MAX,
+ PTHREAD_MUTEX_PSHARED (mut));
+ }
+
+ do
+ {
+ lll_unlock (cond->__data.__lock, pshared);
+
+ lll_futex_wait (&cond->__data.__nwaiters, nwaiters, pshared);
+
+ lll_lock (cond->__data.__lock, pshared);
+
+ nwaiters = cond->__data.__nwaiters;
+ }
+ while (nwaiters >= (1 << COND_NWAITERS_SHIFT));
+ }
+
+ return 0;
+}
+versioned_symbol (libpthread, __pthread_cond_destroy,
+ pthread_cond_destroy, GLIBC_2_3_2);
diff --git a/nptl_2_17/pthread_cond_init_2_17.c b/nptl_2_17/pthread_cond_init_2_17.c
new file mode 100644
index 00000000..f4eff6ab
--- /dev/null
+++ b/nptl_2_17/pthread_cond_init_2_17.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received 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_2_17.h"
+#include <shlib-compat.h>
+#include <stap-probe.h>
+
+
+int
+__pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
+{
+ ASSERT_TYPE_SIZE (pthread_cond_t, __SIZEOF_PTHREAD_COND_T);
+
+ struct pthread_condattr *icond_attr = (struct pthread_condattr *) cond_attr;
+
+ cond->__data.__lock = LLL_LOCK_INITIALIZER;
+ cond->__data.__futex = 0;
+ cond->__data.__nwaiters = (icond_attr != NULL
+ ? ((icond_attr->value >> 1)
+ & ((1 << COND_NWAITERS_SHIFT) - 1))
+ : CLOCK_REALTIME);
+ cond->__data.__total_seq = 0;
+ cond->__data.__wakeup_seq = 0;
+ cond->__data.__woken_seq = 0;
+ cond->__data.__mutex = (icond_attr == NULL || (icond_attr->value & 1) == 0
+ ? NULL : (void *) ~0l);
+ cond->__data.__broadcast_seq = 0;
+
+
+ LIBC_PROBE (cond_init, 2, cond, cond_attr);
+
+ return 0;
+}
+versioned_symbol (libpthread, __pthread_cond_init,
+ pthread_cond_init, GLIBC_2_3_2);
diff --git a/nptl_2_17/pthread_cond_signal_2_17.c b/nptl_2_17/pthread_cond_signal_2_17.c
new file mode 100644
index 00000000..5d79b894
--- /dev/null
+++ b/nptl_2_17/pthread_cond_signal_2_17.c
@@ -0,0 +1,82 @@
+/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "kernel-features_2_17.h"
+#include "pthread_2_17.h"
+#include "pthreadP_2_17.h"
+#include <lowlevellock_2_17.h>
+
+#include <endian.h>
+#include <errno.h>
+
+#include <shlib-compat.h>
+#include <stap-probe.h>
+
+
+int
+__pthread_cond_signal (pthread_cond_t *cond)
+{
+ int pshared = (cond->__data.__mutex == (void *) ~0l)
+ ? LLL_SHARED : LLL_PRIVATE;
+
+ LIBC_PROBE (cond_signal, 1, cond);
+
+ /* Make sure we are alone. */
+ lll_lock (cond->__data.__lock, pshared);
+
+ /* Are there any waiters to be woken? */
+ if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
+ {
+ /* Yes. Mark one of them as woken. */
+ ++cond->__data.__wakeup_seq;
+ ++cond->__data.__futex;
+
+#if (defined lll_futex_cmp_requeue_pi \
+ && defined __ASSUME_REQUEUE_PI)
+ pthread_mutex_t *mut = cond->__data.__mutex;
+
+ if (USE_REQUEUE_PI (mut)
+ /* This can only really fail with a ENOSYS, since nobody can modify
+ futex while we have the cond_lock. */
+ && lll_futex_cmp_requeue_pi (&cond->__data.__futex, 1, 0,
+ &mut->__data.__lock,
+ cond->__data.__futex, pshared) == 0)
+ {
+ lll_unlock (cond->__data.__lock, pshared);
+ return 0;
+ }
+ else
+#endif
+ /* Wake one. */
+ if (! __builtin_expect (lll_futex_wake_unlock (&cond->__data.__futex,
+ 1, 1,
+ &cond->__data.__lock,
+ pshared), 0))
+ return 0;
+
+ /* Fallback if neither of them work. */
+ lll_futex_wake (&cond->__data.__futex, 1, pshared);
+ }
+/* We are done. */
+ lll_unlock (cond->__data.__lock, pshared);
+
+ return 0;
+}
+
+versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal,
+ GLIBC_2_3_2);
diff --git a/nptl_2_17/pthread_cond_timedwait_2_17.c b/nptl_2_17/pthread_cond_timedwait_2_17.c
new file mode 100644
index 00000000..ab497195
--- /dev/null
+++ b/nptl_2_17/pthread_cond_timedwait_2_17.c
@@ -0,0 +1,266 @@
+/* Copyright (C) 2003-2016 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "kernel-features_2_17.h"
+#include "bits/thread-shared-types_2_17.h"
+#include <sysdep_2_17.h>
+#include "pthread_2_17.h"
+#include "pthreadP_2_17.h"
+
+#include <endian.h>
+#include <errno.h>
+#include <lowlevellock_2_17.h>
+#include <sys/time.h>
+
+#include <shlib-compat.h>
+
+# undef INTERNAL_VSYSCALL
+# define INTERNAL_VSYSCALL INTERNAL_SYSCALL
+# undef INLINE_VSYSCALL
+# define INLINE_VSYSCALL INLINE_SYSCALL
+
+/* Cleanup handler, defined in pthread_cond_wait.c. */
+extern void __condvar_cleanup (void *arg)
+ __attribute__ ((visibility ("hidden")));
+
+struct _condvar_cleanup_buffer
+{
+ int oldtype;
+ pthread_cond_t *cond;
+ pthread_mutex_t *mutex;
+ unsigned int bc_seq;
+};
+
+int
+__pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
+ const struct timespec *abstime)
+{
+ struct _pthread_cleanup_buffer buffer;
+ struct _condvar_cleanup_buffer cbuffer;
+ int result = 0;
+
+ /* Catch invalid parameters. */
+ if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+ return EINVAL;
+
+ int pshared = (cond->__data.__mutex == (void *) ~0l)
+ ? LLL_SHARED : LLL_PRIVATE;
+
+#if (defined lll_futex_timed_wait_requeue_pi \
+ && defined __ASSUME_REQUEUE_PI)
+ int pi_flag = 0;
+#endif
+
+ /* Make sure we are alone. */
+ lll_lock (cond->__data.__lock, pshared);
+
+ /* Now we can release the mutex. */
+ int err = __pthread_mutex_unlock_usercnt (mutex, 0);
+ if (err)
+ {
+ lll_unlock (cond->__data.__lock, pshared);
+ return err;
+ }
+
+ /* We have one new user of the condvar. */
+ ++cond->__data.__total_seq;
+ ++cond->__data.__futex;
+ cond->__data.__nwaiters += 1 << COND_NWAITERS_SHIFT;
+
+ /* Work around the fact that the kernel rejects negative timeout values
+ despite them being valid. */
+ if (__glibc_unlikely (abstime->tv_sec < 0))
+ goto timeout;
+
+ /* Remember the mutex we are using here. If there is already a
+ different address store this is a bad user bug. Do not store
+ anything for pshared condvars. */
+ if (cond->__data.__mutex != (void *) ~0l)
+ cond->__data.__mutex = mutex;
+
+ /* Prepare structure passed to cancellation handler. */
+ cbuffer.cond = cond;
+ cbuffer.mutex = mutex;
+
+ /* Before we block we enable cancellation. Therefore we have to
+ install a cancellation handler. */
+ __pthread_cleanup_push (&buffer, __condvar_cleanup, &cbuffer);
+
+ /* The current values of the wakeup counter. The "woken" counter
+ must exceed this value. */
+ unsigned long long int val;
+ unsigned long long int seq;
+ val = seq = cond->__data.__wakeup_seq;
+ /* Remember the broadcast counter. */
+ cbuffer.bc_seq = cond->__data.__broadcast_seq;
+
+ while (1)
+ {
+#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \
+ || !defined lll_futex_timed_wait_bitset)
+ struct timespec rt;
+ {
+# ifdef __NR_clock_gettime
+ INTERNAL_SYSCALL_DECL (err);
+ (void) INTERNAL_VSYSCALL (clock_gettime, err, 2,
+ (cond->__data.__nwaiters
+ & ((1 << COND_NWAITERS_SHIFT) - 1)),
+ &rt);
+ /* Convert the absolute timeout value to a relative timeout. */
+ rt.tv_sec = abstime->tv_sec - rt.tv_sec;
+ rt.tv_nsec = abstime->tv_nsec - rt.tv_nsec;
+# else
+ /* Get the current time. So far we support only one clock. */
+ struct timeval tv;
+ (void) __gettimeofday (&tv, NULL);
+
+ /* Convert the absolute timeout value to a relative timeout. */
+ rt.tv_sec = abstime->tv_sec - tv.tv_sec;
+ rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
+# endif
+ }
+ if (rt.tv_nsec < 0)
+ {
+ rt.tv_nsec += 1000000000;
+ --rt.tv_sec;
+ }
+ /* Did we already time out? */
+ if (__glibc_unlikely (rt.tv_sec < 0))
+ {
+ if (cbuffer.bc_seq != cond->__data.__broadcast_seq)
+ goto bc_out;
+
+ goto timeout;
+ }
+#endif
+
+ unsigned int futex_val = cond->__data.__futex;
+
+ /* Prepare to wait. Release the condvar futex. */
+ lll_unlock (cond->__data.__lock, pshared);
+
+ /* Enable asynchronous cancellation. Required by the standard. */
+ cbuffer.oldtype = __pthread_enable_asynccancel ();
+
+/* REQUEUE_PI was implemented after FUTEX_CLOCK_REALTIME, so it is sufficient
+ to check just the former. */
+#if (defined lll_futex_timed_wait_requeue_pi \
+ && defined __ASSUME_REQUEUE_PI)
+ /* If pi_flag remained 1 then it means that we had the lock and the mutex
+ but a spurious waker raced ahead of us. Give back the mutex before
+ going into wait again. */
+ if (pi_flag)
+ {
+ __pthread_mutex_cond_lock_adjust (mutex);
+ __pthread_mutex_unlock_usercnt (mutex, 0);
+ }
+ pi_flag = USE_REQUEUE_PI (mutex);
+
+ if (pi_flag)
+ {
+ unsigned int clockbit = (cond->__data.__nwaiters & 1
+ ? 0 : FUTEX_CLOCK_REALTIME);
+ err = lll_futex_timed_wait_requeue_pi (&cond->__data.__futex,
+ futex_val, abstime, clockbit,
+ &mutex->__data.__lock,
+ pshared);
+ pi_flag = (err == 0);
+ }
+ else
+#endif
+
+ {
+#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \
+ || !defined lll_futex_timed_wait_bitset)
+ /* Wait until woken by signal or broadcast. */
+ err = lll_futex_timed_wait (&cond->__data.__futex,
+ futex_val, &rt, pshared);
+#else
+ unsigned int clockbit = (cond->__data.__nwaiters & 1
+ ? 0 : FUTEX_CLOCK_REALTIME);
+ err = lll_futex_timed_wait_bitset (&cond->__data.__futex, futex_val,
+ abstime, clockbit, pshared);
+#endif
+ }
+
+ /* Disable asynchronous cancellation. */
+ __pthread_disable_asynccancel (cbuffer.oldtype);
+
+ /* We are going to look at shared data again, so get the lock. */
+ lll_lock (cond->__data.__lock, pshared);
+
+ /* If a broadcast happened, we are done. */
+ if (cbuffer.bc_seq != cond->__data.__broadcast_seq)
+ goto bc_out;
+
+ /* Check whether we are eligible for wakeup. */
+ val = cond->__data.__wakeup_seq;
+ if (val != seq && cond->__data.__woken_seq != val)
+ break;
+
+ /* Not woken yet. Maybe the time expired? */
+ if (__glibc_unlikely (err == -ETIMEDOUT))
+ {
+ timeout:
+ /* Yep. Adjust the counters. */
+ ++cond->__data.__wakeup_seq;
+ ++cond->__data.__futex;
+
+ /* The error value. */
+ result = ETIMEDOUT;
+ break;
+ }
+ }
+
+ /* Another thread woken up. */
+ ++cond->__data.__woken_seq;
+
+ bc_out:
+
+ cond->__data.__nwaiters -= 1 << COND_NWAITERS_SHIFT;
+
+ /* If pthread_cond_destroy was called on this variable already,
+ notify the pthread_cond_destroy caller all waiters have left
+ and it can be successfully destroyed. */
+ if (cond->__data.__total_seq == -1ULL
+ && cond->__data.__nwaiters < (1 << COND_NWAITERS_SHIFT))
+ lll_futex_wake (&cond->__data.__nwaiters, 1, pshared);
+
+ /* We are done with the condvar. */
+ lll_unlock (cond->__data.__lock, pshared);
+
+ /* The cancellation handling is back to normal, remove the handler. */
+ __pthread_cleanup_pop (&buffer, 0);
+
+ /* Get the mutex before returning. */
+#if (defined lll_futex_timed_wait_requeue_pi \
+ && defined __ASSUME_REQUEUE_PI)
+ if (pi_flag)
+ {
+ __pthread_mutex_cond_lock_adjust (mutex);
+ err = 0;
+ }
+ else
+#endif
+ err = __pthread_mutex_cond_lock (mutex);
+
+ return err ?: result;
+}
+
+versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
+ GLIBC_2_3_2);
diff --git a/nptl_2_17/pthread_cond_wait_2_17.c b/nptl_2_17/pthread_cond_wait_2_17.c
new file mode 100644
index 00000000..966ecab1
--- /dev/null
+++ b/nptl_2_17/pthread_cond_wait_2_17.c
@@ -0,0 +1,234 @@
+/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "bits/thread-shared-types_2_17.h"
+#include <sysdep_2_17.h>
+#include <lowlevellock_2_17.h>
+#include "kernel-features_2_17.h"
+#include "pthread_2_17.h"
+#include "pthreadP_2_17.h"
+
+#include <endian.h>
+#include <errno.h>
+
+#include <shlib-compat.h>
+#include <stap-probe.h>
+
+struct _condvar_cleanup_buffer
+{
+ int oldtype;
+ pthread_cond_t *cond;
+ pthread_mutex_t *mutex;
+ unsigned int bc_seq;
+};
+
+void
+__attribute__ ((visibility ("hidden")))
+__condvar_cleanup (void *arg)
+{
+ struct _condvar_cleanup_buffer *cbuffer =
+ (struct _condvar_cleanup_buffer *) arg;
+ unsigned int destroying;
+ int pshared = (cbuffer->cond->__data.__mutex == (void *) ~0l)
+ ? LLL_SHARED : LLL_PRIVATE;
+
+ /* We are going to modify shared data. */
+ lll_lock (cbuffer->cond->__data.__lock, pshared);
+
+ if (cbuffer->bc_seq == cbuffer->cond->__data.__broadcast_seq)
+ {
+ /* This thread is not waiting anymore. Adjust the sequence counters
+ * appropriately. We do not increment WAKEUP_SEQ if this would
+ * bump it over the value of TOTAL_SEQ. This can happen if a thread
+ * was woken and then canceled. */
+ if (cbuffer->cond->__data.__wakeup_seq
+ < cbuffer->cond->__data.__total_seq)
+ {
+ ++cbuffer->cond->__data.__wakeup_seq;
+ ++cbuffer->cond->__data.__futex;
+ }
+ ++cbuffer->cond->__data.__woken_seq;
+ }
+
+ cbuffer->cond->__data.__nwaiters -= 1 << COND_NWAITERS_SHIFT;
+
+ /* If pthread_cond_destroy was called on this variable already,
+ * notify the pthread_cond_destroy caller all waiters have left
+ * and it can be successfully destroyed. */
+ destroying = 0;
+ if (cbuffer->cond->__data.__total_seq == -1ULL
+ && cbuffer->cond->__data.__nwaiters < (1 << COND_NWAITERS_SHIFT))
+ {
+ lll_futex_wake (&cbuffer->cond->__data.__nwaiters, 1, pshared);
+ destroying = 1;
+ }
+
+ /* We are done. */
+ lll_unlock (cbuffer->cond->__data.__lock, pshared);
+
+ /* Wake everybody to make sure no condvar signal gets lost. */
+ if (! destroying)
+ lll_futex_wake (&cbuffer->cond->__data.__futex, INT_MAX, pshared);
+
+ /* Get the mutex before returning unless asynchronous cancellation
+ * is in effect. We don't try to get the mutex if we already own it. */
+ if (!(USE_REQUEUE_PI (cbuffer->mutex))
+ || ((cbuffer->mutex->__data.__lock & FUTEX_TID_MASK)
+ != THREAD_GETMEM (THREAD_SELF, tid)))
+ {
+ __pthread_mutex_cond_lock (cbuffer->mutex);
+ }
+ else
+ __pthread_mutex_cond_lock_adjust (cbuffer->mutex);
+}
+
+int
+__pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
+{
+struct _pthread_cleanup_buffer buffer;
+ struct _condvar_cleanup_buffer cbuffer;
+ int err;
+ int pshared = (cond->__data.__mutex == (void *) ~0l)
+ ? LLL_SHARED : LLL_PRIVATE;
+
+#if (defined lll_futex_wait_requeue_pi \
+ && defined __ASSUME_REQUEUE_PI)
+ int pi_flag = 0;
+#endif
+
+ LIBC_PROBE (cond_wait, 2, cond, mutex);
+ /* Make sure we are alone. */
+ lll_lock (cond->__data.__lock, pshared);
+
+ /* Now we can release the mutex. */
+ err = __pthread_mutex_unlock_usercnt (mutex, 0);
+ if (__glibc_unlikely (err))
+ {
+ lll_unlock (cond->__data.__lock, pshared);
+ return err;
+ }
+ /* We have one new user of the condvar. */
+ ++cond->__data.__total_seq;
+ ++cond->__data.__futex;
+ cond->__data.__nwaiters += 1 << COND_NWAITERS_SHIFT;
+
+ /* Remember the mutex we are using here. If there is already a
+ * different address store this is a bad user bug. Do not store
+ * anything for pshared condvars. */
+ if (cond->__data.__mutex != (void *) ~0l)
+ cond->__data.__mutex = mutex;
+
+ /* Prepare structure passed to cancellation handler. */
+ cbuffer.cond = cond;
+ cbuffer.mutex = mutex;
+
+ /* Before we block we enable cancellation. Therefore we have to
+ * install a cancellation handler. */
+ __pthread_cleanup_push (&buffer, __condvar_cleanup, &cbuffer);
+
+ /* The current values of the wakeup counter. The "woken" counter
+ * must exceed this value. */
+ unsigned long long int val;
+ unsigned long long int seq;
+ val = seq = cond->__data.__wakeup_seq;
+ /* Remember the broadcast counter. */
+ cbuffer.bc_seq = cond->__data.__broadcast_seq;
+
+ do
+ {
+ unsigned int futex_val = cond->__data.__futex;
+ /* Prepare to wait. Release the condvar futex. */
+ lll_unlock (cond->__data.__lock, pshared);
+
+ /* Enable asynchronous cancellation. Required by the standard. */
+ cbuffer.oldtype = __pthread_enable_asynccancel ();
+
+#if (defined lll_futex_wait_requeue_pi \
+ && defined __ASSUME_REQUEUE_PI)
+ /* If pi_flag remained 1 then it means that we had the lock and the mutex
+ but a spurious waker raced ahead of us. Give back the mutex before
+ going into wait again. */
+ if (pi_flag)
+ {
+ __pthread_mutex_cond_lock_adjust (mutex);
+ __pthread_mutex_unlock_usercnt (mutex, 0);
+ }
+ pi_flag = USE_REQUEUE_PI (mutex);
+
+ if (pi_flag)
+ {
+ err = lll_futex_wait_requeue_pi (&cond->__data.__futex,
+ futex_val, &mutex->__data.__lock,
+ pshared);
+
+ pi_flag = (err == 0);
+ }
+ else
+#endif
+ /* Wait until woken by signal or broadcast. */
+ lll_futex_wait (&cond->__data.__futex, futex_val, pshared);
+
+ /* Disable asynchronous cancellation. */
+ __pthread_disable_asynccancel (cbuffer.oldtype);
+
+ /* We are going to look at shared data again, so get the lock. */
+ lll_lock (cond->__data.__lock, pshared);
+
+ /* If a broadcast happened, we are done. */
+ if (cbuffer.bc_seq != cond->__data.__broadcast_seq)
+ goto bc_out;
+
+ /* Check whether we are eligible for wakeup. */
+ val = cond->__data.__wakeup_seq;
+ }
+ while (val == seq || cond->__data.__woken_seq == val);
+
+ /* Another thread woken up. */
+ ++cond->__data.__woken_seq;
+
+bc_out:
+ cond->__data.__nwaiters -= 1 << COND_NWAITERS_SHIFT;
+
+ /* If pthread_cond_destroy was called on this varaible already,
+ notify the pthread_cond_destroy caller all waiters have left
+ and it can be successfully destroyed. */
+ if (cond->__data.__total_seq == -1ULL
+ && cond->__data.__nwaiters < (1 << COND_NWAITERS_SHIFT))
+ lll_futex_wake (&cond->__data.__nwaiters, 1, pshared);
+
+ /* We are done with the condvar. */
+ lll_unlock (cond->__data.__lock, pshared);
+
+ /* The cancellation handling is back to normal, remove the handler. */
+ __pthread_cleanup_pop (&buffer, 0);
+
+ /* Get the mutex before returning. Not needed for PI. */
+#if (defined lll_futex_wait_requeue_pi \
+ && defined __ASSUME_REQUEUE_PI)
+ if (pi_flag)
+ {
+ __pthread_mutex_cond_lock_adjust (mutex);
+ return 0;
+ }
+ else
+#endif
+ return __pthread_mutex_cond_lock (mutex);
+}
+
+versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
+ GLIBC_2_3_2);
diff --git a/nptl_2_17/pthread_condattr_getclock_2_17.c b/nptl_2_17/pthread_condattr_getclock_2_17.c
new file mode 100644
index 00000000..414a6856
--- /dev/null
+++ b/nptl_2_17/pthread_condattr_getclock_2_17.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP_2_17.h"
+
+
+int
+pthread_condattr_getclock (const pthread_condattr_t *attr, clockid_t *clock_id)
+{
+ *clock_id = (((((const struct pthread_condattr *) attr)->value) >> 1)
+ & ((1 << COND_NWAITERS_SHIFT) - 1));
+ return 0;
+}
diff --git a/nptl_2_17/pthread_condattr_getpshared_2_17.c b/nptl_2_17/pthread_condattr_getpshared_2_17.c
new file mode 100644
index 00000000..2b85506f
--- /dev/null
+++ b/nptl_2_17/pthread_condattr_getpshared_2_17.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received 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_2_17.h"
+
+
+int
+pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared)
+{
+ *pshared = ((const struct pthread_condattr *) attr)->value & 1;
+
+ return 0;
+}
diff --git a/nptl_2_17/pthread_condattr_init_2_17.c b/nptl_2_17/pthread_condattr_init_2_17.c
new file mode 100644
index 00000000..427a349c
--- /dev/null
+++ b/nptl_2_17/pthread_condattr_init_2_17.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received 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_2_17.h"
+#include <string.h>
+
+
+int
+__pthread_condattr_init (pthread_condattr_t *attr)
+{
+ ASSERT_TYPE_SIZE (pthread_condattr_t, __SIZEOF_PTHREAD_CONDATTR_T);
+ ASSERT_PTHREAD_INTERNAL_SIZE (pthread_condattr_t,
+ struct pthread_condattr);
+
+memset (attr, '\0', sizeof (*attr));
+ return 0;
+}
+strong_alias (__pthread_condattr_init, pthread_condattr_init)
diff --git a/nptl_2_17/pthread_condattr_setclock_2_17.c b/nptl_2_17/pthread_condattr_setclock_2_17.c
new file mode 100644
index 00000000..69c64dcb
--- /dev/null
+++ b/nptl_2_17/pthread_condattr_setclock_2_17.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP_2_17.h"
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sysdep.h>
+
+
+int
+pthread_condattr_setclock (pthread_condattr_t *attr, clockid_t clock_id)
+{
+ /* Only a few clocks are allowed. */
+ if (clock_id != CLOCK_MONOTONIC && clock_id != CLOCK_REALTIME)
+ /* If more clocks are allowed some day the storing of the clock ID
+ in the pthread_cond_t structure needs to be adjusted. */
+ return EINVAL;
+
+ /* Make sure the value fits in the bits we reserved. */
+ assert (clock_id < (1 << COND_NWAITERS_SHIFT));
+
+ int *valuep = &((struct pthread_condattr *) attr)->value;
+
+ *valuep = ((*valuep & ~(((1 << COND_NWAITERS_SHIFT) - 1) << 1))
+ | (clock_id << 1));
+
+ return 0;
+}
diff --git a/nptl_2_17/pthread_mutex_cond_lock_2_17.c b/nptl_2_17/pthread_mutex_cond_lock_2_17.c
new file mode 100644
index 00000000..674ae77b
--- /dev/null
+++ b/nptl_2_17/pthread_mutex_cond_lock_2_17.c
@@ -0,0 +1,21 @@
+#include <pthreadP_2_17.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)
+
+/* We need to assume that there are other threads blocked on the futex.
+ See __pthread_mutex_lock_full for further details. */
+#define LLL_ROBUST_MUTEX_LOCK_MODIFIER FUTEX_WAITERS
+#define __pthread_mutex_lock __pthread_mutex_cond_lock
+#define __pthread_mutex_lock_full __pthread_mutex_cond_lock_full
+#define NO_INCR
+
+#include <pthread_mutex_lock_2_17.c>
diff --git a/nptl_2_17/pthread_mutex_lock_2_17.c b/nptl_2_17/pthread_mutex_lock_2_17.c
new file mode 100644
index 00000000..787f37b0
--- /dev/null
+++ b/nptl_2_17/pthread_mutex_lock_2_17.c
@@ -0,0 +1,635 @@
+/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received 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_2_17.h"
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <not-cancel_2_17.h>
+#include <atomic.h>
+#include <lowlevellock_2_17.h>
+#include <stap-probe.h>
+
+#ifndef lll_lock_elision
+#define lll_lock_elision(lock, try_lock, private) ({ \
+ lll_lock (lock, private); 0; })
+#endif
+
+#ifndef lll_trylock_elision
+#define lll_trylock_elision(a,t) lll_trylock(a)
+#endif
+
+/* Some of the following definitions differ when pthread_mutex_cond_lock.c
+ includes this file. */
+#ifndef LLL_MUTEX_LOCK
+# define LLL_MUTEX_LOCK(mutex) \
+ lll_lock ((mutex)->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex))
+# define LLL_MUTEX_TRYLOCK(mutex) \
+ lll_trylock ((mutex)->__data.__lock)
+# define LLL_ROBUST_MUTEX_LOCK_MODIFIER 0
+# define LLL_MUTEX_LOCK_ELISION(mutex) \
+ lll_lock_elision ((mutex)->__data.__lock, (mutex)->__data.__elision, \
+ PTHREAD_MUTEX_PSHARED (mutex))
+# define LLL_MUTEX_TRYLOCK_ELISION(mutex) \
+ lll_trylock_elision((mutex)->__data.__lock, (mutex)->__data.__elision, \
+ PTHREAD_MUTEX_PSHARED (mutex))
+#endif
+
+#ifndef FORCE_ELISION
+#define FORCE_ELISION(m, s)
+#endif
+
+static int __pthread_mutex_lock_full (pthread_mutex_t *mutex)
+ __attribute_noinline__;
+
+int
+__pthread_mutex_lock (pthread_mutex_t *mutex)
+{
+ /* See concurrency notes regarding mutex type which is loaded from __kind
+ in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */
+ unsigned int type = PTHREAD_MUTEX_TYPE_ELISION (mutex);
+
+ LIBC_PROBE (mutex_entry, 1, mutex);
+
+ if (__builtin_expect (type & ~(PTHREAD_MUTEX_KIND_MASK_NP
+ | PTHREAD_MUTEX_ELISION_FLAGS_NP), 0))
+ return __pthread_mutex_lock_full (mutex);
+
+ if (__glibc_likely (type == PTHREAD_MUTEX_TIMED_NP))
+ {
+ FORCE_ELISION (mutex, goto elision);
+ simple:
+ /* Normal mutex. */
+ LLL_MUTEX_LOCK (mutex);
+ assert (mutex->__data.__owner == 0);
+ }
+#ifdef HAVE_ELISION
+ else if (__glibc_likely (type == PTHREAD_MUTEX_TIMED_ELISION_NP))
+ {
+ elision: __attribute__((unused))
+ /* This case can never happen on a system without elision,
+ as the mutex type initialization functions will not
+ allow to set the elision flags. */
+ /* Don't record owner or users for elision case. This is a
+ tail call. */
+ return LLL_MUTEX_LOCK_ELISION (mutex);
+ }
+#endif
+ else if (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex)
+ == PTHREAD_MUTEX_RECURSIVE_NP, 1))
+ {
+ /* Recursive mutex. */
+ pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
+
+ /* Check whether we already hold the mutex. */
+ if (mutex->__data.__owner == id)
+ {
+ /* Just bump the counter. */
+ if (__glibc_unlikely (mutex->__data.__count + 1 == 0))
+ /* Overflow of the counter. */
+ return EAGAIN;
+
+ ++mutex->__data.__count;
+
+ return 0;
+ }
+
+ /* We have to get the mutex. */
+ LLL_MUTEX_LOCK (mutex);
+
+ assert (mutex->__data.__owner == 0);
+ mutex->__data.__count = 1;
+ }
+ else if (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex)
+ == PTHREAD_MUTEX_ADAPTIVE_NP, 1))
+ {
+ if (! __is_smp)
+ goto simple;
+
+ if (LLL_MUTEX_TRYLOCK (mutex) != 0)
+ {
+ int cnt = 0;
+ int max_cnt = MIN (MAX_ADAPTIVE_COUNT,
+ mutex->__data.__spins * 2 + 10);
+ do
+ {
+ if (cnt++ >= max_cnt)
+ {
+ LLL_MUTEX_LOCK (mutex);
+ break;
+ }
+ atomic_spin_nop ();
+ }
+ while (LLL_MUTEX_TRYLOCK (mutex) != 0);
+
+ mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8;
+ }
+ assert (mutex->__data.__owner == 0);
+ }
+ else
+ {
+ pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
+ assert (PTHREAD_MUTEX_TYPE (mutex) == PTHREAD_MUTEX_ERRORCHECK_NP);
+ /* Check whether we already hold the mutex. */
+ if (__glibc_unlikely (mutex->__data.__owner == id))
+ return EDEADLK;
+ goto simple;
+ }
+
+ pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
+
+ /* Record the ownership. */
+ mutex->__data.__owner = id;
+#ifndef NO_INCR
+ ++mutex->__data.__nusers;
+#endif
+
+ LIBC_PROBE (mutex_acquired, 1, mutex);
+
+ return 0;
+}
+
+static int
+__pthread_mutex_lock_full (pthread_mutex_t *mutex)
+{
+ int oldval;
+ pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
+
+ switch (PTHREAD_MUTEX_TYPE (mutex))
+ {
+ case PTHREAD_MUTEX_ROBUST_RECURSIVE_NP:
+ case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP:
+ case PTHREAD_MUTEX_ROBUST_NORMAL_NP:
+ case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP:
+ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
+ &mutex->__data.__list.__next);
+ /* We need to set op_pending before starting the operation. Also
+ see comments at ENQUEUE_MUTEX. */
+ __asm ("" ::: "memory");
+
+ oldval = mutex->__data.__lock;
+ /* This is set to FUTEX_WAITERS iff we might have shared the
+ FUTEX_WAITERS flag with other threads, and therefore need to keep it
+ set to avoid lost wake-ups. We have the same requirement in the
+ simple mutex algorithm.
+ We start with value zero for a normal mutex, and FUTEX_WAITERS if we
+ are building the special case mutexes for use from within condition
+ variables. */
+ unsigned int assume_other_futex_waiters = LLL_ROBUST_MUTEX_LOCK_MODIFIER;
+ while (1)
+ {
+ /* Try to acquire the lock through a CAS from 0 (not acquired) to
+ our TID | assume_other_futex_waiters. */
+ if (__glibc_likely (oldval == 0))
+ {
+ oldval
+ = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+ id | assume_other_futex_waiters, 0);
+ if (__glibc_likely (oldval == 0))
+ break;
+ }
+
+ if ((oldval & FUTEX_OWNER_DIED) != 0)
+ {
+ /* The previous owner died. Try locking the mutex. */
+ int newval = id;
+#ifdef NO_INCR
+ /* We are not taking assume_other_futex_waiters into accoount
+ here simply because we'll set FUTEX_WAITERS anyway. */
+ newval |= FUTEX_WAITERS;
+#else
+ newval |= (oldval & FUTEX_WAITERS) | assume_other_futex_waiters;
+#endif
+
+ newval
+ = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+ newval, oldval);
+
+ if (newval != oldval)
+ {
+ oldval = newval;
+ continue;
+ }
+
+ /* We got the mutex. */
+ mutex->__data.__count = 1;
+ /* But it is inconsistent unless marked otherwise. */
+ mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
+
+ /* We must not enqueue the mutex before we have acquired it.
+ Also see comments at ENQUEUE_MUTEX. */
+ __asm ("" ::: "memory");
+ ENQUEUE_MUTEX (mutex);
+ /* We need to clear op_pending after we enqueue the mutex. */
+ __asm ("" ::: "memory");
+ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+
+ /* Note that we deliberately exit here. If we fall
+ through to the end of the function __nusers would be
+ incremented which is not correct because the old
+ owner has to be discounted. If we are not supposed
+ to increment __nusers we actually have to decrement
+ it here. */
+#ifdef NO_INCR
+ --mutex->__data.__nusers;
+#endif
+
+ return EOWNERDEAD;
+ }
+
+ /* Check whether we already hold the mutex. */
+ if (__glibc_unlikely ((oldval & FUTEX_TID_MASK) == id))
+ {
+ int kind = PTHREAD_MUTEX_TYPE (mutex);
+ if (kind == PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP)
+ {
+ /* We do not need to ensure ordering wrt another memory
+ access. Also see comments at ENQUEUE_MUTEX. */
+ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
+ NULL);
+ return EDEADLK;
+ }
+
+ if (kind == PTHREAD_MUTEX_ROBUST_RECURSIVE_NP)
+ {
+ /* We do not need to ensure ordering wrt another memory
+ access. */
+ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
+ NULL);
+
+ /* Just bump the counter. */
+ if (__glibc_unlikely (mutex->__data.__count + 1 == 0))
+ /* Overflow of the counter. */
+ return EAGAIN;
+
+ ++mutex->__data.__count;
+
+ return 0;
+ }
+ }
+
+ /* We cannot acquire the mutex nor has its owner died. Thus, try
+ to block using futexes. Set FUTEX_WAITERS if necessary so that
+ other threads are aware that there are potentially threads
+ blocked on the futex. Restart if oldval changed in the
+ meantime. */
+ if ((oldval & FUTEX_WAITERS) == 0)
+ {
+ if (atomic_compare_and_exchange_bool_acq (&mutex->__data.__lock,
+ oldval | FUTEX_WAITERS,
+ oldval)
+ != 0)
+ {
+ oldval = mutex->__data.__lock;
+ continue;
+ }
+ oldval |= FUTEX_WAITERS;
+ }
+
+ /* It is now possible that we share the FUTEX_WAITERS flag with
+ another thread; therefore, update assume_other_futex_waiters so
+ that we do not forget about this when handling other cases
+ above and thus do not cause lost wake-ups. */
+ assume_other_futex_waiters |= FUTEX_WAITERS;
+
+ /* Block using the futex and reload current lock value. */
+ lll_futex_wait (&mutex->__data.__lock, oldval,
+ PTHREAD_ROBUST_MUTEX_PSHARED (mutex));
+ oldval = mutex->__data.__lock;
+ }
+
+ /* We have acquired the mutex; check if it is still consistent. */
+ if (__builtin_expect (mutex->__data.__owner
+ == PTHREAD_MUTEX_NOTRECOVERABLE, 0))
+ {
+ /* This mutex is now not recoverable. */
+ mutex->__data.__count = 0;
+ int private = PTHREAD_ROBUST_MUTEX_PSHARED (mutex);
+ lll_unlock (mutex->__data.__lock, private);
+ /* FIXME This violates the mutex destruction requirements. See
+ __pthread_mutex_unlock_full. */
+ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+ return ENOTRECOVERABLE;
+ }
+
+ mutex->__data.__count = 1;
+ /* We must not enqueue the mutex before we have acquired it.
+ Also see comments at ENQUEUE_MUTEX. */
+ __asm ("" ::: "memory");
+ ENQUEUE_MUTEX (mutex);
+ /* We need to clear op_pending after we enqueue the mutex. */
+ __asm ("" ::: "memory");
+ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+ break;
+
+ /* The PI support requires the Linux futex system call. If that's not
+ available, pthread_mutex_init should never have allowed the type to
+ be set. So it will get the default case for an invalid type. */
+#ifdef __NR_futex
+ case PTHREAD_MUTEX_PI_RECURSIVE_NP:
+ case PTHREAD_MUTEX_PI_ERRORCHECK_NP:
+ case PTHREAD_MUTEX_PI_NORMAL_NP:
+ case PTHREAD_MUTEX_PI_ADAPTIVE_NP:
+ case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP:
+ case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP:
+ case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
+ case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
+ {
+ int kind, robust;
+ {
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
+ in sysdeps/nptl/bits/thread-shared-types.h. */
+ int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind));
+ kind = mutex_kind & PTHREAD_MUTEX_KIND_MASK_NP;
+ robust = mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
+ }
+
+ if (robust)
+ {
+ /* Note: robust PI futexes are signaled by setting bit 0. */
+ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
+ (void *) (((uintptr_t) &mutex->__data.__list.__next)
+ | 1));
+ /* We need to set op_pending before starting the operation. Also
+ see comments at ENQUEUE_MUTEX. */
+ __asm ("" ::: "memory");
+ }
+
+ oldval = mutex->__data.__lock;
+
+ /* Check whether we already hold the mutex. */
+ if (__glibc_unlikely ((oldval & FUTEX_TID_MASK) == id))
+ {
+ if (kind == PTHREAD_MUTEX_ERRORCHECK_NP)
+ {
+ /* We do not need to ensure ordering wrt another memory
+ access. */
+ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+ return EDEADLK;
+ }
+
+ if (kind == PTHREAD_MUTEX_RECURSIVE_NP)
+ {
+ /* We do not need to ensure ordering wrt another memory
+ access. */
+ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+
+ /* Just bump the counter. */
+ if (__glibc_unlikely (mutex->__data.__count + 1 == 0))
+ /* Overflow of the counter. */
+ return EAGAIN;
+
+ ++mutex->__data.__count;
+
+ return 0;
+ }
+ }
+
+ int newval = id;
+# ifdef NO_INCR
+ newval |= FUTEX_WAITERS;
+# endif
+ oldval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+ newval, 0);
+
+ if (oldval != 0)
+ {
+ /* The mutex is locked. The kernel will now take care of
+ everything. */
+ int private = (robust
+ ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex)
+ : PTHREAD_MUTEX_PSHARED (mutex));
+ INTERNAL_SYSCALL_DECL (__err);
+ int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock,
+ __lll_private_flag (FUTEX_LOCK_PI,
+ private), 1, 0);
+
+ if (INTERNAL_SYSCALL_ERROR_P (e, __err)
+ && (INTERNAL_SYSCALL_ERRNO (e, __err) == ESRCH
+ || INTERNAL_SYSCALL_ERRNO (e, __err) == EDEADLK))
+ {
+ assert (INTERNAL_SYSCALL_ERRNO (e, __err) != EDEADLK
+ || (kind != PTHREAD_MUTEX_ERRORCHECK_NP
+ && kind != PTHREAD_MUTEX_RECURSIVE_NP));
+ /* ESRCH can happen only for non-robust PI mutexes where
+ the owner of the lock died. */
+ assert (INTERNAL_SYSCALL_ERRNO (e, __err) != ESRCH || !robust);
+
+ /* Delay the thread indefinitely. */
+ while (1)
+ pause ();
+ }
+
+ oldval = mutex->__data.__lock;
+
+ assert (robust || (oldval & FUTEX_OWNER_DIED) == 0);
+ }
+
+ if (__glibc_unlikely (oldval & FUTEX_OWNER_DIED))
+ {
+ atomic_and (&mutex->__data.__lock, ~FUTEX_OWNER_DIED);
+
+ /* We got the mutex. */
+ mutex->__data.__count = 1;
+ /* But it is inconsistent unless marked otherwise. */
+ mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
+
+ /* We must not enqueue the mutex before we have acquired it.
+ Also see comments at ENQUEUE_MUTEX. */
+ __asm ("" ::: "memory");
+ ENQUEUE_MUTEX_PI (mutex);
+ /* We need to clear op_pending after we enqueue the mutex. */
+ __asm ("" ::: "memory");
+ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+
+ /* Note that we deliberately exit here. If we fall
+ through to the end of the function __nusers would be
+ incremented which is not correct because the old owner
+ has to be discounted. If we are not supposed to
+ increment __nusers we actually have to decrement it here. */
+# ifdef NO_INCR
+ --mutex->__data.__nusers;
+# endif
+
+ return EOWNERDEAD;
+ }
+
+ if (robust
+ && __builtin_expect (mutex->__data.__owner
+ == PTHREAD_MUTEX_NOTRECOVERABLE, 0))
+ {
+ /* This mutex is now not recoverable. */
+ mutex->__data.__count = 0;
+
+ INTERNAL_SYSCALL_DECL (__err);
+ INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock,
+ __lll_private_flag (FUTEX_UNLOCK_PI,
+ PTHREAD_ROBUST_MUTEX_PSHARED (mutex)),
+ 0, 0);
+
+ /* To the kernel, this will be visible after the kernel has
+ acquired the mutex in the syscall. */
+ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+ return ENOTRECOVERABLE;
+ }
+
+ mutex->__data.__count = 1;
+ if (robust)
+ {
+ /* We must not enqueue the mutex before we have acquired it.
+ Also see comments at ENQUEUE_MUTEX. */
+ __asm ("" ::: "memory");
+ ENQUEUE_MUTEX_PI (mutex);
+ /* We need to clear op_pending after we enqueue the mutex. */
+ __asm ("" ::: "memory");
+ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+ }
+ }
+ break;
+#endif /* __NR_futex. */
+
+ case PTHREAD_MUTEX_PP_RECURSIVE_NP:
+ case PTHREAD_MUTEX_PP_ERRORCHECK_NP:
+ case PTHREAD_MUTEX_PP_NORMAL_NP:
+ case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
+ {
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
+ in sysdeps/nptl/bits/thread-shared-types.h. */
+ int kind = atomic_load_relaxed (&(mutex->__data.__kind))
+ & PTHREAD_MUTEX_KIND_MASK_NP;
+
+ oldval = mutex->__data.__lock;
+
+ /* Check whether we already hold the mutex. */
+ if (mutex->__data.__owner == id)
+ {
+ if (kind == PTHREAD_MUTEX_ERRORCHECK_NP)
+ return EDEADLK;
+
+ if (kind == PTHREAD_MUTEX_RECURSIVE_NP)
+ {
+ /* Just bump the counter. */
+ if (__glibc_unlikely (mutex->__data.__count + 1 == 0))
+ /* Overflow of the counter. */
+ return EAGAIN;
+
+ ++mutex->__data.__count;
+
+ return 0;
+ }
+ }
+
+ int oldprio = -1, ceilval;
+ do
+ {
+ int ceiling = (oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK)
+ >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
+
+ if (__pthread_current_priority () > ceiling)
+ {
+ if (oldprio != -1)
+ __pthread_tpp_change_priority (oldprio, -1);
+ return EINVAL;
+ }
+
+ int retval = __pthread_tpp_change_priority (oldprio, ceiling);
+ if (retval)
+ return retval;
+
+ ceilval = ceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
+ oldprio = ceiling;
+
+ oldval
+ = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+#ifdef NO_INCR
+ ceilval | 2,
+#else
+ ceilval | 1,
+#endif
+ ceilval);
+
+ if (oldval == ceilval)
+ break;
+
+ do
+ {
+ oldval
+ = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+ ceilval | 2,
+ ceilval | 1);
+
+ if ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval)
+ break;
+
+ if (oldval != ceilval)
+ lll_futex_wait (&mutex->__data.__lock, ceilval | 2,
+ PTHREAD_MUTEX_PSHARED (mutex));
+ }
+ while (atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+ ceilval | 2, ceilval)
+ != ceilval);
+ }
+ while ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval);
+
+ assert (mutex->__data.__owner == 0);
+ mutex->__data.__count = 1;
+ }
+ break;
+
+ default:
+ /* Correct code cannot set any other type. */
+ return EINVAL;
+ }
+
+ /* Record the ownership. */
+ mutex->__data.__owner = id;
+#ifndef NO_INCR
+ ++mutex->__data.__nusers;
+#endif
+
+ LIBC_PROBE (mutex_acquired, 1, mutex);
+
+ return 0;
+}
+#ifndef __pthread_mutex_lock
+weak_alias (__pthread_mutex_lock, pthread_mutex_lock)
+hidden_def (__pthread_mutex_lock)
+#endif
+
+
+#ifdef NO_INCR
+void
+__pthread_mutex_cond_lock_adjust (pthread_mutex_t *mutex)
+{
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
+ in sysdeps/nptl/bits/thread-shared-types.h. */
+ int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind));
+ assert ((mutex_kind & PTHREAD_MUTEX_PRIO_INHERIT_NP) != 0);
+ assert ((mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0);
+ assert ((mutex_kind & PTHREAD_MUTEX_PSHARED_BIT) == 0);
+
+ /* Record the ownership. */
+ pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
+ mutex->__data.__owner = id;
+
+ if (mutex_kind == PTHREAD_MUTEX_PI_RECURSIVE_NP)
+ ++mutex->__data.__count;
+}
+#endif
diff --git a/nptl_2_17/pthread_mutex_unlock_2_17.c b/nptl_2_17/pthread_mutex_unlock_2_17.c
new file mode 100644
index 00000000..cca86029
--- /dev/null
+++ b/nptl_2_17/pthread_mutex_unlock_2_17.c
@@ -0,0 +1,359 @@
+/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received 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_2_17.h"
+#include <lowlevellock_2_17.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stap-probe.h>
+
+#ifndef lll_unlock_elision
+#define lll_unlock_elision(a,b,c) ({ lll_unlock (a,c); 0; })
+#endif
+
+static int
+__pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr)
+ __attribute_noinline__;
+
+int
+attribute_hidden
+__pthread_mutex_unlock_usercnt (pthread_mutex_t *mutex, int decr)
+{
+ /* See concurrency notes regarding mutex type which is loaded from __kind
+ in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */
+ int type = PTHREAD_MUTEX_TYPE_ELISION (mutex);
+ if (__builtin_expect (type &
+ ~(PTHREAD_MUTEX_KIND_MASK_NP|PTHREAD_MUTEX_ELISION_FLAGS_NP), 0))
+ return __pthread_mutex_unlock_full (mutex, decr);
+
+ if (__builtin_expect (type, PTHREAD_MUTEX_TIMED_NP)
+ == PTHREAD_MUTEX_TIMED_NP)
+ {
+ /* Always reset the owner field. */
+ normal:
+ mutex->__data.__owner = 0;
+ if (decr)
+ /* One less user. */
+ --mutex->__data.__nusers;
+
+ /* Unlock. */
+ lll_unlock (mutex->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex));
+
+ LIBC_PROBE (mutex_release, 1, mutex);
+
+ return 0;
+ }
+ else if (__glibc_likely (type == PTHREAD_MUTEX_TIMED_ELISION_NP))
+ {
+ /* Don't reset the owner/users fields for elision. */
+ return lll_unlock_elision (mutex->__data.__lock, mutex->__data.__elision,
+ PTHREAD_MUTEX_PSHARED (mutex));
+ }
+ else if (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex)
+ == PTHREAD_MUTEX_RECURSIVE_NP, 1))
+ {
+ /* Recursive mutex. */
+ if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
+ return EPERM;
+
+ if (--mutex->__data.__count != 0)
+ /* We still hold the mutex. */
+ return 0;
+ goto normal;
+ }
+ else if (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex)
+ == PTHREAD_MUTEX_ADAPTIVE_NP, 1))
+ goto normal;
+ else
+ {
+ /* Error checking mutex. */
+ assert (type == PTHREAD_MUTEX_ERRORCHECK_NP);
+ if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)
+ || ! lll_islocked (mutex->__data.__lock))
+ return EPERM;
+ goto normal;
+ }
+}
+
+
+static int
+__pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr)
+{
+ int newowner = 0;
+ int private;
+
+ switch (PTHREAD_MUTEX_TYPE (mutex))
+ {
+ case PTHREAD_MUTEX_ROBUST_RECURSIVE_NP:
+ /* Recursive mutex. */
+ if ((mutex->__data.__lock & FUTEX_TID_MASK)
+ == THREAD_GETMEM (THREAD_SELF, tid)
+ && __builtin_expect (mutex->__data.__owner
+ == PTHREAD_MUTEX_INCONSISTENT, 0))
+ {
+ if (--mutex->__data.__count != 0)
+ /* We still hold the mutex. */
+ return ENOTRECOVERABLE;
+
+ goto notrecoverable;
+ }
+
+ if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
+ return EPERM;
+
+ if (--mutex->__data.__count != 0)
+ /* We still hold the mutex. */
+ return 0;
+
+ goto robust;
+
+ case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP:
+ case PTHREAD_MUTEX_ROBUST_NORMAL_NP:
+ case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP:
+ if ((mutex->__data.__lock & FUTEX_TID_MASK)
+ != THREAD_GETMEM (THREAD_SELF, tid)
+ || ! lll_islocked (mutex->__data.__lock))
+ return EPERM;
+
+ /* If the previous owner died and the caller did not succeed in
+ making the state consistent, mark the mutex as unrecoverable
+ and make all waiters. */
+ if (__builtin_expect (mutex->__data.__owner
+ == PTHREAD_MUTEX_INCONSISTENT, 0))
+ notrecoverable:
+ newowner = PTHREAD_MUTEX_NOTRECOVERABLE;
+
+ robust:
+ /* Remove mutex from the list. */
+ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
+ &mutex->__data.__list.__next);
+ /* We must set op_pending before we dequeue the mutex. Also see
+ comments at ENQUEUE_MUTEX. */
+ __asm ("" ::: "memory");
+ DEQUEUE_MUTEX (mutex);
+
+ mutex->__data.__owner = newowner;
+ if (decr)
+ /* One less user. */
+ --mutex->__data.__nusers;
+
+ /* Unlock by setting the lock to 0 (not acquired); if the lock had
+ FUTEX_WAITERS set previously, then wake any waiters.
+ The unlock operation must be the last access to the mutex to not
+ violate the mutex destruction requirements (see __lll_unlock). */
+ private = PTHREAD_ROBUST_MUTEX_PSHARED (mutex);
+ if (__glibc_unlikely ((atomic_exchange_rel (&mutex->__data.__lock, 0)
+ & FUTEX_WAITERS) != 0))
+ lll_futex_wake (&mutex->__data.__lock, 1, private);
+
+ /* We must clear op_pending after we release the mutex.
+ FIXME However, this violates the mutex destruction requirements
+ because another thread could acquire the mutex, destroy it, and
+ reuse the memory for something else; then, if this thread crashes,
+ and the memory happens to have a value equal to the TID, the kernel
+ will believe it is still related to the mutex (which has been
+ destroyed already) and will modify some other random object. */
+ __asm ("" ::: "memory");
+ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+ break;
+
+ /* The PI support requires the Linux futex system call. If that's not
+ available, pthread_mutex_init should never have allowed the type to
+ be set. So it will get the default case for an invalid type. */
+#ifdef __NR_futex
+ case PTHREAD_MUTEX_PI_RECURSIVE_NP:
+ /* Recursive mutex. */
+ if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
+ return EPERM;
+
+ if (--mutex->__data.__count != 0)
+ /* We still hold the mutex. */
+ return 0;
+ goto continue_pi_non_robust;
+
+ case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP:
+ /* Recursive mutex. */
+ if ((mutex->__data.__lock & FUTEX_TID_MASK)
+ == THREAD_GETMEM (THREAD_SELF, tid)
+ && __builtin_expect (mutex->__data.__owner
+ == PTHREAD_MUTEX_INCONSISTENT, 0))
+ {
+ if (--mutex->__data.__count != 0)
+ /* We still hold the mutex. */
+ return ENOTRECOVERABLE;
+
+ goto pi_notrecoverable;
+ }
+
+ if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
+ return EPERM;
+
+ if (--mutex->__data.__count != 0)
+ /* We still hold the mutex. */
+ return 0;
+
+ goto continue_pi_robust;
+
+ case PTHREAD_MUTEX_PI_ERRORCHECK_NP:
+ case PTHREAD_MUTEX_PI_NORMAL_NP:
+ case PTHREAD_MUTEX_PI_ADAPTIVE_NP:
+ case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP:
+ case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
+ case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
+ if ((mutex->__data.__lock & FUTEX_TID_MASK)
+ != THREAD_GETMEM (THREAD_SELF, tid)
+ || ! lll_islocked (mutex->__data.__lock))
+ return EPERM;
+
+ /* If the previous owner died and the caller did not succeed in
+ making the state consistent, mark the mutex as unrecoverable
+ and make all waiters. */
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
+ in sysdeps/nptl/bits/thread-shared-types.h. */
+ if ((atomic_load_relaxed (&(mutex->__data.__kind))
+ & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0
+ && __builtin_expect (mutex->__data.__owner
+ == PTHREAD_MUTEX_INCONSISTENT, 0))
+ pi_notrecoverable:
+ newowner = PTHREAD_MUTEX_NOTRECOVERABLE;
+
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
+ in sysdeps/nptl/bits/thread-shared-types.h. */
+ if ((atomic_load_relaxed (&(mutex->__data.__kind))
+ & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0)
+ {
+ continue_pi_robust:
+ /* Remove mutex from the list.
+ Note: robust PI futexes are signaled by setting bit 0. */
+ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
+ (void *) (((uintptr_t) &mutex->__data.__list.__next)
+ | 1));
+ /* We must set op_pending before we dequeue the mutex. Also see
+ comments at ENQUEUE_MUTEX. */
+ __asm ("" ::: "memory");
+ DEQUEUE_MUTEX (mutex);
+ }
+
+ continue_pi_non_robust:
+ mutex->__data.__owner = newowner;
+ if (decr)
+ /* One less user. */
+ --mutex->__data.__nusers;
+
+ /* Unlock. Load all necessary mutex data before releasing the mutex
+ to not violate the mutex destruction requirements (see
+ lll_unlock). */
+ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
+ in sysdeps/nptl/bits/thread-shared-types.h. */
+ int robust = atomic_load_relaxed (&(mutex->__data.__kind))
+ & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
+ private = (robust
+ ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex)
+ : PTHREAD_MUTEX_PSHARED (mutex));
+ /* Unlock the mutex using a CAS unless there are futex waiters or our
+ TID is not the value of __lock anymore, in which case we let the
+ kernel take care of the situation. Use release MO in the CAS to
+ synchronize with acquire MO in lock acquisitions. */
+ int l = atomic_load_relaxed (&mutex->__data.__lock);
+ do
+ {
+ if (((l & FUTEX_WAITERS) != 0)
+ || (l != THREAD_GETMEM (THREAD_SELF, tid)))
+ {
+ INTERNAL_SYSCALL_DECL (__err);
+ INTERNAL_SYSCALL (futex, __err, 2, &mutex->__data.__lock,
+ __lll_private_flag (FUTEX_UNLOCK_PI, private));
+ break;
+ }
+ }
+ while (!atomic_compare_exchange_weak_release (&mutex->__data.__lock,
+ &l, 0));
+
+ /* This happens after the kernel releases the mutex but violates the
+ mutex destruction requirements; see comments in the code handling
+ PTHREAD_MUTEX_ROBUST_NORMAL_NP. */
+ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
+ break;
+#endif /* __NR_futex. */
+
+ case PTHREAD_MUTEX_PP_RECURSIVE_NP:
+ /* Recursive mutex. */
+ if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
+ return EPERM;
+
+ if (--mutex->__data.__count != 0)
+ /* We still hold the mutex. */
+ return 0;
+ goto pp;
+
+ case PTHREAD_MUTEX_PP_ERRORCHECK_NP:
+ /* Error checking mutex. */
+ if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)
+ || (mutex->__data.__lock & ~ PTHREAD_MUTEX_PRIO_CEILING_MASK) == 0)
+ return EPERM;
+ /* FALLTHROUGH */
+
+ case PTHREAD_MUTEX_PP_NORMAL_NP:
+ case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
+ /* Always reset the owner field. */
+ pp:
+ mutex->__data.__owner = 0;
+
+ if (decr)
+ /* One less user. */
+ --mutex->__data.__nusers;
+
+ /* Unlock. Use release MO in the CAS to synchronize with acquire MO in
+ lock acquisitions. */
+ int newval;
+ int oldval = atomic_load_relaxed (&mutex->__data.__lock);
+ do
+ {
+ newval = oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK;
+ }
+ while (!atomic_compare_exchange_weak_release (&mutex->__data.__lock,
+ &oldval, newval));
+
+ if ((oldval & ~PTHREAD_MUTEX_PRIO_CEILING_MASK) > 1)
+ lll_futex_wake (&mutex->__data.__lock, 1,
+ PTHREAD_MUTEX_PSHARED (mutex));
+
+ int oldprio = newval >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
+
+ LIBC_PROBE (mutex_release, 1, mutex);
+
+ return __pthread_tpp_change_priority (oldprio, -1);
+
+ default:
+ /* Correct code cannot set any other type. */
+ return EINVAL;
+ }
+
+ LIBC_PROBE (mutex_release, 1, mutex);
+ return 0;
+}
+
+
+int
+__pthread_mutex_unlock (pthread_mutex_t *mutex)
+{
+ return __pthread_mutex_unlock_usercnt (mutex, 1);
+}
+weak_alias (__pthread_mutex_unlock, pthread_mutex_unlock)
+hidden_def (__pthread_mutex_unlock)
diff --git a/nptl_2_17/sysdeps/aarch64/nptl/bits/pthreadtypes-arch_2_17.h b/nptl_2_17/sysdeps/aarch64/nptl/bits/pthreadtypes-arch_2_17.h
new file mode 100644
index 00000000..008aa7e0
--- /dev/null
+++ b/nptl_2_17/sysdeps/aarch64/nptl/bits/pthreadtypes-arch_2_17.h
@@ -0,0 +1,71 @@
+/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _BITS_PTHREADTYPES_ARCH_H
+#define _BITS_PTHREADTYPES_ARCH_H 1
+
+#include <endian.h>
+
+#ifdef __ILP32__
+# define __SIZEOF_PTHREAD_ATTR_T 32
+# define __SIZEOF_PTHREAD_MUTEX_T 32
+# define __SIZEOF_PTHREAD_MUTEXATTR_T 4
+# define __SIZEOF_PTHREAD_CONDATTR_T 4
+# define __SIZEOF_PTHREAD_RWLOCK_T 48
+# define __SIZEOF_PTHREAD_BARRIER_T 20
+# define __SIZEOF_PTHREAD_BARRIERATTR_T 4
+#else
+# define __SIZEOF_PTHREAD_ATTR_T 64
+# define __SIZEOF_PTHREAD_MUTEX_T 48
+# define __SIZEOF_PTHREAD_MUTEXATTR_T 8
+# define __SIZEOF_PTHREAD_CONDATTR_T 8
+# define __SIZEOF_PTHREAD_RWLOCK_T 56
+# define __SIZEOF_PTHREAD_BARRIER_T 32
+# define __SIZEOF_PTHREAD_BARRIERATTR_T 8
+#endif
+#define __SIZEOF_PTHREAD_COND_T 48
+#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
+
+/* Definitions for internal mutex struct. */
+#define __PTHREAD_COMPAT_PADDING_MID
+#define __PTHREAD_COMPAT_PADDING_END
+#define __PTHREAD_MUTEX_LOCK_ELISION 0
+#define __PTHREAD_MUTEX_NUSERS_AFTER_KIND 0
+#define __PTHREAD_MUTEX_USE_UNION 0
+
+#define __LOCK_ALIGNMENT
+#define __ONCE_ALIGNMENT
+
+struct __pthread_rwlock_arch_t
+{
+ unsigned int __readers;
+ unsigned int __writers;
+ unsigned int __wrphase_futex;
+ unsigned int __writers_futex;
+ unsigned int __pad3;
+ unsigned int __pad4;
+ int __cur_writer;
+ int __shared;
+ unsigned long int __pad1;
+ unsigned long int __pad2;
+ unsigned int __flags;
+};
+
+#define __PTHREAD_RWLOCK_ELISION_EXTRA 0
+
+#endif /* bits/pthreadtypes.h */
diff --git a/nptl_2_17/sysdeps/generic/sysdep_2_17.h b/nptl_2_17/sysdeps/generic/sysdep_2_17.h
new file mode 100644
index 00000000..934d4da8
--- /dev/null
+++ b/nptl_2_17/sysdeps/generic/sysdep_2_17.h
@@ -0,0 +1,97 @@
+/* Generic asm macros used on many machines.
+ Copyright (C) 1991-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef C_LABEL
+
+/* Define a macro we can use to construct the asm name for a C symbol. */
+# define C_LABEL(name) name##:
+
+#endif
+
+#ifdef __ASSEMBLER__
+/* Mark the end of function named SYM. This is used on some platforms
+ to generate correct debugging information. */
+# ifndef END
+# define END(sym)
+# endif
+
+# ifndef JUMPTARGET
+# define JUMPTARGET(sym) sym
+# endif
+#endif
+
+/* Makros to generate eh_frame unwind information. */
+#ifdef __ASSEMBLER__
+# define cfi_startproc .cfi_startproc
+# define cfi_endproc .cfi_endproc
+# define cfi_def_cfa(reg, off) .cfi_def_cfa reg, off
+# define cfi_def_cfa_register(reg) .cfi_def_cfa_register reg
+# define cfi_def_cfa_offset(off) .cfi_def_cfa_offset off
+# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off
+# define cfi_offset(reg, off) .cfi_offset reg, off
+# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off
+# define cfi_register(r1, r2) .cfi_register r1, r2
+# define cfi_return_column(reg) .cfi_return_column reg
+# define cfi_restore(reg) .cfi_restore reg
+# define cfi_same_value(reg) .cfi_same_value reg
+# define cfi_undefined(reg) .cfi_undefined reg
+# define cfi_remember_state .cfi_remember_state
+# define cfi_restore_state .cfi_restore_state
+# define cfi_window_save .cfi_window_save
+# define cfi_personality(enc, exp) .cfi_personality enc, exp
+# define cfi_lsda(enc, exp) .cfi_lsda enc, exp
+
+#else /* ! ASSEMBLER */
+
+# define CFI_STRINGIFY(Name) CFI_STRINGIFY2 (Name)
+# define CFI_STRINGIFY2(Name) #Name
+# define CFI_STARTPROC ".cfi_startproc"
+# define CFI_ENDPROC ".cfi_endproc"
+# define CFI_DEF_CFA(reg, off) \
+ ".cfi_def_cfa " CFI_STRINGIFY(reg) "," CFI_STRINGIFY(off)
+# define CFI_DEF_CFA_REGISTER(reg) \
+ ".cfi_def_cfa_register " CFI_STRINGIFY(reg)
+# define CFI_DEF_CFA_OFFSET(off) \
+ ".cfi_def_cfa_offset " CFI_STRINGIFY(off)
+# define CFI_ADJUST_CFA_OFFSET(off) \
+ ".cfi_adjust_cfa_offset " CFI_STRINGIFY(off)
+# define CFI_OFFSET(reg, off) \
+ ".cfi_offset " CFI_STRINGIFY(reg) "," CFI_STRINGIFY(off)
+# define CFI_REL_OFFSET(reg, off) \
+ ".cfi_rel_offset " CFI_STRINGIFY(reg) "," CFI_STRINGIFY(off)
+# define CFI_REGISTER(r1, r2) \
+ ".cfi_register " CFI_STRINGIFY(r1) "," CFI_STRINGIFY(r2)
+# define CFI_RETURN_COLUMN(reg) \
+ ".cfi_return_column " CFI_STRINGIFY(reg)
+# define CFI_RESTORE(reg) \
+ ".cfi_restore " CFI_STRINGIFY(reg)
+# define CFI_UNDEFINED(reg) \
+ ".cfi_undefined " CFI_STRINGIFY(reg)
+# define CFI_REMEMBER_STATE \
+ ".cfi_remember_state"
+# define CFI_RESTORE_STATE \
+ ".cfi_restore_state"
+# define CFI_WINDOW_SAVE \
+ ".cfi_window_save"
+# define CFI_PERSONALITY(enc, exp) \
+ ".cfi_personality " CFI_STRINGIFY(enc) "," CFI_STRINGIFY(exp)
+# define CFI_LSDA(enc, exp) \
+ ".cfi_lsda " CFI_STRINGIFY(enc) "," CFI_STRINGIFY(exp)
+#endif
+
+#include "dwarf2.h"
diff --git a/nptl_2_17/sysdeps/nptl/futex-internal_2_17.h b/nptl_2_17/sysdeps/nptl/futex-internal_2_17.h
new file mode 100644
index 00000000..353fdfb9
--- /dev/null
+++ b/nptl_2_17/sysdeps/nptl/futex-internal_2_17.h
@@ -0,0 +1,210 @@
+/* futex operations for glibc-internal use. Stub version; do not include
+ this file directly.
+ Copyright (C) 2014-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef STUB_FUTEX_INTERNAL_H
+#define STUB_FUTEX_INTERNAL_H
+
+#include <sys/time.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <libc-diag.h>
+
+/* This file defines futex operations used internally in glibc. A futex
+ consists of the so-called futex word in userspace, which is of type
+ unsigned int and represents an application-specific condition, and kernel
+ state associated with this particular futex word (e.g., wait queues). The
+ futex operations we provide are wrappers for the futex syscalls and add
+ glibc-specific error checking of the syscall return value. We abort on
+ error codes that are caused by bugs in glibc or in the calling application,
+ or when an error code is not known. We return error codes that can arise
+ in correct executions to the caller. Each operation calls out exactly the
+ return values that callers need to handle.
+
+ The private flag must be either FUTEX_PRIVATE or FUTEX_SHARED.
+ FUTEX_PRIVATE is always supported, and the implementation can internally
+ use FUTEX_SHARED when FUTEX_PRIVATE is requested. FUTEX_SHARED is not
+ necessarily supported (use futex_supports_pshared to detect this).
+
+ We expect callers to only use these operations if futexes and the
+ specific futex operations being used are supported (e.g., FUTEX_SHARED).
+
+ Given that waking other threads waiting on a futex involves concurrent
+ accesses to the futex word, you must use atomic operations to access the
+ futex word.
+
+ Both absolute and relative timeouts can be used. An absolute timeout
+ expires when the given specific point in time on the specified clock
+ passes, or when it already has passed. A relative timeout expires when
+ the given duration of time on the CLOCK_MONOTONIC clock passes. Relative
+ timeouts may be imprecise (see futex_supports_exact_relative_timeouts).
+
+ Due to POSIX requirements on when synchronization data structures such
+ as mutexes or semaphores can be destroyed and due to the futex design
+ having separate fast/slow paths for wake-ups, we need to consider that
+ futex_wake calls might effectively target a data structure that has been
+ destroyed and reused for another object, or unmapped; thus, some
+ errors or spurious wake-ups can happen in correct executions that would
+ not be possible in a program using just a single futex whose lifetime
+ does not end before the program terminates. For background, see:
+ https://sourceware.org/ml/libc-alpha/2014-04/msg00075.html
+ https://lkml.org/lkml/2014/11/27/472 */
+
+/* Defined this way for interoperability with lowlevellock.
+ FUTEX_PRIVATE must be zero because the initializers for pthread_mutex_t,
+ pthread_rwlock_t, and pthread_cond_t initialize the respective field of
+ those structures to zero, and we want FUTEX_PRIVATE to be the default. */
+#define FUTEX_PRIVATE LLL_PRIVATE
+#define FUTEX_SHARED LLL_SHARED
+#if FUTEX_PRIVATE != 0
+# error FUTEX_PRIVATE must be equal to 0
+#endif
+
+/* Returns EINVAL if PSHARED is neither PTHREAD_PROCESS_PRIVATE nor
+ PTHREAD_PROCESS_SHARED; otherwise, returns 0 if PSHARED is supported, and
+ ENOTSUP if not. */
+static __always_inline int
+futex_supports_pshared (int pshared);
+
+/* Returns true if relative timeouts are robust to concurrent changes to the
+ system clock. If this returns false, relative timeouts can still be used
+ but might be effectively longer or shorter than requested. */
+static __always_inline bool
+futex_supports_exact_relative_timeouts (void);
+
+/* Atomically wrt other futex operations on the same futex, this blocks iff
+ the value *FUTEX_WORD matches the expected value. This is
+ semantically equivalent to:
+ l = <get lock associated with futex> (FUTEX_WORD);
+ wait_flag = <get wait_flag associated with futex> (FUTEX_WORD);
+ lock (l);
+ val = atomic_load_relaxed (FUTEX_WORD);
+ if (val != expected) { unlock (l); return EAGAIN; }
+ atomic_store_relaxed (wait_flag, true);
+ unlock (l);
+ // Now block; can time out in futex_time_wait (see below)
+ while (atomic_load_relaxed(wait_flag) && !<spurious wake-up>);
+
+ Note that no guarantee of a happens-before relation between a woken
+ futex_wait and a futex_wake is documented; however, this does not matter
+ in practice because we have to consider spurious wake-ups (see below),
+ and thus would not be able to reliably reason about which futex_wake woke
+ us.
+
+ Returns 0 if woken by a futex operation or spuriously. (Note that due to
+ the POSIX requirements mentioned above, we need to conservatively assume
+ that unrelated futex_wake operations could wake this futex; it is easiest
+ to just be prepared for spurious wake-ups.)
+ Returns EAGAIN if the futex word did not match the expected value.
+ Returns EINTR if waiting was interrupted by a signal.
+
+ Note that some previous code in glibc assumed the underlying futex
+ operation (e.g., syscall) to start with or include the equivalent of a
+ seq_cst fence; this allows one to avoid an explicit seq_cst fence before
+ a futex_wait call when synchronizing similar to Dekker synchronization.
+ However, we make no such guarantee here. */
+static __always_inline int
+futex_wait (unsigned int *futex_word, unsigned int expected, int private);
+
+/* Like futex_wait but does not provide any indication why we stopped waiting.
+ Thus, when this function returns, you have to always check FUTEX_WORD to
+ determine whether you need to continue waiting, and you cannot detect
+ whether the waiting was interrupted by a signal. Example use:
+ while (atomic_load_relaxed (&futex_word) == 23)
+ futex_wait_simple (&futex_word, 23, FUTEX_PRIVATE);
+ This is common enough to make providing this wrapper worthwhile. */
+static __always_inline void
+futex_wait_simple (unsigned int *futex_word, unsigned int expected,
+ int private)
+{
+ ignore_value (futex_wait (futex_word, expected, private));
+}
+
+
+/* Like futex_wait but is a POSIX cancellation point. */
+static __always_inline int
+futex_wait_cancelable (unsigned int *futex_word, unsigned int expected,
+ int private);
+
+/* Like futex_wait, but will eventually time out (i.e., stop being
+ blocked) after the duration of time provided (i.e., RELTIME) has
+ passed. The caller must provide a normalized RELTIME. RELTIME can also
+ equal NULL, in which case this function behaves equivalent to futex_wait.
+
+ Returns the same values as futex_wait under those same conditions;
+ additionally, returns ETIMEDOUT if the timeout expired.
+ */
+static __always_inline int
+futex_reltimed_wait (unsigned int* futex_word, unsigned int expected,
+ const struct timespec* reltime, int private);
+
+/* Like futex_reltimed_wait but is a POSIX cancellation point. */
+static __always_inline int
+futex_reltimed_wait_cancelable (unsigned int* futex_word,
+ unsigned int expected,
+ const struct timespec* reltime, int private);
+
+/* Check whether the specified clockid is supported by
+ futex_abstimed_wait and futex_abstimed_wait_cancelable. */
+static __always_inline int
+futex_abstimed_supported_clockid (clockid_t clockid);
+
+/* Like futex_reltimed_wait, but the provided timeout (ABSTIME) is an
+ absolute point in time; a call will time out after this point in time. */
+static __always_inline int
+futex_abstimed_wait (unsigned int* futex_word, unsigned int expected,
+ clockid_t clockid,
+ const struct timespec* abstime, int private);
+
+/* Like futex_reltimed_wait but is a POSIX cancellation point. */
+static __always_inline int
+futex_abstimed_wait_cancelable (unsigned int* futex_word,
+ unsigned int expected,
+ clockid_t clockid,
+ const struct timespec* abstime, int private);
+
+/* Atomically wrt other futex operations on the same futex, this unblocks the
+ specified number of processes, or all processes blocked on this futex if
+ there are fewer than the specified number. Semantically, this is
+ equivalent to:
+ l = <get lock associated with futex> (FUTEX_WORD);
+ lock (l);
+ for (res = 0; PROCESSES_TO_WAKE > 0; PROCESSES_TO_WAKE--, res++) {
+ if (<no process blocked on futex>) break;
+ wf = <get wait_flag of a process blocked on futex> (FUTEX_WORD);
+ // No happens-before guarantee with woken futex_wait (see above)
+ atomic_store_relaxed (wf, 0);
+ }
+ return res;
+
+ Note that we need to support futex_wake calls to past futexes whose memory
+ has potentially been reused due to POSIX' requirements on synchronization
+ object destruction (see above); therefore, we must not report or abort
+ on most errors. */
+static __always_inline void
+futex_wake (unsigned int* futex_word, int processes_to_wake, int private);
+
+/* Calls __libc_fatal with an error message. Convenience function for
+ concrete implementations of the futex interface. */
+static __always_inline __attribute__ ((__noreturn__)) void
+futex_fatal_error (void)
+{
+ __libc_fatal ("The futex facility returned an unexpected error code.");
+}
+
+#endif /* futex-internal.h */
diff --git a/nptl_2_17/sysdeps/nptl/lowlevellock_2_17.h b/nptl_2_17/sysdeps/nptl/lowlevellock_2_17.h
new file mode 100644
index 00000000..1247949a
--- /dev/null
+++ b/nptl_2_17/sysdeps/nptl/lowlevellock_2_17.h
@@ -0,0 +1,208 @@
+/* Low-level lock implementation. Generic futex-based version.
+ Copyright (C) 2005-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _LOWLEVELLOCK_H
+#define _LOWLEVELLOCK_H 1
+
+#include <atomic.h>
+#include <lowlevellock-futex_2_17.h>
+
+/* Low-level locks use a combination of atomic operations (to acquire and
+ release lock ownership) and futex operations (to block until the state
+ of a lock changes). A lock can be in one of three states:
+ 0: not acquired,
+ 1: acquired with no waiters; no other threads are blocked or about to block
+ for changes to the lock state,
+ >1: acquired, possibly with waiters; there may be other threads blocked or
+ about to block for changes to the lock state.
+
+ We expect that the common case is an uncontended lock, so we just need
+ to transition the lock between states 0 and 1; releasing the lock does
+ not need to wake any other blocked threads. If the lock is contended
+ and a thread decides to block using a futex operation, then this thread
+ needs to first change the state to >1; if this state is observed during
+ lock release, the releasing thread will wake one of the potentially
+ blocked threads.
+
+ Much of this code takes a 'private' parameter. This may be:
+ LLL_PRIVATE: lock only shared within a process
+ LLL_SHARED: lock may be shared across processes.
+
+ Condition variables contain an optimization for broadcasts that requeues
+ waiting threads on a lock's futex. Therefore, there is a special
+ variant of the locks (whose name contains "cond") that makes sure to
+ always set the lock state to >1 and not just 1.
+
+ Robust locks set the lock to the id of the owner. This allows detection
+ of the case where the owner exits without releasing the lock. Flags are
+ OR'd with the owner id to record additional information about lock state.
+ Therefore the states of robust locks are:
+ 0: not acquired
+ id: acquired (by user identified by id & FUTEX_TID_MASK)
+
+ The following flags may be set in the robust lock value:
+ FUTEX_WAITERS - possibly has waiters
+ FUTEX_OWNER_DIED - owning user has exited without releasing the futex. */
+
+
+/* If LOCK is 0 (not acquired), set to 1 (acquired with no waiters) and return
+ 0. Otherwise leave lock unchanged and return non-zero to indicate that the
+ lock was not acquired. */
+#define lll_trylock(lock) \
+ __glibc_unlikely (atomic_compare_and_exchange_bool_acq (&(lock), 1, 0))
+
+/* If LOCK is 0 (not acquired), set to 2 (acquired, possibly with waiters) and
+ return 0. Otherwise leave lock unchanged and return non-zero to indicate
+ that the lock was not acquired. */
+#define lll_cond_trylock(lock) \
+ __glibc_unlikely (atomic_compare_and_exchange_bool_acq (&(lock), 2, 0))
+
+extern void __lll_lock_wait_private (int *futex) attribute_hidden;
+extern void __lll_lock_wait (int *futex, int private) attribute_hidden;
+
+/* This is an expression rather than a statement even though its value is
+ void, so that it can be used in a comma expression or as an expression
+ that's cast to void. */
+/* The inner conditional compiles to a call to __lll_lock_wait_private if
+ private is known at compile time to be LLL_PRIVATE, and to a call to
+ __lll_lock_wait otherwise. */
+/* If FUTEX is 0 (not acquired), set to 1 (acquired with no waiters) and
+ return. Otherwise, ensure that it is >1 (acquired, possibly with waiters)
+ and then block until we acquire the lock, at which point FUTEX will still be
+ >1. The lock is always acquired on return. */
+#define __lll_lock(futex, private) \
+ ((void) \
+ ({ \
+ int *__futex = (futex); \
+ if (__glibc_unlikely \
+ (atomic_compare_and_exchange_bool_acq (__futex, 1, 0))) \
+ { \
+ if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \
+ __lll_lock_wait_private (__futex); \
+ else \
+ __lll_lock_wait (__futex, private); \
+ } \
+ }))
+#define lll_lock(futex, private) \
+ __lll_lock (&(futex), private)
+
+
+/* This is an expression rather than a statement even though its value is
+ void, so that it can be used in a comma expression or as an expression
+ that's cast to void. */
+/* Unconditionally set FUTEX to 2 (acquired, possibly with waiters). If FUTEX
+ was 0 (not acquired) then return. Otherwise, block until the lock is
+ acquired, at which point FUTEX is 2 (acquired, possibly with waiters). The
+ lock is always acquired on return. */
+#define __lll_cond_lock(futex, private) \
+ ((void) \
+ ({ \
+ int *__futex = (futex); \
+ if (__glibc_unlikely (atomic_exchange_acq (__futex, 2) != 0)) \
+ __lll_lock_wait (__futex, private); \
+ }))
+#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private)
+
+
+extern int __lll_timedlock_wait (int *futex, const struct timespec *,
+ int private) attribute_hidden;
+
+
+/* As __lll_lock, but with a timeout. If the timeout occurs then return
+ ETIMEDOUT. If ABSTIME is invalid, return EINVAL. */
+#define __lll_timedlock(futex, abstime, private) \
+ ({ \
+ int *__futex = (futex); \
+ int __val = 0; \
+ \
+ if (__glibc_unlikely \
+ (atomic_compare_and_exchange_bool_acq (__futex, 1, 0))) \
+ __val = __lll_timedlock_wait (__futex, abstime, private); \
+ __val; \
+ })
+#define lll_timedlock(futex, abstime, private) \
+ __lll_timedlock (&(futex), abstime, private)
+
+
+/* This is an expression rather than a statement even though its value is
+ void, so that it can be used in a comma expression or as an expression
+ that's cast to void. */
+/* Unconditionally set FUTEX to 0 (not acquired), releasing the lock. If FUTEX
+ was >1 (acquired, possibly with waiters), then wake any waiters. The waiter
+ that acquires the lock will set FUTEX to >1.
+ Evaluate PRIVATE before releasing the lock so that we do not violate the
+ mutex destruction requirements. Specifically, we need to ensure that
+ another thread can destroy the mutex (and reuse its memory) once it
+ acquires the lock and when there will be no further lock acquisitions;
+ thus, we must not access the lock after releasing it, or those accesses
+ could be concurrent with mutex destruction or reuse of the memory. */
+#define __lll_unlock(futex, private) \
+ ((void) \
+ ({ \
+ int *__futex = (futex); \
+ int __private = (private); \
+ int __oldval = atomic_exchange_rel (__futex, 0); \
+ if (__glibc_unlikely (__oldval > 1)) \
+ lll_futex_wake (__futex, 1, __private); \
+ }))
+#define lll_unlock(futex, private) \
+ __lll_unlock (&(futex), private)
+
+
+#define lll_islocked(futex) \
+ ((futex) != LLL_LOCK_INITIALIZER)
+
+
+/* Our internal lock implementation is identical to the binary-compatible
+ mutex implementation. */
+
+/* Initializers for lock. */
+#define LLL_LOCK_INITIALIZER (0)
+#define LLL_LOCK_INITIALIZER_LOCKED (1)
+
+
+/* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex
+ wake-up when the clone terminates. The memory location contains the
+ thread ID while the clone is running and is reset to zero by the kernel
+ afterwards. The kernel up to version 3.16.3 does not use the private futex
+ operations for futex wake-up when the clone terminates. */
+#define lll_wait_tid(tid) \
+ do { \
+ __typeof (tid) __tid; \
+ /* We need acquire MO here so that we synchronize \
+ with the kernel's store to 0 when the clone \
+ terminates. (see above) */ \
+ while ((__tid = atomic_load_acquire (&(tid))) != 0) \
+ lll_futex_wait (&(tid), __tid, LLL_SHARED); \
+ } while (0)
+
+extern int __lll_timedwait_tid (int *, const struct timespec *)
+ attribute_hidden;
+
+/* As lll_wait_tid, but with a timeout. If the timeout occurs then return
+ ETIMEDOUT. If ABSTIME is invalid, return EINVAL. */
+#define lll_timedwait_tid(tid, abstime) \
+ ({ \
+ int __res = 0; \
+ if ((tid) != 0) \
+ __res = __lll_timedwait_tid (&(tid), (abstime)); \
+ __res; \
+ })
+
+
+#endif /* lowlevellock.h */
diff --git a/nptl_2_17/sysdeps/unix/sysdep_2_17.h b/nptl_2_17/sysdeps/unix/sysdep_2_17.h
new file mode 100644
index 00000000..a9905ff9
--- /dev/null
+++ b/nptl_2_17/sysdeps/unix/sysdep_2_17.h
@@ -0,0 +1,148 @@
+/* Copyright (C) 1991-2018 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 <sysdeps/generic/sysdep_2_17.h>
+
+#include <sys/syscall.h>
+#define HAVE_SYSCALLS
+
+/* Note that using a `PASTE' macro loses. */
+#define SYSCALL__(name, args) PSEUDO (__##name, name, args)
+#define SYSCALL(name, args) PSEUDO (name, name, args)
+
+#define __SYSCALL_CONCAT_X(a,b) a##b
+#define __SYSCALL_CONCAT(a,b) __SYSCALL_CONCAT_X (a, b)
+
+
+#define __INTERNAL_SYSCALL0(name, err) \
+ INTERNAL_SYSCALL (name, err, 0)
+#define __INTERNAL_SYSCALL1(name, err, a1) \
+ INTERNAL_SYSCALL (name, err, 1, a1)
+#define __INTERNAL_SYSCALL2(name, err, a1, a2) \
+ INTERNAL_SYSCALL (name, err, 2, a1, a2)
+#define __INTERNAL_SYSCALL3(name, err, a1, a2, a3) \
+ INTERNAL_SYSCALL (name, err, 3, a1, a2, a3)
+#define __INTERNAL_SYSCALL4(name, err, a1, a2, a3, a4) \
+ INTERNAL_SYSCALL (name, err, 4, a1, a2, a3, a4)
+#define __INTERNAL_SYSCALL5(name, err, a1, a2, a3, a4, a5) \
+ INTERNAL_SYSCALL (name, err, 5, a1, a2, a3, a4, a5)
+#define __INTERNAL_SYSCALL6(name, err, a1, a2, a3, a4, a5, a6) \
+ INTERNAL_SYSCALL (name, err, 6, a1, a2, a3, a4, a5, a6)
+#define __INTERNAL_SYSCALL7(name, err, a1, a2, a3, a4, a5, a6, a7) \
+ INTERNAL_SYSCALL (name, err, 7, a1, a2, a3, a4, a5, a6, a7)
+
+#define __INTERNAL_SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,o,...) o
+#define __INTERNAL_SYSCALL_NARGS(...) \
+ __INTERNAL_SYSCALL_NARGS_X (__VA_ARGS__,7,6,5,4,3,2,1,0,)
+#define __INTERNAL_SYSCALL_DISP(b,...) \
+ __SYSCALL_CONCAT (b,__INTERNAL_SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
+
+/* Issue a syscall defined by syscall number plus any other argument required.
+ It is similar to INTERNAL_SYSCALL macro, but without the need to pass the
+ expected argument number as second parameter. */
+#define INTERNAL_SYSCALL_CALL(...) \
+ __INTERNAL_SYSCALL_DISP (__INTERNAL_SYSCALL, __VA_ARGS__)
+
+#define __INLINE_SYSCALL0(name) \
+ INLINE_SYSCALL (name, 0)
+#define __INLINE_SYSCALL1(name, a1) \
+ INLINE_SYSCALL (name, 1, a1)
+#define __INLINE_SYSCALL2(name, a1, a2) \
+ INLINE_SYSCALL (name, 2, a1, a2)
+#define __INLINE_SYSCALL3(name, a1, a2, a3) \
+ INLINE_SYSCALL (name, 3, a1, a2, a3)
+#define __INLINE_SYSCALL4(name, a1, a2, a3, a4) \
+ INLINE_SYSCALL (name, 4, a1, a2, a3, a4)
+#define __INLINE_SYSCALL5(name, a1, a2, a3, a4, a5) \
+ INLINE_SYSCALL (name, 5, a1, a2, a3, a4, a5)
+#define __INLINE_SYSCALL6(name, a1, a2, a3, a4, a5, a6) \
+ INLINE_SYSCALL (name, 6, a1, a2, a3, a4, a5, a6)
+#define __INLINE_SYSCALL7(name, a1, a2, a3, a4, a5, a6, a7) \
+ INLINE_SYSCALL (name, 7, a1, a2, a3, a4, a5, a6, a7)
+
+#define __INLINE_SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n
+#define __INLINE_SYSCALL_NARGS(...) \
+ __INLINE_SYSCALL_NARGS_X (__VA_ARGS__,7,6,5,4,3,2,1,0,)
+#define __INLINE_SYSCALL_DISP(b,...) \
+ __SYSCALL_CONCAT (b,__INLINE_SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__)
+
+/* Issue a syscall defined by syscall number plus any other argument
+ required. Any error will be handled using arch defined macros and errno
+ will be set accordingly.
+ It is similar to INLINE_SYSCALL macro, but without the need to pass the
+ expected argument number as second parameter. */
+#define INLINE_SYSCALL_CALL(...) \
+ __INLINE_SYSCALL_DISP (__INLINE_SYSCALL, __VA_ARGS__)
+
+#define SYSCALL_CANCEL(...) \
+ ({ \
+ long int sc_ret; \
+ if (SINGLE_THREAD_P) \
+ sc_ret = INLINE_SYSCALL_CALL (__VA_ARGS__); \
+ else \
+ { \
+ int sc_cancel_oldtype = LIBC_CANCEL_ASYNC (); \
+ sc_ret = INLINE_SYSCALL_CALL (__VA_ARGS__); \
+ LIBC_CANCEL_RESET (sc_cancel_oldtype); \
+ } \
+ sc_ret; \
+ })
+
+/* Issue a syscall defined by syscall number plus any other argument
+ required. Any error will be returned unmodified (including errno). */
+#define INTERNAL_SYSCALL_CANCEL(...) \
+ ({ \
+ long int sc_ret; \
+ if (SINGLE_THREAD_P) \
+ sc_ret = INTERNAL_SYSCALL_CALL (__VA_ARGS__); \
+ else \
+ { \
+ int sc_cancel_oldtype = LIBC_CANCEL_ASYNC (); \
+ sc_ret = INTERNAL_SYSCALL_CALL (__VA_ARGS__); \
+ LIBC_CANCEL_RESET (sc_cancel_oldtype); \
+ } \
+ sc_ret; \
+ })
+
+/* Machine-dependent sysdep.h files are expected to define the macro
+ PSEUDO (function_name, syscall_name) to emit assembly code to define the
+ C-callable function FUNCTION_NAME to do system call SYSCALL_NAME.
+ r0 and r1 are the system call outputs. MOVE(x, y) should be defined as
+ an instruction such that "MOVE(r1, r0)" works. ret should be defined
+ as the return instruction. */
+
+#ifndef SYS_ify
+#define SYS_ify(syscall_name) SYS_##syscall_name
+#endif
+
+/* Terminate a system call named SYM. This is used on some platforms
+ to generate correct debugging information. */
+#ifndef PSEUDO_END
+#define PSEUDO_END(sym)
+#endif
+#ifndef PSEUDO_END_NOERRNO
+#define PSEUDO_END_NOERRNO(sym) PSEUDO_END(sym)
+#endif
+#ifndef PSEUDO_END_ERRVAL
+#define PSEUDO_END_ERRVAL(sym) PSEUDO_END(sym)
+#endif
+
+/* Wrappers around system calls should normally inline the system call code.
+ But sometimes it is not possible or implemented and we use this code. */
+#ifndef INLINE_SYSCALL
+#define INLINE_SYSCALL(name, nr, args...) __syscall_##name (args)
+#endif
diff --git a/nptl_2_17/sysdeps/unix/sysv/linux/aarch64/sysdep_2_17.h b/nptl_2_17/sysdeps/unix/sysv/linux/aarch64/sysdep_2_17.h
new file mode 100644
index 00000000..76f41900
--- /dev/null
+++ b/nptl_2_17/sysdeps/unix/sysv/linux/aarch64/sysdep_2_17.h
@@ -0,0 +1,301 @@
+/* Copyright (C) 2005-2018 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _LINUX_AARCH64_SYSDEP_H
+#define _LINUX_AARCH64_SYSDEP_H 1
+
+#include <descr_2_17.h>
+#include <lowlevellock-futex_2_17.h>
+#include <sysdeps/unix/sysdep_2_17.h>
+#include <sysdeps/aarch64/sysdep.h>
+#include <sysdeps/unix/sysv/linux/generic/sysdep_2_17.h>
+
+/* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO. */
+#include <dl-sysdep.h>
+
+#include <tls.h>
+
+/* In order to get __set_errno() definition in INLINE_SYSCALL. */
+#ifndef __ASSEMBLER__
+#include <errno.h>
+#endif
+
+/* For Linux we can use the system call table in the header file
+ /usr/include/asm/unistd.h
+ of the kernel. But these symbols do not follow the SYS_* syntax
+ so we have to redefine the `SYS_ify' macro here. */
+#undef SYS_ify
+#define SYS_ify(syscall_name) (__NR_##syscall_name)
+
+#ifdef __ASSEMBLER__
+
+/* Linux uses a negative return value to indicate syscall errors,
+ unlike most Unices, which use the condition codes' carry flag.
+
+ Since version 2.1 the return value of a system call might be
+ negative even if the call succeeded. E.g., the `lseek' system call
+ might return a large offset. Therefore we must not anymore test
+ for < 0, but test for a real error by making sure the value in R0
+ is a real error number. Linus said he will make sure the no syscall
+ returns a value in -1 .. -4095 as a valid result so we can safely
+ test with -4095. */
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args) \
+ .text; \
+ ENTRY (name); \
+ DO_CALL (syscall_name, args); \
+ cmn x0, #4095; \
+ b.cs .Lsyscall_error;
+
+# undef PSEUDO_END
+# define PSEUDO_END(name) \
+ SYSCALL_ERROR_HANDLER \
+ END (name)
+
+# undef PSEUDO_NOERRNO
+# define PSEUDO_NOERRNO(name, syscall_name, args) \
+ .text; \
+ ENTRY (name); \
+ DO_CALL (syscall_name, args);
+
+# undef PSEUDO_END_NOERRNO
+# define PSEUDO_END_NOERRNO(name) \
+ END (name)
+
+# define ret_NOERRNO ret
+
+/* The function has to return the error code. */
+# undef PSEUDO_ERRVAL
+# define PSEUDO_ERRVAL(name, syscall_name, args) \
+ .text; \
+ ENTRY (name) \
+ DO_CALL (syscall_name, args); \
+ neg x0, x0
+
+# undef PSEUDO_END_ERRVAL
+# define PSEUDO_END_ERRVAL(name) \
+ END (name)
+
+# define ret_ERRVAL ret
+
+# if !IS_IN (libc)
+# define SYSCALL_ERROR .Lsyscall_error
+# if RTLD_PRIVATE_ERRNO
+# define SYSCALL_ERROR_HANDLER \
+.Lsyscall_error: \
+ adrp x1, C_SYMBOL_NAME(rtld_errno); \
+ neg w0, w0; \
+ str w0, [x1, :lo12:C_SYMBOL_NAME(rtld_errno)]; \
+ mov x0, -1; \
+ RET;
+# else
+
+# define SYSCALL_ERROR_HANDLER \
+.Lsyscall_error: \
+ adrp x1, :gottprel:errno; \
+ neg w2, w0; \
+ ldr PTR_REG(1), [x1, :gottprel_lo12:errno]; \
+ mrs x3, tpidr_el0; \
+ mov x0, -1; \
+ str w2, [x1, x3]; \
+ RET;
+# endif
+# else
+# define SYSCALL_ERROR __syscall_error
+# define SYSCALL_ERROR_HANDLER \
+.Lsyscall_error: \
+ b __syscall_error;
+# endif
+
+/* Linux takes system call args in registers:
+ syscall number x8
+ arg 1 x0
+ arg 2 x1
+ arg 3 x2
+ arg 4 x3
+ arg 5 x4
+ arg 6 x5
+ arg 7 x6
+
+ The compiler is going to form a call by coming here, through PSEUDO, with
+ arguments
+ syscall number in the DO_CALL macro
+ arg 1 x0
+ arg 2 x1
+ arg 3 x2
+ arg 4 x3
+ arg 5 x4
+ arg 6 x5
+ arg 7 x6
+
+*/
+
+# undef DO_CALL
+# define DO_CALL(syscall_name, args) \
+ mov x8, SYS_ify (syscall_name); \
+ svc 0
+
+#else /* not __ASSEMBLER__ */
+
+
+/* List of system calls which are supported as vsyscalls. */
+# define HAVE_CLOCK_GETRES_VSYSCALL 1
+# define HAVE_CLOCK_GETTIME_VSYSCALL 1
+# define HAVE_GETTIMEOFDAY_VSYSCALL 1
+
+/* Previously AArch64 used the generic version without the libc_hidden_def
+ which lead in a non existent __send symbol in libc.so. */
+# undef HAVE_INTERNAL_SEND_SYMBOL
+
+# define SINGLE_THREAD_BY_GLOBAL 1
+
+/* Define a macro which expands into the inline wrapper code for a system
+ call. */
+# undef INLINE_SYSCALL
+# define INLINE_SYSCALL(name, nr, args...) \
+ ({ unsigned long _sys_result = INTERNAL_SYSCALL (name, , nr, args); \
+ if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_sys_result, ), 0))\
+ { \
+ __set_errno (INTERNAL_SYSCALL_ERRNO (_sys_result, )); \
+ _sys_result = (unsigned long) -1; \
+ } \
+ (long) _sys_result; })
+
+# undef INTERNAL_SYSCALL_DECL
+# define INTERNAL_SYSCALL_DECL(err) do { } while (0)
+
+# undef INTERNAL_SYSCALL_RAW
+# define INTERNAL_SYSCALL_RAW(name, err, nr, args...) \
+ ({ long _sys_result; \
+ { \
+ LOAD_ARGS_##nr (args) \
+ register long _x8 asm ("x8") = (name); \
+ asm volatile ("svc 0 // syscall " # name \
+ : "=r" (_x0) : "r"(_x8) ASM_ARGS_##nr : "memory"); \
+ _sys_result = _x0; \
+ } \
+ _sys_result; })
+
+# undef INTERNAL_SYSCALL
+# define INTERNAL_SYSCALL(name, err, nr, args...) \
+ INTERNAL_SYSCALL_RAW(SYS_ify(name), err, nr, args)
+
+# undef INTERNAL_SYSCALL_AARCH64
+# define INTERNAL_SYSCALL_AARCH64(name, err, nr, args...) \
+ INTERNAL_SYSCALL_RAW(__ARM_NR_##name, err, nr, args)
+
+# undef INTERNAL_SYSCALL_ERROR_P
+# define INTERNAL_SYSCALL_ERROR_P(val, err) \
+ ((unsigned long) (val) >= (unsigned long) -4095)
+
+# undef INTERNAL_SYSCALL_ERRNO
+# define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))
+
+# define LOAD_ARGS_0() \
+ register long _x0 asm ("x0");
+# define LOAD_ARGS_1(x0) \
+ long _x0tmp = (long) (x0); \
+ LOAD_ARGS_0 () \
+ _x0 = _x0tmp;
+# define LOAD_ARGS_2(x0, x1) \
+ long _x1tmp = (long) (x1); \
+ LOAD_ARGS_1 (x0) \
+ register long _x1 asm ("x1") = _x1tmp;
+# define LOAD_ARGS_3(x0, x1, x2) \
+ long _x2tmp = (long) (x2); \
+ LOAD_ARGS_2 (x0, x1) \
+ register long _x2 asm ("x2") = _x2tmp;
+# define LOAD_ARGS_4(x0, x1, x2, x3) \
+ long _x3tmp = (long) (x3); \
+ LOAD_ARGS_3 (x0, x1, x2) \
+ register long _x3 asm ("x3") = _x3tmp;
+# define LOAD_ARGS_5(x0, x1, x2, x3, x4) \
+ long _x4tmp = (long) (x4); \
+ LOAD_ARGS_4 (x0, x1, x2, x3) \
+ register long _x4 asm ("x4") = _x4tmp;
+# define LOAD_ARGS_6(x0, x1, x2, x3, x4, x5) \
+ long _x5tmp = (long) (x5); \
+ LOAD_ARGS_5 (x0, x1, x2, x3, x4) \
+ register long _x5 asm ("x5") = _x5tmp;
+# define LOAD_ARGS_7(x0, x1, x2, x3, x4, x5, x6)\
+ long _x6tmp = (long) (x6); \
+ LOAD_ARGS_6 (x0, x1, x2, x3, x4, x5) \
+ register long _x6 asm ("x6") = _x6tmp;
+
+# define ASM_ARGS_0
+# define ASM_ARGS_1 , "r" (_x0)
+# define ASM_ARGS_2 ASM_ARGS_1, "r" (_x1)
+# define ASM_ARGS_3 ASM_ARGS_2, "r" (_x2)
+# define ASM_ARGS_4 ASM_ARGS_3, "r" (_x3)
+# define ASM_ARGS_5 ASM_ARGS_4, "r" (_x4)
+# define ASM_ARGS_6 ASM_ARGS_5, "r" (_x5)
+# define ASM_ARGS_7 ASM_ARGS_6, "r" (_x6)
+
+# undef INTERNAL_SYSCALL_NCS
+# define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
+ INTERNAL_SYSCALL_RAW (number, err, nr, args)
+
+#endif /* __ASSEMBLER__ */
+
+/* Pointer mangling is supported for AArch64. */
+#if (IS_IN (rtld) || \
+ (!defined SHARED && (IS_IN (libc) \
+ || IS_IN (libpthread))))
+# ifdef __ASSEMBLER__
+/* Note, dst, src, guard, and tmp are all register numbers rather than
+ register names so they will work with both ILP32 and LP64. */
+# define PTR_MANGLE(dst, src, guard, tmp) \
+ LDST_PCREL (ldr, guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard_local)); \
+ PTR_MANGLE2 (dst, src, guard)
+/* Use PTR_MANGLE2 for efficiency if guard is already loaded. */
+# define PTR_MANGLE2(dst, src, guard)\
+ eor x##dst, x##src, x##guard
+# define PTR_DEMANGLE(dst, src, guard, tmp)\
+ PTR_MANGLE (dst, src, guard, tmp)
+# define PTR_DEMANGLE2(dst, src, guard)\
+ PTR_MANGLE2 (dst, src, guard)
+# else
+extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden;
+# define PTR_MANGLE(var) \
+ (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local)
+# define PTR_DEMANGLE(var) PTR_MANGLE (var)
+# endif
+#else
+# ifdef __ASSEMBLER__
+/* Note, dst, src, guard, and tmp are all register numbers rather than
+ register names so they will work with both ILP32 and LP64. */
+# define PTR_MANGLE(dst, src, guard, tmp) \
+ LDST_GLOBAL (ldr, guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard)); \
+ PTR_MANGLE2 (dst, src, guard)
+/* Use PTR_MANGLE2 for efficiency if guard is already loaded. */
+# define PTR_MANGLE2(dst, src, guard)\
+ eor x##dst, x##src, x##guard
+# define PTR_DEMANGLE(dst, src, guard, tmp)\
+ PTR_MANGLE (dst, src, guard, tmp)
+# define PTR_DEMANGLE2(dst, src, guard)\
+ PTR_MANGLE2 (dst, src, guard)
+# else
+extern uintptr_t __pointer_chk_guard attribute_relro;
+# define PTR_MANGLE(var) \
+ (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard)
+# define PTR_DEMANGLE(var) PTR_MANGLE (var)
+# endif
+#endif
+
+#endif /* linux/aarch64/sysdep.h */
diff --git a/nptl_2_17/sysdeps/unix/sysv/linux/generic/sysdep_2_17.h b/nptl_2_17/sysdeps/unix/sysv/linux/generic/sysdep_2_17.h
new file mode 100644
index 00000000..1898464d
--- /dev/null
+++ b/nptl_2_17/sysdeps/unix/sysv/linux/generic/sysdep_2_17.h
@@ -0,0 +1,35 @@
+/* Copyright (C) 2011-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <bits/wordsize.h>
+#include <kernel-features.h>
+#include <sysdeps/unix/sysdep_2_17.h>
+#include <sysdeps/unix/sysv/linux/sysdep_2_17.h>
+
+/* Provide the common name to allow more code reuse. */
+#ifdef __NR_llseek
+# define __NR__llseek __NR_llseek
+#endif
+
+#if __WORDSIZE == 64
+/* By defining the older names, glibc will build syscall wrappers for
+ both pread and pread64; sysdeps/unix/sysv/linux/wordsize-64/pread64.c
+ will suppress generating any separate code for pread64.c. */
+#define __NR_pread __NR_pread64
+#define __NR_pwrite __NR_pwrite64
+#endif
diff --git a/nptl_2_17/sysdeps/unix/sysv/linux/internal-signals_2_17.h b/nptl_2_17/sysdeps/unix/sysv/linux/internal-signals_2_17.h
new file mode 100644
index 00000000..8f2b45c3
--- /dev/null
+++ b/nptl_2_17/sysdeps/unix/sysv/linux/internal-signals_2_17.h
@@ -0,0 +1,91 @@
+/* Special use of signals internally. Linux version.
+ Copyright (C) 2014-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef __INTERNAL_SIGNALS_H
+# define __INTERNAL_SIGNALS_H
+
+#include <sysdep_2_17.h>
+#include <signal.h>
+#include <sigsetops.h>
+#include <stdbool.h>
+
+/* The signal used for asynchronous cancelation. */
+#define SIGCANCEL __SIGRTMIN
+
+
+/* Signal needed for the kernel-supported POSIX timer implementation.
+ We can reuse the cancellation signal since we can distinguish
+ cancellation from timer expirations. */
+#define SIGTIMER SIGCANCEL
+
+
+/* Signal used to implement the setuid et.al. functions. */
+#define SIGSETXID (__SIGRTMIN + 1)
+
+
+/* Return is sig is used internally. */
+static inline bool
+__is_internal_signal (int sig)
+{
+ return (sig == SIGCANCEL) || (sig == SIGSETXID);
+}
+
+/* Remove internal glibc signal from the mask. */
+static inline void
+__clear_internal_signals (sigset_t *set)
+{
+ __sigdelset (set, SIGCANCEL);
+ __sigdelset (set, SIGSETXID);
+}
+
+#define SIGALL_SET \
+ ((__sigset_t) { .__val = {[0 ... _SIGSET_NWORDS-1 ] = -1 } })
+
+/* Block all signals, including internal glibc ones. */
+static inline int
+__libc_signal_block_all (sigset_t *set)
+{
+ INTERNAL_SYSCALL_DECL (err);
+ return INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_BLOCK, &SIGALL_SET,
+ set, _NSIG / 8);
+}
+
+/* Block all application signals (excluding internal glibc ones). */
+static inline int
+__libc_signal_block_app (sigset_t *set)
+{
+ sigset_t allset = SIGALL_SET;
+ __clear_internal_signals (&allset);
+ INTERNAL_SYSCALL_DECL (err);
+ return INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_BLOCK, &allset, set,
+ _NSIG / 8);
+}
+
+/* Restore current process signal mask. */
+static inline int
+__libc_signal_restore_set (const sigset_t *set)
+{
+ INTERNAL_SYSCALL_DECL (err);
+ return INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, set, NULL,
+ _NSIG / 8);
+}
+
+/* Used to communicate with signal handler. */
+extern struct xid_command *__xidcmd attribute_hidden;
+
+#endif
diff --git a/nptl_2_17/sysdeps/unix/sysv/linux/lowlevellock-futex_2_17.h b/nptl_2_17/sysdeps/unix/sysv/linux/lowlevellock-futex_2_17.h
new file mode 100644
index 00000000..399de2e5
--- /dev/null
+++ b/nptl_2_17/sysdeps/unix/sysv/linux/lowlevellock-futex_2_17.h
@@ -0,0 +1,150 @@
+/* Low-level locking access to futex facilities. Linux version.
+ Copyright (C) 2005-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _LOWLEVELLOCK_FUTEX_H
+#define _LOWLEVELLOCK_FUTEX_H 1
+
+#ifndef __ASSEMBLER__
+#include <sysdep_2_17.h>
+#include <tls.h>
+#include <kernel-features.h>
+#endif
+
+#define FUTEX_WAIT 0
+#define FUTEX_WAKE 1
+#define FUTEX_REQUEUE 3
+#define FUTEX_CMP_REQUEUE 4
+#define FUTEX_WAKE_OP 5
+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1)
+#define FUTEX_LOCK_PI 6
+#define FUTEX_UNLOCK_PI 7
+#define FUTEX_TRYLOCK_PI 8
+#define FUTEX_WAIT_BITSET 9
+#define FUTEX_WAKE_BITSET 10
+#define FUTEX_WAIT_REQUEUE_PI 11
+#define FUTEX_CMP_REQUEUE_PI 12
+#define FUTEX_PRIVATE_FLAG 128
+#define FUTEX_CLOCK_REALTIME 256
+
+#define FUTEX_BITSET_MATCH_ANY 0xffffffff
+
+/* Values for 'private' parameter of locking macros. Yes, the
+ definition seems to be backwards. But it is not. The bit will be
+ reversed before passing to the system call. */
+#define LLL_PRIVATE 0
+#define LLL_SHARED FUTEX_PRIVATE_FLAG
+
+#ifndef __ASSEMBLER__
+
+#if IS_IN (libc) || IS_IN (rtld)
+/* In libc.so or ld.so all futexes are private. */
+# define __lll_private_flag(fl, private) \
+ ({ \
+ /* Prevent warnings in callers of this macro. */ \
+ int __lll_private_flag_priv __attribute__ ((unused)); \
+ __lll_private_flag_priv = (private); \
+ ((fl) | FUTEX_PRIVATE_FLAG); \
+ })
+#else
+# define __lll_private_flag(fl, private) \
+ (((fl) | FUTEX_PRIVATE_FLAG) ^ (private))
+#endif
+
+#define lll_futex_syscall(nargs, futexp, op, ...) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ long int __ret = INTERNAL_SYSCALL (futex, __err, nargs, futexp, op, \
+ __VA_ARGS__); \
+ (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (__ret, __err)) \
+ ? -INTERNAL_SYSCALL_ERRNO (__ret, __err) : 0); \
+ })
+
+#define lll_futex_wait(futexp, val, private) \
+ lll_futex_timed_wait (futexp, val, NULL, private)
+
+#define lll_futex_timed_wait(futexp, val, timeout, private) \
+ lll_futex_syscall (4, futexp, \
+ __lll_private_flag (FUTEX_WAIT, private), \
+ val, timeout)
+
+/* Verify whether the supplied clockid is supported by
+ lll_futex_clock_wait_bitset. */
+#define lll_futex_supported_clockid(clockid) \
+ ((clockid) == CLOCK_REALTIME || (clockid) == CLOCK_MONOTONIC)
+
+/* The kernel currently only supports CLOCK_MONOTONIC or
+ CLOCK_REALTIME timeouts for FUTEX_WAIT_BITSET. We could attempt to
+ convert others here but currently do not. */
+#define lll_futex_clock_wait_bitset(futexp, val, clockid, timeout, private) \
+ ({ \
+ long int __ret; \
+ if (lll_futex_supported_clockid (clockid)) \
+ { \
+ const unsigned int clockbit = \
+ (clockid == CLOCK_REALTIME) ? FUTEX_CLOCK_REALTIME : 0; \
+ const int op = \
+ __lll_private_flag (FUTEX_WAIT_BITSET | clockbit, private); \
+ \
+ __ret = lll_futex_syscall (6, futexp, op, val, \
+ timeout, NULL /* Unused. */, \
+ FUTEX_BITSET_MATCH_ANY); \
+ } \
+ else \
+ __ret = -EINVAL; \
+ __ret; \
+ })
+
+#define lll_futex_wake(futexp, nr, private) \
+ lll_futex_syscall (4, futexp, \
+ __lll_private_flag (FUTEX_WAKE, private), nr, 0)
+
+/* Returns non-zero if error happened, zero if success. */
+#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \
+ lll_futex_syscall (6, futexp, \
+ __lll_private_flag (FUTEX_CMP_REQUEUE, private), \
+ nr_wake, nr_move, mutex, val)
+
+/* Returns non-zero if error happened, zero if success. */
+#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \
+ lll_futex_syscall (6, futexp, \
+ __lll_private_flag (FUTEX_WAKE_OP, private), \
+ nr_wake, nr_wake2, futexp2, \
+ FUTEX_OP_CLEAR_WAKE_IF_GT_ONE)
+
+/* Priority Inheritance support. */
+#define lll_futex_wait_requeue_pi(futexp, val, mutex, private) \
+ lll_futex_timed_wait_requeue_pi (futexp, val, NULL, 0, mutex, private)
+
+#define lll_futex_timed_wait_requeue_pi(futexp, val, timeout, clockbit, \
+ mutex, private) \
+ lll_futex_syscall (5, futexp, \
+ __lll_private_flag (FUTEX_WAIT_REQUEUE_PI \
+ | (clockbit), private), \
+ val, timeout, mutex)
+
+
+#define lll_futex_cmp_requeue_pi(futexp, nr_wake, nr_move, mutex, \
+ val, private) \
+ lll_futex_syscall (6, futexp, \
+ __lll_private_flag (FUTEX_CMP_REQUEUE_PI, \
+ private), \
+ nr_wake, nr_move, mutex, val)
+
+#endif /* !__ASSEMBLER__ */
+
+#endif /* lowlevellock-futex.h */
diff --git a/nptl_2_17/sysdeps/unix/sysv/linux/not-cancel_2_17.h b/nptl_2_17/sysdeps/unix/sysv/linux/not-cancel_2_17.h
new file mode 100644
index 00000000..602307db
--- /dev/null
+++ b/nptl_2_17/sysdeps/unix/sysv/linux/not-cancel_2_17.h
@@ -0,0 +1,93 @@
+/* Uncancelable versions of cancelable interfaces. Linux/NPTL version.
+ Copyright (C) 2003-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef NOT_CANCEL_H
+# define NOT_CANCEL_H
+
+#include <fcntl.h>
+#include <sysdep_2_17.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sys/wait.h>
+#include <time.h>
+
+/* Non cancellable open syscall. */
+__typeof (open) __open_nocancel;
+
+/* Non cancellable open syscall (LFS version). */
+__typeof (open64) __open64_nocancel;
+
+/* Non cancellable openat syscall. */
+__typeof (openat) __openat_nocancel;
+
+/* Non cacellable openat syscall (LFS version). */
+__typeof (openat64) __openat64_nocancel;
+
+/* Non cancellable read syscall. */
+__typeof (__read) __read_nocancel;
+
+/* Uncancelable write. */
+__typeof (__write) __write_nocancel;
+
+/* Uncancelable close. */
+__typeof (__close) __close_nocancel;
+
+/* Non cancellable close syscall that does not also set errno in case of
+ failure. */
+static inline void
+__close_nocancel_nostatus (int fd)
+{
+ __close_nocancel (fd);
+}
+
+/* Non cancellable writev syscall that does not also set errno in case of
+ failure. */
+static inline void
+__writev_nocancel_nostatus (int fd, const struct iovec *iov, int iovcnt)
+{
+ INTERNAL_SYSCALL_DECL (err);
+ INTERNAL_SYSCALL_CALL (writev, err, fd, iov, iovcnt);
+}
+
+/* Uncancelable waitpid. */
+__typeof (waitpid) __waitpid_nocancel;
+
+/* Uncancelable pause. */
+__typeof (pause) __pause_nocancel;
+
+/* Uncancelable nanosleep. */
+__typeof (__nanosleep) __nanosleep_nocancel;
+
+/* Uncancelable fcntl. */
+__typeof (__fcntl) __fcntl64_nocancel;
+
+hidden_proto (__open_nocancel)
+hidden_proto (__open64_nocancel)
+hidden_proto (__openat_nocancel)
+hidden_proto (__openat64_nocancel)
+hidden_proto (__read_nocancel)
+hidden_proto (__write_nocancel)
+hidden_proto (__close_nocancel)
+hidden_proto (__waitpid_nocancel)
+hidden_proto (__pause_nocancel)
+hidden_proto (__nanosleep_nocancel)
+hidden_proto (__fcntl64_nocancel)
+
+#endif /* NOT_CANCEL_H */
diff --git a/nptl_2_17/sysdeps/unix/sysv/linux/sysdep_2_17.h b/nptl_2_17/sysdeps/unix/sysv/linux/sysdep_2_17.h
new file mode 100644
index 00000000..4fd0a9ba
--- /dev/null
+++ b/nptl_2_17/sysdeps/unix/sysv/linux/sysdep_2_17.h
@@ -0,0 +1,68 @@
+/* Copyright (C) 2015-2018 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 <bits/wordsize.h>
+#include <kernel-features.h>
+
+/* Set error number and return -1. A target may choose to return the
+ internal function, __syscall_error, which sets errno and returns -1.
+ We use -1l, instead of -1, so that it can be casted to (void *). */
+#define INLINE_SYSCALL_ERROR_RETURN_VALUE(err) \
+ ({ \
+ __set_errno (err); \
+ -1l; \
+ })
+
+/* Provide a dummy argument that can be used to force register
+ alignment for register pairs if required by the syscall ABI. */
+#ifdef __ASSUME_ALIGNED_REGISTER_PAIRS
+#define __ALIGNMENT_ARG 0,
+#define __ALIGNMENT_COUNT(a,b) b
+#else
+#define __ALIGNMENT_ARG
+#define __ALIGNMENT_COUNT(a,b) a
+#endif
+
+/* Provide a common macro to pass 64-bit value on syscalls. */
+#if __WORDSIZE == 64 || defined __ASSUME_WORDSIZE64_ILP32
+# define SYSCALL_LL(val) (val)
+# define SYSCALL_LL64(val) (val)
+#else
+#define SYSCALL_LL(val) \
+ __LONG_LONG_PAIR ((val) >> 31, (val))
+#define SYSCALL_LL64(val) \
+ __LONG_LONG_PAIR ((long) ((val) >> 32), (long) ((val) & 0xffffffff))
+#endif
+
+/* Provide a common macro to pass 64-bit value on pread and pwrite
+ syscalls. */
+#ifdef __ASSUME_PRW_DUMMY_ARG
+# define SYSCALL_LL_PRW(val) 0, SYSCALL_LL (val)
+# define SYSCALL_LL64_PRW(val) 0, SYSCALL_LL64 (val)
+#else
+# define SYSCALL_LL_PRW(val) __ALIGNMENT_ARG SYSCALL_LL (val)
+# define SYSCALL_LL64_PRW(val) __ALIGNMENT_ARG SYSCALL_LL64 (val)
+#endif
+
+/* Provide a macro to pass the off{64}_t argument on p{readv,writev}{64}. */
+#define LO_HI_LONG(val) \
+ (long) (val), \
+ (long) (((uint64_t) (val)) >> 32)
+
+/* Exports the __send symbol on send.c linux implementation (some ABI have
+ it missing due the usage of a old generic version without it). */
+#define HAVE_INTERNAL_SEND_SYMBOL 1
diff --git a/nptl_2_17/sysdeps/unix/sysv/linux/x86_64/sysdep_2_17.h b/nptl_2_17/sysdeps/unix/sysv/linux/x86_64/sysdep_2_17.h
new file mode 100644
index 00000000..8cf61c21
--- /dev/null
+++ b/nptl_2_17/sysdeps/unix/sysv/linux/x86_64/sysdep_2_17.h
@@ -0,0 +1,432 @@
+/* Copyright (C) 2001-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _LINUX_X86_64_SYSDEP_H
+#define _LINUX_X86_64_SYSDEP_H 1
+
+/* There is some commonality. */
+#include <sysdeps/unix/sysv/linux/sysdep_2_17.h>
+#include <sysdeps/unix/x86_64/sysdep_2_17.h>
+#include "descr_2_17.h"
+#include <tls.h>
+
+/* Defines RTLD_PRIVATE_ERRNO. */
+#include <dl-sysdep.h>
+
+/* For Linux we can use the system call table in the header file
+ /usr/include/asm/unistd.h
+ of the kernel. But these symbols do not follow the SYS_* syntax
+ so we have to redefine the `SYS_ify' macro here. */
+#undef SYS_ify
+#define SYS_ify(syscall_name) __NR_##syscall_name
+
+/* This is a kludge to make syscalls.list find these under the names
+ pread and pwrite, since some kernel headers define those names
+ and some define the *64 names for the same system calls. */
+#if !defined __NR_pread && defined __NR_pread64
+# define __NR_pread __NR_pread64
+#endif
+#if !defined __NR_pwrite && defined __NR_pwrite64
+# define __NR_pwrite __NR_pwrite64
+#endif
+
+/* This is to help the old kernel headers where __NR_semtimedop is not
+ available. */
+#ifndef __NR_semtimedop
+# define __NR_semtimedop 220
+#endif
+
+
+#ifdef __ASSEMBLER__
+
+/* Linux uses a negative return value to indicate syscall errors,
+ unlike most Unices, which use the condition codes' carry flag.
+
+ Since version 2.1 the return value of a system call might be
+ negative even if the call succeeded. E.g., the `lseek' system call
+ might return a large offset. Therefore we must not anymore test
+ for < 0, but test for a real error by making sure the value in %eax
+ is a real error number. Linus said he will make sure the no syscall
+ returns a value in -1 .. -4095 as a valid result so we can savely
+ test with -4095. */
+
+/* We don't want the label for the error handle to be global when we define
+ it here. */
+# ifdef PIC
+# define SYSCALL_ERROR_LABEL 0f
+# else
+# define SYSCALL_ERROR_LABEL syscall_error
+# endif
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args) \
+ .text; \
+ ENTRY (name) \
+ DO_CALL (syscall_name, args); \
+ cmpq $-4095, %rax; \
+ jae SYSCALL_ERROR_LABEL
+
+# undef PSEUDO_END
+# define PSEUDO_END(name) \
+ SYSCALL_ERROR_HANDLER \
+ END (name)
+
+# undef PSEUDO_NOERRNO
+# define PSEUDO_NOERRNO(name, syscall_name, args) \
+ .text; \
+ ENTRY (name) \
+ DO_CALL (syscall_name, args)
+
+# undef PSEUDO_END_NOERRNO
+# define PSEUDO_END_NOERRNO(name) \
+ END (name)
+
+# define ret_NOERRNO ret
+
+# undef PSEUDO_ERRVAL
+# define PSEUDO_ERRVAL(name, syscall_name, args) \
+ .text; \
+ ENTRY (name) \
+ DO_CALL (syscall_name, args); \
+ negq %rax
+
+# undef PSEUDO_END_ERRVAL
+# define PSEUDO_END_ERRVAL(name) \
+ END (name)
+
+# define ret_ERRVAL ret
+
+# if defined PIC && RTLD_PRIVATE_ERRNO
+# define SYSCALL_SET_ERRNO \
+ lea rtld_errno(%rip), %RCX_LP; \
+ neg %eax; \
+ movl %eax, (%rcx)
+# else
+# if IS_IN (libc)
+# define SYSCALL_ERROR_ERRNO __libc_errno
+# else
+# define SYSCALL_ERROR_ERRNO errno
+# endif
+# define SYSCALL_SET_ERRNO \
+ movq SYSCALL_ERROR_ERRNO@GOTTPOFF(%rip), %rcx;\
+ neg %eax; \
+ movl %eax, %fs:(%rcx);
+# endif
+
+# ifndef PIC
+# define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */
+# else
+# define SYSCALL_ERROR_HANDLER \
+0: \
+ SYSCALL_SET_ERRNO; \
+ or $-1, %RAX_LP; \
+ ret;
+# endif /* PIC */
+
+/* The Linux/x86-64 kernel expects the system call parameters in
+ registers according to the following table:
+
+ syscall number rax
+ arg 1 rdi
+ arg 2 rsi
+ arg 3 rdx
+ arg 4 r10
+ arg 5 r8
+ arg 6 r9
+
+ The Linux kernel uses and destroys internally these registers:
+ return address from
+ syscall rcx
+ eflags from syscall r11
+
+ Normal function call, including calls to the system call stub
+ functions in the libc, get the first six parameters passed in
+ registers and the seventh parameter and later on the stack. The
+ register use is as follows:
+
+ system call number in the DO_CALL macro
+ arg 1 rdi
+ arg 2 rsi
+ arg 3 rdx
+ arg 4 rcx
+ arg 5 r8
+ arg 6 r9
+
+ We have to take care that the stack is aligned to 16 bytes. When
+ called the stack is not aligned since the return address has just
+ been pushed.
+
+
+ Syscalls of more than 6 arguments are not supported. */
+
+# undef DO_CALL
+# define DO_CALL(syscall_name, args) \
+ DOARGS_##args \
+ movl $SYS_ify (syscall_name), %eax; \
+ syscall;
+
+# define DOARGS_0 /* nothing */
+# define DOARGS_1 /* nothing */
+# define DOARGS_2 /* nothing */
+# define DOARGS_3 /* nothing */
+# define DOARGS_4 movq %rcx, %r10;
+# define DOARGS_5 DOARGS_4
+# define DOARGS_6 DOARGS_5
+
+#else /* !__ASSEMBLER__ */
+/* Define a macro which expands inline into the wrapper code for a system
+ call. */
+# undef INLINE_SYSCALL
+# define INLINE_SYSCALL(name, nr, args...) \
+ ({ \
+ unsigned long int resultvar = INTERNAL_SYSCALL (name, , nr, args); \
+ if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (resultvar, ))) \
+ { \
+ __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, )); \
+ resultvar = (unsigned long int) -1; \
+ } \
+ (long int) resultvar; })
+
+/* Define a macro with explicit types for arguments, which expands inline
+ into the wrapper code for a system call. It should be used when size
+ of any argument > size of long int. */
+# undef INLINE_SYSCALL_TYPES
+# define INLINE_SYSCALL_TYPES(name, nr, args...) \
+ ({ \
+ unsigned long int resultvar = INTERNAL_SYSCALL_TYPES (name, , nr, args); \
+ if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (resultvar, ))) \
+ { \
+ __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, )); \
+ resultvar = (unsigned long int) -1; \
+ } \
+ (long int) resultvar; })
+
+# undef INTERNAL_SYSCALL_DECL
+# define INTERNAL_SYSCALL_DECL(err) do { } while (0)
+
+/* Registers clobbered by syscall. */
+# define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx"
+
+/* Create a variable 'name' based on type 'X' to avoid explicit types.
+ This is mainly used set use 64-bits arguments in x32. */
+#define TYPEFY(X, name) __typeof__ ((X) - (X)) name
+/* Explicit cast the argument to avoid integer from pointer warning on
+ x32. */
+#define ARGIFY(X) ((__typeof__ ((X) - (X))) (X))
+
+#undef INTERNAL_SYSCALL
+#define INTERNAL_SYSCALL(name, err, nr, args...) \
+ internal_syscall##nr (SYS_ify (name), err, args)
+
+#undef INTERNAL_SYSCALL_NCS
+#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
+ internal_syscall##nr (number, err, args)
+
+#undef internal_syscall0
+#define internal_syscall0(number, err, dummy...) \
+({ \
+ unsigned long int resultvar; \
+ asm volatile ( \
+ "syscall\n\t" \
+ : "=a" (resultvar) \
+ : "0" (number) \
+ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
+ (long int) resultvar; \
+})
+
+#undef internal_syscall1
+#define internal_syscall1(number, err, arg1) \
+({ \
+ unsigned long int resultvar; \
+ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
+ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
+ asm volatile ( \
+ "syscall\n\t" \
+ : "=a" (resultvar) \
+ : "0" (number), "r" (_a1) \
+ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
+ (long int) resultvar; \
+})
+
+#undef internal_syscall2
+#define internal_syscall2(number, err, arg1, arg2) \
+({ \
+ unsigned long int resultvar; \
+ TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
+ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
+ register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
+ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
+ asm volatile ( \
+ "syscall\n\t" \
+ : "=a" (resultvar) \
+ : "0" (number), "r" (_a1), "r" (_a2) \
+ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
+ (long int) resultvar; \
+})
+
+#undef internal_syscall3
+#define internal_syscall3(number, err, arg1, arg2, arg3) \
+({ \
+ unsigned long int resultvar; \
+ TYPEFY (arg3, __arg3) = ARGIFY (arg3); \
+ TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
+ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
+ register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \
+ register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
+ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
+ asm volatile ( \
+ "syscall\n\t" \
+ : "=a" (resultvar) \
+ : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3) \
+ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
+ (long int) resultvar; \
+})
+
+#undef internal_syscall4
+#define internal_syscall4(number, err, arg1, arg2, arg3, arg4) \
+({ \
+ unsigned long int resultvar; \
+ TYPEFY (arg4, __arg4) = ARGIFY (arg4); \
+ TYPEFY (arg3, __arg3) = ARGIFY (arg3); \
+ TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
+ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
+ register TYPEFY (arg4, _a4) asm ("r10") = __arg4; \
+ register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \
+ register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
+ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
+ asm volatile ( \
+ "syscall\n\t" \
+ : "=a" (resultvar) \
+ : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4) \
+ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
+ (long int) resultvar; \
+})
+
+#undef internal_syscall5
+#define internal_syscall5(number, err, arg1, arg2, arg3, arg4, arg5) \
+({ \
+ unsigned long int resultvar; \
+ TYPEFY (arg5, __arg5) = ARGIFY (arg5); \
+ TYPEFY (arg4, __arg4) = ARGIFY (arg4); \
+ TYPEFY (arg3, __arg3) = ARGIFY (arg3); \
+ TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
+ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
+ register TYPEFY (arg5, _a5) asm ("r8") = __arg5; \
+ register TYPEFY (arg4, _a4) asm ("r10") = __arg4; \
+ register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \
+ register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
+ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
+ asm volatile ( \
+ "syscall\n\t" \
+ : "=a" (resultvar) \
+ : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4), \
+ "r" (_a5) \
+ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
+ (long int) resultvar; \
+})
+
+#undef internal_syscall6
+#define internal_syscall6(number, err, arg1, arg2, arg3, arg4, arg5, arg6) \
+({ \
+ unsigned long int resultvar; \
+ TYPEFY (arg6, __arg6) = ARGIFY (arg6); \
+ TYPEFY (arg5, __arg5) = ARGIFY (arg5); \
+ TYPEFY (arg4, __arg4) = ARGIFY (arg4); \
+ TYPEFY (arg3, __arg3) = ARGIFY (arg3); \
+ TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
+ TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
+ register TYPEFY (arg6, _a6) asm ("r9") = __arg6; \
+ register TYPEFY (arg5, _a5) asm ("r8") = __arg5; \
+ register TYPEFY (arg4, _a4) asm ("r10") = __arg4; \
+ register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \
+ register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
+ register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
+ asm volatile ( \
+ "syscall\n\t" \
+ : "=a" (resultvar) \
+ : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4), \
+ "r" (_a5), "r" (_a6) \
+ : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
+ (long int) resultvar; \
+})
+
+# undef INTERNAL_SYSCALL_ERROR_P
+# define INTERNAL_SYSCALL_ERROR_P(val, err) \
+ ((unsigned long int) (long int) (val) >= -4095L)
+
+# undef INTERNAL_SYSCALL_ERRNO
+# define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))
+
+/* List of system calls which are supported as vsyscalls. */
+# define HAVE_CLOCK_GETTIME_VSYSCALL 1
+# define HAVE_GETTIMEOFDAY_VSYSCALL 1
+# define HAVE_GETCPU_VSYSCALL 1
+
+# define SINGLE_THREAD_BY_GLOBAL 1
+
+#endif /* __ASSEMBLER__ */
+
+
+/* Pointer mangling support. */
+#if IS_IN (rtld)
+/* We cannot use the thread descriptor because in ld.so we use setjmp
+ earlier than the descriptor is initialized. */
+# ifdef __ASSEMBLER__
+# define PTR_MANGLE(reg) xor __pointer_chk_guard_local(%rip), reg; \
+ rol $2*LP_SIZE+1, reg
+# define PTR_DEMANGLE(reg) ror $2*LP_SIZE+1, reg; \
+ xor __pointer_chk_guard_local(%rip), reg
+# else
+# define PTR_MANGLE(reg) asm ("xor __pointer_chk_guard_local(%%rip), %0\n" \
+ "rol $2*" LP_SIZE "+1, %0" \
+ : "=r" (reg) : "0" (reg))
+# define PTR_DEMANGLE(reg) asm ("ror $2*" LP_SIZE "+1, %0\n" \
+ "xor __pointer_chk_guard_local(%%rip), %0" \
+ : "=r" (reg) : "0" (reg))
+# endif
+#else
+# ifdef __ASSEMBLER__
+# define PTR_MANGLE(reg) xor %fs:POINTER_GUARD, reg; \
+ rol $2*LP_SIZE+1, reg
+# define PTR_DEMANGLE(reg) ror $2*LP_SIZE+1, reg; \
+ xor %fs:POINTER_GUARD, reg
+# else
+# define PTR_MANGLE(var) asm ("xor %%fs:%c2, %0\n" \
+ "rol $2*" LP_SIZE "+1, %0" \
+ : "=r" (var) \
+ : "0" (var), \
+ "i" (offsetof (tcbhead_t, \
+ pointer_guard)))
+# define PTR_DEMANGLE(var) asm ("ror $2*" LP_SIZE "+1, %0\n" \
+ "xor %%fs:%c2, %0" \
+ : "=r" (var) \
+ : "0" (var), \
+ "i" (offsetof (tcbhead_t, \
+ pointer_guard)))
+# endif
+#endif
+
+/* How to pass the off{64}_t argument on p{readv,writev}{64}. */
+#undef LO_HI_LONG
+#define LO_HI_LONG(val) (val), 0
+
+/* Each shadow stack slot takes 8 bytes. Assuming that each stack
+ frame takes 256 bytes, this is used to compute shadow stack size
+ from stack size. */
+#define STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT 5
+
+#endif /* linux/x86_64/sysdep.h */
diff --git a/nptl_2_17/sysdeps/unix/x86_64/sysdep_2_17.h b/nptl_2_17/sysdeps/unix/x86_64/sysdep_2_17.h
new file mode 100644
index 00000000..5d61be20
--- /dev/null
+++ b/nptl_2_17/sysdeps/unix/x86_64/sysdep_2_17.h
@@ -0,0 +1,34 @@
+/* Copyright (C) 1991-2018 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 <sysdeps/unix/sysdep_2_17.h>
+#include <sysdeps/x86_64/sysdep_2_17.h>
+
+#ifdef __ASSEMBLER__
+
+/* This is defined as a separate macro so that other sysdep.h files
+ can include this one and then redefine DO_CALL. */
+
+#define DO_CALL(syscall_name, args) \
+ lea SYS_ify (syscall_name), %rax; \
+ syscall
+
+#define r0 %rax /* Normal return-value register. */
+#define r1 %rbx /* Secondary return-value register. */
+#define MOVE(x,y) movq x, y
+
+#endif /* __ASSEMBLER__ */
diff --git a/nptl_2_17/sysdeps/x86/sysdep_2_17.h b/nptl_2_17/sysdeps/x86/sysdep_2_17.h
new file mode 100644
index 00000000..9f319ea4
--- /dev/null
+++ b/nptl_2_17/sysdeps/x86/sysdep_2_17.h
@@ -0,0 +1,104 @@
+/* Assembler macros for x86.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _X86_SYSDEP_H
+#define _X86_SYSDEP_H 1
+
+#include <sysdeps/generic/sysdep_2_17.h>
+
+/* __CET__ is defined by GCC with Control-Flow Protection values:
+
+enum cf_protection_level
+{
+ CF_NONE = 0,
+ CF_BRANCH = 1 << 0,
+ CF_RETURN = 1 << 1,
+ CF_FULL = CF_BRANCH | CF_RETURN,
+ CF_SET = 1 << 2
+};
+*/
+
+/* Set if CF_BRANCH (IBT) is enabled. */
+#define X86_FEATURE_1_IBT (1U << 0)
+/* Set if CF_RETURN (SHSTK) is enabled. */
+#define X86_FEATURE_1_SHSTK (1U << 1)
+
+#ifdef __CET__
+# define CET_ENABLED 1
+# define IBT_ENABLED (__CET__ & X86_FEATURE_1_IBT)
+# define SHSTK_ENABLED (__CET__ & X86_FEATURE_1_SHSTK)
+#else
+# define CET_ENABLED 0
+# define IBT_ENABLED 0
+# define SHSTK_ENABLED 0
+#endif
+
+#ifdef __ASSEMBLER__
+
+/* Syntactic details of assembler. */
+
+#ifdef _CET_ENDBR
+# define _CET_NOTRACK notrack
+#else
+# define _CET_ENDBR
+# define _CET_NOTRACK
+#endif
+
+/* ELF uses byte-counts for .align, most others use log2 of count of bytes. */
+#define ALIGNARG(log2) 1<<log2
+#define ASM_SIZE_DIRECTIVE(name) .size name,.-name;
+
+/* Define an entry point visible from C. */
+#define ENTRY(name) \
+ .globl C_SYMBOL_NAME(name); \
+ .type C_SYMBOL_NAME(name),@function; \
+ .align ALIGNARG(4); \
+ C_LABEL(name) \
+ cfi_startproc; \
+ _CET_ENDBR; \
+ CALL_MCOUNT
+
+#undef END
+#define END(name) \
+ cfi_endproc; \
+ ASM_SIZE_DIRECTIVE(name)
+
+#define ENTRY_CHK(name) ENTRY (name)
+#define END_CHK(name) END (name)
+
+/* Since C identifiers are not normally prefixed with an underscore
+ on this system, the asm identifier `syscall_error' intrudes on the
+ C name space. Make sure we use an innocuous name. */
+#define syscall_error __syscall_error
+#define mcount _mcount
+
+#undef PSEUDO_END
+#define PSEUDO_END(name) \
+ END (name)
+
+/* Local label name for asm code. */
+#ifndef L
+/* ELF-like local names start with `.L'. */
+# define L(name) .L##name
+#endif
+
+#define atom_text_section .section ".text.atom", "ax"
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* _X86_SYSDEP_H */
diff --git a/nptl_2_17/sysdeps/x86_64/nptl/bits/pthreadtypes-arch_2_17.h b/nptl_2_17/sysdeps/x86_64/nptl/bits/pthreadtypes-arch_2_17.h
new file mode 100644
index 00000000..290f2f46
--- /dev/null
+++ b/nptl_2_17/sysdeps/x86_64/nptl/bits/pthreadtypes-arch_2_17.h
@@ -0,0 +1,106 @@
+/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _BITS_PTHREADTYPES_ARCH_H
+#define _BITS_PTHREADTYPES_ARCH_H 1
+
+#include <bits/wordsize.h>
+
+#ifdef __x86_64__
+# if __WORDSIZE == 64
+# define __SIZEOF_PTHREAD_MUTEX_T 40
+# define __SIZEOF_PTHREAD_ATTR_T 56
+# define __SIZEOF_PTHREAD_MUTEX_T 40
+# define __SIZEOF_PTHREAD_RWLOCK_T 56
+# define __SIZEOF_PTHREAD_BARRIER_T 32
+# else
+# define __SIZEOF_PTHREAD_MUTEX_T 32
+# define __SIZEOF_PTHREAD_ATTR_T 32
+# define __SIZEOF_PTHREAD_MUTEX_T 32
+# define __SIZEOF_PTHREAD_RWLOCK_T 44
+# define __SIZEOF_PTHREAD_BARRIER_T 20
+# endif
+#else
+# define __SIZEOF_PTHREAD_MUTEX_T 24
+# define __SIZEOF_PTHREAD_ATTR_T 36
+# define __SIZEOF_PTHREAD_MUTEX_T 24
+# define __SIZEOF_PTHREAD_RWLOCK_T 32
+# define __SIZEOF_PTHREAD_BARRIER_T 20
+#endif
+#define __SIZEOF_PTHREAD_MUTEXATTR_T 4
+#define __SIZEOF_PTHREAD_COND_T 48
+#define __SIZEOF_PTHREAD_CONDATTR_T 4
+#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
+#define __SIZEOF_PTHREAD_BARRIERATTR_T 4
+
+/* Definitions for internal mutex struct. */
+#define __PTHREAD_COMPAT_PADDING_MID
+#define __PTHREAD_COMPAT_PADDING_END
+#define __PTHREAD_MUTEX_LOCK_ELISION 1
+#ifdef __x86_64__
+# define __PTHREAD_MUTEX_NUSERS_AFTER_KIND 0
+# define __PTHREAD_MUTEX_USE_UNION 0
+#else
+# define __PTHREAD_MUTEX_NUSERS_AFTER_KIND 1
+# define __PTHREAD_MUTEX_USE_UNION 1
+#endif
+
+#define __LOCK_ALIGNMENT
+#define __ONCE_ALIGNMENT
+
+struct __pthread_rwlock_arch_t
+{
+ unsigned int __readers;
+ unsigned int __writers;
+ unsigned int __wrphase_futex;
+ unsigned int __writers_futex;
+ unsigned int __pad3;
+ unsigned int __pad4;
+#ifdef __x86_64__
+ int __cur_writer;
+ int __shared;
+ signed char __rwelision;
+# ifdef __ILP32__
+ unsigned char __pad1[3];
+# define __PTHREAD_RWLOCK_ELISION_EXTRA 0, { 0, 0, 0 }
+# else
+ unsigned char __pad1[7];
+# define __PTHREAD_RWLOCK_ELISION_EXTRA 0, { 0, 0, 0, 0, 0, 0, 0 }
+# endif
+ unsigned long int __pad2;
+ /* FLAGS must stay at this position in the structure to maintain
+ binary compatibility. */
+ unsigned int __flags;
+# define __PTHREAD_RWLOCK_INT_FLAGS_SHARED 1
+#else
+ /* FLAGS must stay at this position in the structure to maintain
+ binary compatibility. */
+ unsigned char __flags;
+ unsigned char __shared;
+ signed char __rwelision;
+# define __PTHREAD_RWLOCK_ELISION_EXTRA 0
+ unsigned char __pad2;
+ int __cur_writer;
+#endif
+};
+
+#ifndef __x86_64__
+/* Extra attributes for the cleanup functions. */
+# define __cleanup_fct_attribute __attribute__ ((__regparm__ (1)))
+#endif
+
+#endif /* bits/pthreadtypes.h */
diff --git a/nptl_2_17/sysdeps/x86_64/sysdep_2_17.h b/nptl_2_17/sysdeps/x86_64/sysdep_2_17.h
new file mode 100644
index 00000000..ab1b6bea
--- /dev/null
+++ b/nptl_2_17/sysdeps/x86_64/sysdep_2_17.h
@@ -0,0 +1,129 @@
+/* Assembler macros for x86-64.
+ Copyright (C) 2001-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _X86_64_SYSDEP_H
+#define _X86_64_SYSDEP_H 1
+
+#include <sysdeps/x86/sysdep_2_17.h>
+
+#ifdef __ASSEMBLER__
+
+/* Syntactic details of assembler. */
+
+/* This macro is for setting proper CFI with DW_CFA_expression describing
+ the register as saved relative to %rsp instead of relative to the CFA.
+ Expression is DW_OP_drop, DW_OP_breg7 (%rsp is register 7), sleb128 offset
+ from %rsp. */
+#define cfi_offset_rel_rsp(regn, off) .cfi_escape 0x10, regn, 0x4, 0x13, \
+ 0x77, off & 0x7F | 0x80, off >> 7
+
+/* If compiled for profiling, call `mcount' at the start of each function. */
+#ifdef PROF
+/* The mcount code relies on a normal frame pointer being on the stack
+ to locate our caller, so push one just for its benefit. */
+#define CALL_MCOUNT \
+ pushq %rbp; \
+ cfi_adjust_cfa_offset(8); \
+ movq %rsp, %rbp; \
+ cfi_def_cfa_register(%rbp); \
+ call JUMPTARGET(mcount); \
+ popq %rbp; \
+ cfi_def_cfa(rsp,8);
+#else
+#define CALL_MCOUNT /* Do nothing. */
+#endif
+
+#define PSEUDO(name, syscall_name, args) \
+lose: \
+ jmp JUMPTARGET(syscall_error) \
+ .globl syscall_error; \
+ ENTRY (name) \
+ DO_CALL (syscall_name, args); \
+ jb lose
+
+#undef JUMPTARGET
+#ifdef SHARED
+# ifdef BIND_NOW
+# define JUMPTARGET(name) *name##@GOTPCREL(%rip)
+# else
+# define JUMPTARGET(name) name##@PLT
+# endif
+#else
+/* For static archives, branch to target directly. */
+# define JUMPTARGET(name) name
+#endif
+
+/* Long and pointer size in bytes. */
+#define LP_SIZE 8
+
+/* Instruction to operate on long and pointer. */
+#define LP_OP(insn) insn##q
+
+/* Assembler address directive. */
+#define ASM_ADDR .quad
+
+/* Registers to hold long and pointer. */
+#define RAX_LP rax
+#define RBP_LP rbp
+#define RBX_LP rbx
+#define RCX_LP rcx
+#define RDI_LP rdi
+#define RDX_LP rdx
+#define RSI_LP rsi
+#define RSP_LP rsp
+#define R8_LP r8
+#define R9_LP r9
+#define R10_LP r10
+#define R11_LP r11
+#define R12_LP r12
+#define R13_LP r13
+#define R14_LP r14
+#define R15_LP r15
+
+#else /* __ASSEMBLER__ */
+
+/* Long and pointer size in bytes. */
+#define LP_SIZE "8"
+
+/* Instruction to operate on long and pointer. */
+#define LP_OP(insn) #insn "q"
+
+/* Assembler address directive. */
+#define ASM_ADDR ".quad"
+
+/* Registers to hold long and pointer. */
+#define RAX_LP "rax"
+#define RBP_LP "rbp"
+#define RBX_LP "rbx"
+#define RCX_LP "rcx"
+#define RDI_LP "rdi"
+#define RDX_LP "rdx"
+#define RSI_LP "rsi"
+#define RSP_LP "rsp"
+#define R8_LP "r8"
+#define R9_LP "r9"
+#define R10_LP "r10"
+#define R11_LP "r11"
+#define R12_LP "r12"
+#define R13_LP "r13"
+#define R14_LP "r14"
+#define R15_LP "r15"
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* _X86_64_SYSDEP_H */
diff --git a/nptl_2_17/thread_db_2_17.h b/nptl_2_17/thread_db_2_17.h
new file mode 100644
index 00000000..4206aed0
--- /dev/null
+++ b/nptl_2_17/thread_db_2_17.h
@@ -0,0 +1,458 @@
+/* thread_db.h -- interface to libthread_db.so library for debugging -lpthread
+ Copyright (C) 1999-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _THREAD_DB_H
+#define _THREAD_DB_H 1
+
+/* This is the debugger interface for the NPTL library. It is
+ modelled closely after the interface with same names in Solaris
+ with the goal to share the same code in the debugger. */
+#include <pthread.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/procfs.h>
+
+
+/* Error codes of the library. */
+typedef enum
+{
+ TD_OK, /* No error. */
+ TD_ERR, /* No further specified error. */
+ TD_NOTHR, /* No matching thread found. */
+ TD_NOSV, /* No matching synchronization handle found. */
+ TD_NOLWP, /* No matching light-weighted process found. */
+ TD_BADPH, /* Invalid process handle. */
+ TD_BADTH, /* Invalid thread handle. */
+ TD_BADSH, /* Invalid synchronization handle. */
+ TD_BADTA, /* Invalid thread agent. */
+ TD_BADKEY, /* Invalid key. */
+ TD_NOMSG, /* No event available. */
+ TD_NOFPREGS, /* No floating-point register content available. */
+ TD_NOLIBTHREAD, /* Application not linked with thread library. */
+ TD_NOEVENT, /* Requested event is not supported. */
+ TD_NOCAPAB, /* Capability not available. */
+ TD_DBERR, /* Internal debug library error. */
+ TD_NOAPLIC, /* Operation is not applicable. */
+ TD_NOTSD, /* No thread-specific data available. */
+ TD_MALLOC, /* Out of memory. */
+ TD_PARTIALREG, /* Not entire register set was read or written. */
+ TD_NOXREGS, /* X register set not available for given thread. */
+ TD_TLSDEFER, /* Thread has not yet allocated TLS for given module. */
+ TD_NOTALLOC = TD_TLSDEFER,
+ TD_VERSION, /* Version if libpthread and libthread_db do not match. */
+ TD_NOTLS /* There is no TLS segment in the given module. */
+} td_err_e;
+
+
+/* Possible thread states. TD_THR_ANY_STATE is a pseudo-state used to
+ select threads regardless of state in td_ta_thr_iter(). */
+typedef enum
+{
+ TD_THR_ANY_STATE,
+ TD_THR_UNKNOWN,
+ TD_THR_STOPPED,
+ TD_THR_RUN,
+ TD_THR_ACTIVE,
+ TD_THR_ZOMBIE,
+ TD_THR_SLEEP,
+ TD_THR_STOPPED_ASLEEP
+} td_thr_state_e;
+
+/* Thread type: user or system. TD_THR_ANY_TYPE is a pseudo-type used
+ to select threads regardless of type in td_ta_thr_iter(). */
+typedef enum
+{
+ TD_THR_ANY_TYPE,
+ TD_THR_USER,
+ TD_THR_SYSTEM
+} td_thr_type_e;
+
+
+/* Types of the debugging library. */
+
+/* Handle for a process. This type is opaque. */
+typedef struct td_thragent td_thragent_t;
+
+/* The actual thread handle type. This is also opaque. */
+typedef struct td_thrhandle
+{
+ td_thragent_t *th_ta_p;
+ psaddr_t th_unique;
+} td_thrhandle_t;
+
+
+/* Forward declaration of a type defined by and for the dynamic linker. */
+struct link_map;
+
+
+/* Flags for `td_ta_thr_iter'. */
+#define TD_THR_ANY_USER_FLAGS 0xffffffff
+#define TD_THR_LOWEST_PRIORITY -20
+#define TD_SIGNO_MASK NULL
+
+
+#define TD_EVENTSIZE 2
+#define BT_UISHIFT 5 /* log base 2 of BT_NBIPUI, to extract word index */
+#define BT_NBIPUI (1 << BT_UISHIFT) /* n bits per unsigned int */
+#define BT_UIMASK (BT_NBIPUI - 1) /* to extract bit index */
+
+/* Bitmask of enabled events. */
+typedef struct td_thr_events
+{
+ uint32_t event_bits[TD_EVENTSIZE];
+} td_thr_events_t;
+
+/* Event set manipulation macros. */
+#define __td_eventmask(n) \
+ (UINT32_C (1) << (((n) - 1) & BT_UIMASK))
+#define __td_eventword(n) \
+ ((UINT32_C ((n) - 1)) >> BT_UISHIFT)
+
+#define td_event_emptyset(setp) \
+ do { \
+ int __i; \
+ for (__i = TD_EVENTSIZE; __i > 0; --__i) \
+ (setp)->event_bits[__i - 1] = 0; \
+ } while (0)
+
+#define td_event_fillset(setp) \
+ do { \
+ int __i; \
+ for (__i = TD_EVENTSIZE; __i > 0; --__i) \
+ (setp)->event_bits[__i - 1] = UINT32_C (0xffffffff); \
+ } while (0)
+
+#define td_event_addset(setp, n) \
+ (((setp)->event_bits[__td_eventword (n)]) |= __td_eventmask (n))
+#define td_event_delset(setp, n) \
+ (((setp)->event_bits[__td_eventword (n)]) &= ~__td_eventmask (n))
+#define td_eventismember(setp, n) \
+ (__td_eventmask (n) & ((setp)->event_bits[__td_eventword (n)]))
+#if TD_EVENTSIZE == 2
+# define td_eventisempty(setp) \
+ (!((setp)->event_bits[0]) && !((setp)->event_bits[1]))
+#else
+# error "td_eventisempty must be changed to match TD_EVENTSIZE"
+#endif
+
+/* Events reportable by the thread implementation. */
+typedef enum
+{
+ TD_ALL_EVENTS, /* Pseudo-event number. */
+ TD_EVENT_NONE = TD_ALL_EVENTS, /* Depends on context. */
+ TD_READY, /* Is executable now. */
+ TD_SLEEP, /* Blocked in a synchronization obj. */
+ TD_SWITCHTO, /* Now assigned to a process. */
+ TD_SWITCHFROM, /* Not anymore assigned to a process. */
+ TD_LOCK_TRY, /* Trying to get an unavailable lock. */
+ TD_CATCHSIG, /* Signal posted to the thread. */
+ TD_IDLE, /* Process getting idle. */
+ TD_CREATE, /* New thread created. */
+ TD_DEATH, /* Thread terminated. */
+ TD_PREEMPT, /* Preempted. */
+ TD_PRI_INHERIT, /* Inherited elevated priority. */
+ TD_REAP, /* Reaped. */
+ TD_CONCURRENCY, /* Number of processes changing. */
+ TD_TIMEOUT, /* Conditional variable wait timed out. */
+ TD_MIN_EVENT_NUM = TD_READY,
+ TD_MAX_EVENT_NUM = TD_TIMEOUT,
+ TD_EVENTS_ENABLE = 31 /* Event reporting enabled. */
+} td_event_e;
+
+/* Values representing the different ways events are reported. */
+typedef enum
+{
+ NOTIFY_BPT, /* User must insert breakpoint at u.bptaddr. */
+ NOTIFY_AUTOBPT, /* Breakpoint at u.bptaddr is automatically
+ inserted. */
+ NOTIFY_SYSCALL /* System call u.syscallno will be invoked. */
+} td_notify_e;
+
+/* Description how event type is reported. */
+typedef struct td_notify
+{
+ td_notify_e type; /* Way the event is reported. */
+ union
+ {
+ psaddr_t bptaddr; /* Address of breakpoint. */
+ int syscallno; /* Number of system call used. */
+ } u;
+} td_notify_t;
+
+/* Structure used to report event. */
+typedef struct td_event_msg
+{
+ td_event_e event; /* Event type being reported. */
+ const td_thrhandle_t *th_p; /* Thread reporting the event. */
+ union
+ {
+# if 0
+ td_synchandle_t *sh; /* Handle of synchronization object. */
+#endif
+ uintptr_t data; /* Event specific data. */
+ } msg;
+} td_event_msg_t;
+
+/* Structure containing event data available in each thread structure. */
+typedef struct
+{
+ td_thr_events_t eventmask; /* Mask of enabled events. */
+ td_event_e eventnum; /* Number of last event. */
+ void *eventdata; /* Data associated with event. */
+} td_eventbuf_t;
+
+
+/* Gathered statistics about the process. */
+typedef struct td_ta_stats
+{
+ int nthreads; /* Total number of threads in use. */
+ int r_concurrency; /* Concurrency level requested by user. */
+ int nrunnable_num; /* Average runnable threads, numerator. */
+ int nrunnable_den; /* Average runnable threads, denominator. */
+ int a_concurrency_num; /* Achieved concurrency level, numerator. */
+ int a_concurrency_den; /* Achieved concurrency level, denominator. */
+ int nlwps_num; /* Average number of processes in use,
+ numerator. */
+ int nlwps_den; /* Average number of processes in use,
+ denominator. */
+ int nidle_num; /* Average number of idling processes,
+ numerator. */
+ int nidle_den; /* Average number of idling processes,
+ denominator. */
+} td_ta_stats_t;
+
+
+/* Since Sun's library is based on Solaris threads we have to define a few
+ types to map them to POSIX threads. */
+typedef pthread_t thread_t;
+typedef pthread_key_t thread_key_t;
+
+
+/* Callback for iteration over threads. */
+typedef int td_thr_iter_f (const td_thrhandle_t *, void *);
+
+/* Callback for iteration over thread local data. */
+typedef int td_key_iter_f (thread_key_t, void (*) (void *), void *);
+
+
+
+/* Forward declaration. This has to be defined by the user. */
+struct ps_prochandle;
+
+
+/* Information about the thread. */
+typedef struct td_thrinfo
+{
+ td_thragent_t *ti_ta_p; /* Process handle. */
+ unsigned int ti_user_flags; /* Unused. */
+ thread_t ti_tid; /* Thread ID returned by
+ pthread_create(). */
+ char *ti_tls; /* Pointer to thread-local data. */
+ psaddr_t ti_startfunc; /* Start function passed to
+ pthread_create(). */
+ psaddr_t ti_stkbase; /* Base of thread's stack. */
+ long int ti_stksize; /* Size of thread's stack. */
+ psaddr_t ti_ro_area; /* Unused. */
+ int ti_ro_size; /* Unused. */
+ td_thr_state_e ti_state; /* Thread state. */
+ unsigned char ti_db_suspended; /* Nonzero if suspended by debugger. */
+ td_thr_type_e ti_type; /* Type of the thread (system vs
+ user thread). */
+ intptr_t ti_pc; /* Unused. */
+ intptr_t ti_sp; /* Unused. */
+ short int ti_flags; /* Unused. */
+ int ti_pri; /* Thread priority. */
+ lwpid_t ti_lid; /* Kernel PID for this thread. */
+ sigset_t ti_sigmask; /* Signal mask. */
+ unsigned char ti_traceme; /* Nonzero if event reporting
+ enabled. */
+ unsigned char ti_preemptflag; /* Unused. */
+ unsigned char ti_pirecflag; /* Unused. */
+ sigset_t ti_pending; /* Set of pending signals. */
+ td_thr_events_t ti_events; /* Set of enabled events. */
+} td_thrinfo_t;
+
+
+
+/* Prototypes for exported library functions. */
+
+/* Initialize the thread debug support library. */
+extern td_err_e td_init (void);
+
+/* Historical relict. Should not be used anymore. */
+extern td_err_e td_log (void);
+
+/* Return list of symbols the library can request. */
+extern const char **td_symbol_list (void);
+
+/* Generate new thread debug library handle for process PS. */
+extern td_err_e td_ta_new (struct ps_prochandle *__ps, td_thragent_t **__ta);
+
+/* Free resources allocated for TA. */
+extern td_err_e td_ta_delete (td_thragent_t *__ta);
+
+/* Get number of currently running threads in process associated with TA. */
+extern td_err_e td_ta_get_nthreads (const td_thragent_t *__ta, int *__np);
+
+/* Return process handle passed in `td_ta_new' for process associated with
+ TA. */
+extern td_err_e td_ta_get_ph (const td_thragent_t *__ta,
+ struct ps_prochandle **__ph);
+
+/* Map thread library handle PT to thread debug library handle for process
+ associated with TA and store result in *TH. */
+extern td_err_e td_ta_map_id2thr (const td_thragent_t *__ta, pthread_t __pt,
+ td_thrhandle_t *__th);
+
+/* Map process ID LWPID to thread debug library handle for process
+ associated with TA and store result in *TH. */
+extern td_err_e td_ta_map_lwp2thr (const td_thragent_t *__ta, lwpid_t __lwpid,
+ td_thrhandle_t *__th);
+
+
+/* Call for each thread in a process associated with TA the callback function
+ CALLBACK. */
+extern td_err_e td_ta_thr_iter (const td_thragent_t *__ta,
+ td_thr_iter_f *__callback, void *__cbdata_p,
+ td_thr_state_e __state, int __ti_pri,
+ sigset_t *__ti_sigmask_p,
+ unsigned int __ti_user_flags);
+
+/* Call for each defined thread local data entry the callback function KI. */
+extern td_err_e td_ta_tsd_iter (const td_thragent_t *__ta, td_key_iter_f *__ki,
+ void *__p);
+
+
+/* Get event address for EVENT. */
+extern td_err_e td_ta_event_addr (const td_thragent_t *__ta,
+ td_event_e __event, td_notify_t *__ptr);
+
+/* Enable EVENT in global mask. */
+extern td_err_e td_ta_set_event (const td_thragent_t *__ta,
+ td_thr_events_t *__event);
+
+/* Disable EVENT in global mask. */
+extern td_err_e td_ta_clear_event (const td_thragent_t *__ta,
+ td_thr_events_t *__event);
+
+/* Return information about last event. */
+extern td_err_e td_ta_event_getmsg (const td_thragent_t *__ta,
+ td_event_msg_t *__msg);
+
+
+/* Set suggested concurrency level for process associated with TA. */
+extern td_err_e td_ta_setconcurrency (const td_thragent_t *__ta, int __level);
+
+
+/* Enable collecting statistics for process associated with TA. */
+extern td_err_e td_ta_enable_stats (const td_thragent_t *__ta, int __enable);
+
+/* Reset statistics. */
+extern td_err_e td_ta_reset_stats (const td_thragent_t *__ta);
+
+/* Retrieve statistics from process associated with TA. */
+extern td_err_e td_ta_get_stats (const td_thragent_t *__ta,
+ td_ta_stats_t *__statsp);
+
+
+/* Validate that TH is a thread handle. */
+extern td_err_e td_thr_validate (const td_thrhandle_t *__th);
+
+/* Return information about thread TH. */
+extern td_err_e td_thr_get_info (const td_thrhandle_t *__th,
+ td_thrinfo_t *__infop);
+
+/* Retrieve floating-point register contents of process running thread TH. */
+extern td_err_e td_thr_getfpregs (const td_thrhandle_t *__th,
+ prfpregset_t *__regset);
+
+/* Retrieve general register contents of process running thread TH. */
+extern td_err_e td_thr_getgregs (const td_thrhandle_t *__th,
+ prgregset_t __gregs);
+
+/* Retrieve extended register contents of process running thread TH. */
+extern td_err_e td_thr_getxregs (const td_thrhandle_t *__th, void *__xregs);
+
+/* Get size of extended register set of process running thread TH. */
+extern td_err_e td_thr_getxregsize (const td_thrhandle_t *__th, int *__sizep);
+
+/* Set floating-point register contents of process running thread TH. */
+extern td_err_e td_thr_setfpregs (const td_thrhandle_t *__th,
+ const prfpregset_t *__fpregs);
+
+/* Set general register contents of process running thread TH. */
+extern td_err_e td_thr_setgregs (const td_thrhandle_t *__th,
+ prgregset_t __gregs);
+
+/* Set extended register contents of process running thread TH. */
+extern td_err_e td_thr_setxregs (const td_thrhandle_t *__th,
+ const void *__addr);
+
+
+/* Get address of the given module's TLS storage area for the given thread. */
+extern td_err_e td_thr_tlsbase (const td_thrhandle_t *__th,
+ unsigned long int __modid,
+ psaddr_t *__base);
+
+/* Get address of thread local variable. */
+extern td_err_e td_thr_tls_get_addr (const td_thrhandle_t *__th,
+ psaddr_t __map_address, size_t __offset,
+ psaddr_t *__address);
+
+
+/* Enable reporting for EVENT for thread TH. */
+extern td_err_e td_thr_event_enable (const td_thrhandle_t *__th, int __event);
+
+/* Enable EVENT for thread TH. */
+extern td_err_e td_thr_set_event (const td_thrhandle_t *__th,
+ td_thr_events_t *__event);
+
+/* Disable EVENT for thread TH. */
+extern td_err_e td_thr_clear_event (const td_thrhandle_t *__th,
+ td_thr_events_t *__event);
+
+/* Get event message for thread TH. */
+extern td_err_e td_thr_event_getmsg (const td_thrhandle_t *__th,
+ td_event_msg_t *__msg);
+
+
+/* Set priority of thread TH. */
+extern td_err_e td_thr_setprio (const td_thrhandle_t *__th, int __prio);
+
+
+/* Set pending signals for thread TH. */
+extern td_err_e td_thr_setsigpending (const td_thrhandle_t *__th,
+ unsigned char __n, const sigset_t *__ss);
+
+/* Set signal mask for thread TH. */
+extern td_err_e td_thr_sigsetmask (const td_thrhandle_t *__th,
+ const sigset_t *__ss);
+
+
+/* Return thread local data associated with key TK in thread TH. */
+extern td_err_e td_thr_tsd (const td_thrhandle_t *__th,
+ const thread_key_t __tk, void **__data);
+
+
+/* Suspend execution of thread TH. */
+extern td_err_e td_thr_dbsuspend (const td_thrhandle_t *__th);
+
+/* Resume execution of thread TH. */
+extern td_err_e td_thr_dbresume (const td_thrhandle_t *__th);
+
+#endif /* thread_db.h */
diff --git a/nptl_2_17/tpp_2_17.c b/nptl_2_17/tpp_2_17.c
new file mode 100644
index 00000000..45fff81a
--- /dev/null
+++ b/nptl_2_17/tpp_2_17.c
@@ -0,0 +1,195 @@
+/* Thread Priority Protect helpers.
+ Copyright (C) 2006-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@redhat.com>, 2006.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP_2_17.h"
+#include <assert.h>
+#include <atomic.h>
+#include <errno.h>
+#include <sched.h>
+#include <stdlib.h>
+#include <atomic.h>
+
+
+int __sched_fifo_min_prio = -1;
+int __sched_fifo_max_prio = -1;
+
+/* We only want to initialize __sched_fifo_min_prio and __sched_fifo_max_prio
+ once. The standard solution would be similar to pthread_once, but then
+ readers would need to use an acquire fence. In this specific case,
+ initialization is comprised of just idempotent writes to two variables
+ that have an initial value of -1. Therefore, we can treat each variable as
+ a separate, at-least-once initialized value. This enables using just
+ relaxed MO loads and stores, but requires that consumers check for
+ initialization of each value that is to be used; see
+ __pthread_tpp_change_priority for an example.
+ */
+void
+__init_sched_fifo_prio (void)
+{
+ atomic_store_relaxed (&__sched_fifo_max_prio,
+ __sched_get_priority_max (SCHED_FIFO));
+ atomic_store_relaxed (&__sched_fifo_min_prio,
+ __sched_get_priority_min (SCHED_FIFO));
+}
+
+int
+__pthread_tpp_change_priority (int previous_prio, int new_prio)
+{
+ struct pthread *self = THREAD_SELF;
+ struct priority_protection_data *tpp = THREAD_GETMEM (self, tpp);
+ int fifo_min_prio = atomic_load_relaxed (&__sched_fifo_min_prio);
+ int fifo_max_prio = atomic_load_relaxed (&__sched_fifo_max_prio);
+
+ if (tpp == NULL)
+ {
+ /* See __init_sched_fifo_prio. We need both the min and max prio,
+ so need to check both, and run initialization if either one is
+ not initialized. The memory model's write-read coherence rule
+ makes this work. */
+ if (fifo_min_prio == -1 || fifo_max_prio == -1)
+ {
+ __init_sched_fifo_prio ();
+ fifo_min_prio = atomic_load_relaxed (&__sched_fifo_min_prio);
+ fifo_max_prio = atomic_load_relaxed (&__sched_fifo_max_prio);
+ }
+
+ size_t size = sizeof *tpp;
+ size += (fifo_max_prio - fifo_min_prio + 1)
+ * sizeof (tpp->priomap[0]);
+ tpp = calloc (size, 1);
+ if (tpp == NULL)
+ return ENOMEM;
+ tpp->priomax = fifo_min_prio - 1;
+ THREAD_SETMEM (self, tpp, tpp);
+ }
+
+ assert (new_prio == -1
+ || (new_prio >= fifo_min_prio
+ && new_prio <= fifo_max_prio));
+ assert (previous_prio == -1
+ || (previous_prio >= fifo_min_prio
+ && previous_prio <= fifo_max_prio));
+
+ int priomax = tpp->priomax;
+ int newpriomax = priomax;
+ if (new_prio != -1)
+ {
+ if (tpp->priomap[new_prio - fifo_min_prio] + 1 == 0)
+ return EAGAIN;
+ ++tpp->priomap[new_prio - fifo_min_prio];
+ if (new_prio > priomax)
+ newpriomax = new_prio;
+ }
+
+ if (previous_prio != -1)
+ {
+ if (--tpp->priomap[previous_prio - fifo_min_prio] == 0
+ && priomax == previous_prio
+ && previous_prio > new_prio)
+ {
+ int i;
+ for (i = previous_prio - 1; i >= fifo_min_prio; --i)
+ if (tpp->priomap[i - fifo_min_prio])
+ break;
+ newpriomax = i;
+ }
+ }
+
+ if (priomax == newpriomax)
+ return 0;
+
+ /* See CREATE THREAD NOTES in nptl/pthread_create.c. */
+ lll_lock (self->lock, LLL_PRIVATE);
+
+ tpp->priomax = newpriomax;
+
+ int result = 0;
+
+ if ((self->flags & ATTR_FLAG_SCHED_SET) == 0)
+ {
+ if (__sched_getparam (self->tid, &self->schedparam) != 0)
+ result = errno;
+ else
+ self->flags |= ATTR_FLAG_SCHED_SET;
+ }
+
+ if ((self->flags & ATTR_FLAG_POLICY_SET) == 0)
+ {
+ self->schedpolicy = __sched_getscheduler (self->tid);
+ if (self->schedpolicy == -1)
+ result = errno;
+ else
+ self->flags |= ATTR_FLAG_POLICY_SET;
+ }
+
+ if (result == 0)
+ {
+ struct sched_param sp = self->schedparam;
+ if (sp.sched_priority < newpriomax || sp.sched_priority < priomax)
+ {
+ if (sp.sched_priority < newpriomax)
+ sp.sched_priority = newpriomax;
+
+ if (__sched_setscheduler (self->tid, self->schedpolicy, &sp) < 0)
+ result = errno;
+ }
+ }
+
+ lll_unlock (self->lock, LLL_PRIVATE);
+
+ return result;
+}
+
+int
+__pthread_current_priority (void)
+{
+ struct pthread *self = THREAD_SELF;
+ if ((self->flags & (ATTR_FLAG_POLICY_SET | ATTR_FLAG_SCHED_SET))
+ == (ATTR_FLAG_POLICY_SET | ATTR_FLAG_SCHED_SET))
+ return self->schedparam.sched_priority;
+
+ int result = 0;
+
+ /* See CREATE THREAD NOTES in nptl/pthread_create.c. */
+ lll_lock (self->lock, LLL_PRIVATE);
+
+ if ((self->flags & ATTR_FLAG_SCHED_SET) == 0)
+ {
+ if (__sched_getparam (self->tid, &self->schedparam) != 0)
+ result = -1;
+ else
+ self->flags |= ATTR_FLAG_SCHED_SET;
+ }
+
+ if ((self->flags & ATTR_FLAG_POLICY_SET) == 0)
+ {
+ self->schedpolicy = __sched_getscheduler (self->tid);
+ if (self->schedpolicy == -1)
+ result = -1;
+ else
+ self->flags |= ATTR_FLAG_POLICY_SET;
+ }
+
+ if (result != -1)
+ result = self->schedparam.sched_priority;
+
+ lll_unlock (self->lock, LLL_PRIVATE);
+
+ return result;
+}
diff --git a/nptl_2_17/vars_2_17.c b/nptl_2_17/vars_2_17.c
new file mode 100644
index 00000000..ae60c0f8
--- /dev/null
+++ b/nptl_2_17/vars_2_17.c
@@ -0,0 +1,43 @@
+/* Copyright (C) 2004-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "pthreadP_2_17.h"
+#include <stdlib.h>
+#include <tls.h>
+#include <unistd.h>
+
+/* Default thread attributes for the case when the user does not
+ provide any. */
+struct pthread_attr __default_pthread_attr attribute_hidden;
+
+/* Mutex protecting __default_pthread_attr. */
+int __default_pthread_attr_lock = LLL_LOCK_INITIALIZER;
+
+/* Flag whether the machine is SMP or not. */
+int __is_smp attribute_hidden;
+
+#ifndef TLS_MULTIPLE_THREADS_IN_TCB
+/* Variable set to a nonzero value either if more than one thread runs or ran,
+ or if a single-threaded process is trying to cancel itself. See
+ nptl/descr.h for more context on the single-threaded process case. */
+int __pthread_multiple_threads attribute_hidden;
+#endif
+
+/* Table of the key information. */
+struct pthread_key_struct __pthread_keys[PTHREAD_KEYS_MAX]
+ __attribute__ ((nocommon));
+hidden_data_def (__pthread_keys)
--
2.30.0