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

