Subject: [PATCH] nptl: Add pthread_thread_number_np function
To: libc-alpha@sourceware.org

The implementation is actually in libc.so.  With a full implementation
of pthread_self in libc.so, pthread_thread_number_np is completely
usable without libpthread.

2017-12-22  Florian Weimer  <fweimer@redhat.com>


	nptl: Add pthread_thread_number_np function.
	* csu/libc-tls.c (__libc_setup_tls): Call __dl_inittcb.
	* elf/Makefile (dl-routines): Add dl-inittcb.
	* elf/dl-inittcb.c: New file.
	* elf/rtld.c (init_tls): Call __dl_inittcb.
	* manual/threads.texi (Non-POSIX Extensions): Reference Non-POSIX
	Extensions.
	(Non-POSIX Extensions): New node.
	* nptl/Makefile (routines): Add thread_number.
	(tests): Add tst-thread_number-single, tst-thread_number-multi,
	tst-thread_number-single-static, tst-thread_number-multi-static.
	(tests-nolibpthread): Add tst-thread_number-single,
	tst-thread_number-single-static.
	(tests-static): Add tst-thread_number-single-static,
	tst-thread_number-multi-static.
	* nptl/Versions (GLIBC_2.27): Export pthread_thread_number_np.
	* nptl/allocatestack.c (allocate_stack): Increment
	global_thread_number under__default_pthread_attr_lock and use its
	value to set the new thread number.
	* nptl/descr.h (struct pthread): Add number member.
	* nptl/thread_number.c: New file.
	* nptl/tst-thread_number-multi.c: Likewise.
	* nptl/tst-thread_number-single.c: Likewise.
	* nptl/tst-thread_number-multi-static.c: Likewise.
	* nptl/tst-thread_number-single-static.c: Likewise.
	* sysdeps/nptl/bits/pthread-common.h: New file.
	* sysdeps/nptl/Makefile (sysdep_headers): Install it.
	* sysdeps/nptl/pthread.h: Include <bits/pthread-common.h>.
	* sysdeps/unix/sysv/linux/hppa/pthread.h: Likewise.
	* sysdeps/unix/sysv/linux/libc**.abilist: Update.

diff --git a/NEWS b/NEWS
index 2a1a4bfd85..3fd41915ed 100644
--- a/NEWS
+++ b/NEWS
@@ -55,7 +55,8 @@ Major new features:
   _Float32x types, as defined by ISO/IEC TS 18661-3:2015.  These are
   corresponding interfaces to those supported for _Float128.
 
-* glibc now implements the memfd_create and mlock2 functions on Linux.
+* glibc now implements the memfd_create, mlock2, and
+  pthread_thread_number_np functions on Linux.
 
 * Support for memory protection keys was added.  The <sys/mman.h> header now
   declares the functions pkey_alloc, pkey_free, pkey_mprotect, pkey_set,
diff --git a/csu/libc-tls.c b/csu/libc-tls.c
index 1f8ddaf543..dceb01e533 100644
--- a/csu/libc-tls.c
+++ b/csu/libc-tls.c
@@ -195,6 +195,7 @@ __libc_setup_tls (void)
 #endif
   if (__builtin_expect (lossage != NULL, 0))
     _startup_fatal (lossage);
+  __dl_inittcb ();
 
   /* Update the executable's link map with enough information to make
      the TLS routines happy.  */
diff --git a/elf/Makefile b/elf/Makefile
index a987614b6f..bf2928e958 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -31,7 +31,7 @@ routines	= $(all-dl-routines) dl-support dl-iteratephdr \
 # profiled libraries.
 dl-routines	= $(addprefix dl-,load lookup object reloc deps hwcaps \
 				  runtime init fini debug misc \
-				  version profile tls origin scope \
+				  version profile tls inittcb origin scope \
 				  execstack caller open close trampoline \
 				  exception sort-maps)
 ifeq (yes,$(use-ldconfig))
diff --git a/elf/dl-inittcb.c b/elf/dl-inittcb.c
new file mode 100644
index 0000000000..5a70e9775d
--- /dev/null
+++ b/elf/dl-inittcb.c
@@ -0,0 +1,22 @@
+/* Initialize TCB contents.  Generic version.
+   Copyright (C) 2017 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/>.  */
+
+void
+__dl_inittcb (void)
+{
+}
diff --git a/elf/rtld.c b/elf/rtld.c
index c01b7e3641..6eb51f689b 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -740,6 +740,7 @@ cannot allocate TLS data structures for initial thread\n");
   const char *lossage = TLS_INIT_TP (tcbp);
   if (__glibc_unlikely (lossage != NULL))
     _dl_fatal_printf ("cannot set up thread-local storage: %s\n", lossage);
+  __dl_inittcb ();
   tls_init_tp_called = true;
 
   return tcbp;
diff --git a/manual/threads.texi b/manual/threads.texi
index 769d974d50..6aa08f398a 100644
--- a/manual/threads.texi
+++ b/manual/threads.texi
@@ -80,6 +80,7 @@ the standard.
 @menu
 * Default Thread Attributes::             Setting default attributes for
 					  threads in a process.
+* Identifying Threads::                   Unique identifiers for threads.
 @end menu
 
 @node Default Thread Attributes
@@ -124,6 +125,30 @@ The system does not have sufficient memory.
 @end table
 @end deftypefun
 
+@node Identifying Threads
+@subsection Unique identifiers for threads
+
+@Theglibc{} provides a non-standard function to obtain a unique thread
+identifier.
+
+@deftypefun uint64_t pthread_thread_number_np (pthread_t @var{thread})
+@standards{GNU, pthread.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+
+This function returns a number that uniquely identifies @var{thread}
+among all past, current, and future running threads.  This number does
+not change during the life-time of the thread.  Once returned by this
+function, a number will not be reused after the thread terminates.
+
+The returned number is only unique with regards to the current process.
+It may be shared by subprocesses and other processes in the system.
+
+The initial (main) thread has number 1.  Thread numbers are not
+necessarily assigned in a consecutive fashion.  They bear no
+relationship to POSIX thread IDs (@code{pthread_t} values), process IDs
+or thread IDs assigned by the kernel.
+@end deftypefun
+
 @c FIXME these are undocumented:
 @c pthread_atfork
 @c pthread_attr_destroy
diff --git a/nptl/Makefile b/nptl/Makefile
index cf2ba8131b..6f20d4e07d 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -31,7 +31,7 @@ install-lib-ldscripts := libpthread.so
 
 routines = alloca_cutoff forward libc-lowlevellock libc-cancellation \
 	   libc-cleanup libc_pthread_init libc_multiple_threads \
-	   register-atfork unregister-atfork pthread_self
+	   register-atfork unregister-atfork pthread_self thread_number
 shared-only-routines = forward
 
 # We need to provide certain routines for compatibility with existing
@@ -304,7 +304,8 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
 			    c89 gnu89 c99 gnu99 c11 gnu11) \
 	tst-bad-schedattr \
 	tst-thread_local1 tst-mutex-errorcheck tst-robust10 \
-	tst-robust-fork tst-create-detached tst-memstream
+	tst-robust-fork tst-create-detached tst-memstream \
+	tst-thread_number-single tst-thread_number-multi \
 
 tests-internal := tst-rwlock19 tst-rwlock20 \
 		  tst-sem11 tst-sem12 tst-sem13 \
@@ -320,7 +321,9 @@ test-srcs = tst-oddstacklimit
 test-xfail-tst-once5 = yes
 
 # Files which must not be linked with libpthread.
-tests-nolibpthread = tst-unload
+tests-nolibpthread = tst-unload \
+  tst-thread_number-single \
+  tst-thread_number-single-static \
 
 gen-as-const-headers = pthread-errnos.sym \
 		       unwindbuf.sym \
@@ -435,9 +438,13 @@ link-libc-static := $(common-objpfx)libc.a $(static-gnulib) \
 tests-static += tst-locale1 tst-locale2 tst-stackguard1-static \
 		tst-cancel21-static tst-cancel24-static tst-cond8-static \
 		tst-mutex8-static tst-mutexpi8-static tst-sem11-static \
-		tst-sem12-static
+		tst-sem12-static tst-thread_number-single-static \
+		tst-thread_number-multi-static \
+
 tests += tst-cancel21-static tst-cancel24-static \
-	 tst-cond8-static
+  tst-cond8-static tst-thread_number-single-static \
+  tst-thread_number-multi-static \
+
 tests-internal += tst-sem11-static tst-sem12-static tst-stackguard1-static
 xtests-static += tst-setuid1-static
 
diff --git a/nptl/Versions b/nptl/Versions
index 0ae5def464..a7204912a8 100644
--- a/nptl/Versions
+++ b/nptl/Versions
@@ -28,6 +28,9 @@ libc {
     pthread_cond_wait; pthread_cond_signal;
     pthread_cond_broadcast; pthread_cond_timedwait;
   }
+  GLIBC_2.27 {
+    pthread_thread_number_np;
+  }
   GLIBC_PRIVATE {
     __libc_alloca_cutoff;
     # Internal libc interface to libpthread
diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
index 1cc7893195..454df7740b 100644
--- a/nptl/allocatestack.c
+++ b/nptl/allocatestack.c
@@ -413,16 +413,28 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
   assert (powerof2 (pagesize_m1 + 1));
   assert (TCB_ALIGNMENT >= STACK_ALIGN);
 
-  /* Get the stack size from the attribute if it is set.  Otherwise we
-     use the default we determined at start time.  */
-  if (attr->stacksize != 0)
-    size = attr->stacksize;
-  else
-    {
-      lll_lock (__default_pthread_attr_lock, LLL_PRIVATE);
+  uint64_t thread_number;
+  lll_lock (__default_pthread_attr_lock, LLL_PRIVATE);
+  {
+    /* Number 1 is reserved for the initial thread.  Reuse
+       __default_pthread_attr_lock to avoid concurrent updates of this
+       counter.  */
+    static uint64_t global_thread_number = 1;
+    thread_number = ++global_thread_number;
+
+    /* Check for counter wrap-around.  This should never happen
+       because 2**64 is such a large value.  */
+    if (thread_number == 0)
+      __libc_fatal ("Fatal glibc error: maximum number of threads exceeded\n");
+
+    /* Get the stack size from the attribute if it is set.  Otherwise
+       we use the default we determined at start time.  */
+    if (attr->stacksize != 0)
+      size = attr->stacksize;
+    else
       size = __default_pthread_attr.stacksize;
-      lll_unlock (__default_pthread_attr_lock, LLL_PRIVATE);
-    }
+  }
+  lll_unlock (__default_pthread_attr_lock, LLL_PRIVATE);
 
   /* Get memory for the stack.  */
   if (__glibc_unlikely (attr->flags & ATTR_FLAG_STACKADDR))
@@ -758,6 +770,8 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
 #endif
   pd->robust_head.list = &pd->robust_head;
 
+  pd->number = thread_number;
+
   /* We place the thread descriptor at the end of the stack.  */
   *pdp = pd;
 
diff --git a/nptl/descr.h b/nptl/descr.h
index fdeb397eab..7c6e34a636 100644
--- a/nptl/descr.h
+++ b/nptl/descr.h
@@ -398,6 +398,9 @@ struct pthread
   /* Resolver state.  */
   struct __res_state res;
 
+  /* Unique number assigned to this thread.  */
+  uint64_t number;
+
   /* This member must be last.  */
   char end_padding[];
 
diff --git a/nptl/thread_number.c b/nptl/thread_number.c
new file mode 100644
index 0000000000..30b7f438c3
--- /dev/null
+++ b/nptl/thread_number.c
@@ -0,0 +1,36 @@
+/* Unique numbers for threads.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "pthreadP.h"
+
+/* This function should ideally return an integer wider than uint64_t,
+   so that the thread number can never-ever overflow.  We may have to
+   switch to a 128-bit return value for new architectures
+   (particularly if those provide atomic operations on 128-bit
+   integers).  But with current architectures, the baked-in limit of
+   2**64 threads ever created by a process is not a problem because
+   architectural constraints result in a thread creation rate far
+   below one billion threads per second, and even at that rate, a
+   64-bit counter lasts for hundreds of years.  */
+
+__uint64_t
+pthread_thread_number_np (pthread_t threadid)
+{
+  struct pthread *pd = (struct pthread *) threadid;
+  return pd->number;
+}
diff --git a/nptl/tst-thread_number-multi-static.c b/nptl/tst-thread_number-multi-static.c
new file mode 100644
index 0000000000..658928cfd5
--- /dev/null
+++ b/nptl/tst-thread_number-multi-static.c
@@ -0,0 +1,19 @@
+/* Test unique numbers for threads, static multi-threaded version.
+   Copyright (C) 2017 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 "tst-thread_number-multi.c"
diff --git a/nptl/tst-thread_number-multi.c b/nptl/tst-thread_number-multi.c
new file mode 100644
index 0000000000..881fe6b097
--- /dev/null
+++ b/nptl/tst-thread_number-multi.c
@@ -0,0 +1,101 @@
+/* Test unique numbers for threads, non-static multi-threaded version.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <support/check.h>
+#include <support/namespace.h>
+#include <support/xthread.h>
+
+/* Used to check that the main thread still has thread number 1 in a
+   subprocess.  */
+static void
+subprocess (void *closure)
+{
+  TEST_COMPARE (pthread_thread_number_np (pthread_self ()), 1U);
+}
+
+static void *
+subthread (void *closure)
+{
+  if (closure != NULL)
+    xpthread_barrier_wait (closure);
+  return NULL;
+}
+
+static int
+compare (const void *pleft, const void *pright)
+{
+  uint64_t left = *(const uint64_t *)pleft;
+  uint64_t right = *(const uint64_t *)pright;
+  if (left < right)
+    return -1;
+  if (left > right)
+    return 1;
+  return 0;
+}
+
+static int
+do_test (void)
+{
+  TEST_COMPARE (pthread_thread_number_np (pthread_self ()), 1U);
+  support_isolate_in_subprocess (subprocess, NULL);
+
+  /* Create thread_count threads, half of which are joined
+     immediately, have of which stay around.  */
+  enum { thread_count = 10 };
+  pthread_barrier_t barrier;
+  xpthread_barrier_init (&barrier, NULL, thread_count / 2 + 1);
+  uint64_t ids[thread_count];
+  pthread_t threads[thread_count]; /* Only even-numbered entries are valid.  */
+  for (int i = 0; i < thread_count; ++i)
+    {
+      bool stay_around = (i % 2) == 0;
+      threads[i] = xpthread_create (NULL, subthread,
+                                    stay_around ? &barrier : NULL);
+      ids[i] = pthread_thread_number_np (threads[i]);
+      TEST_VERIFY (ids[i] != 1);
+      if (!stay_around)
+        xpthread_join (threads[i]);
+    }
+
+  /* Check that the IDs are all distinct.  */
+  qsort (ids, thread_count, sizeof (ids[0]), compare);
+  for (int i = 1; i < thread_count; ++i)
+    TEST_VERIFY (ids[i - 1] < ids[i]);
+
+  /* Main thread ID should remain at 1.  */
+  TEST_COMPARE (pthread_thread_number_np (pthread_self ()), 1U);
+  support_isolate_in_subprocess (subprocess, NULL);
+
+  /* Clean up.  */
+  xpthread_barrier_wait (&barrier);
+  for (int i = 0; i < thread_count; ++i)
+    if ((i % 2) == 0)
+      xpthread_join (threads[i]);
+
+  /* Main thread ID should still remain at 1.  */
+  TEST_COMPARE (pthread_thread_number_np (pthread_self ()), 1U);
+  support_isolate_in_subprocess (subprocess, NULL);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/nptl/tst-thread_number-single-static.c b/nptl/tst-thread_number-single-static.c
new file mode 100644
index 0000000000..5c21063c36
--- /dev/null
+++ b/nptl/tst-thread_number-single-static.c
@@ -0,0 +1,19 @@
+/* Test unique numbers for threads, static single-threaded version.
+   Copyright (C) 2017 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 "tst-thread_number-single.c"
diff --git a/nptl/tst-thread_number-single.c b/nptl/tst-thread_number-single.c
new file mode 100644
index 0000000000..7d3e7ee1dd
--- /dev/null
+++ b/nptl/tst-thread_number-single.c
@@ -0,0 +1,40 @@
+/* Test unique numbers for threads, non-static single-threaded version.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <support/check.h>
+#include <support/namespace.h>
+
+/* Used to check that the main thread still has thread number 1 in a
+   subprocess.  */
+static void
+subprocess (void *closure)
+{
+  TEST_COMPARE (pthread_thread_number_np (pthread_self ()), 1U);
+}
+
+static int
+do_test (void)
+{
+  TEST_COMPARE (pthread_thread_number_np (pthread_self ()), 1U);
+  support_isolate_in_subprocess (subprocess, NULL);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 658a4f20b4..b92e48f1bb 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1071,6 +1071,10 @@ extern struct link_map * _dl_get_dl_main_map (void)
 void __pthread_initialize_minimal (void) weak_function;
 #endif
 
+/* Initialize the already-existing TCB for the main thread.  Called
+   during dynamic linker startup or from __libc_setup_tls.  */
+void __dl_inittcb (void) attribute_hidden;
+
 /* Allocate memory for static TLS block (unless MEM is nonzero) and dtv.  */
 extern void *_dl_allocate_tls (void *mem);
 rtld_hidden_proto (_dl_allocate_tls)
diff --git a/sysdeps/nptl/Makefile b/sysdeps/nptl/Makefile
index 4f4f4ffe69..2b9bc549b5 100644
--- a/sysdeps/nptl/Makefile
+++ b/sysdeps/nptl/Makefile
@@ -17,6 +17,7 @@
 # <http://www.gnu.org/licenses/>.
 
 ifeq ($(subdir),nptl)
+sysdep_headers += bits/pthread-common.h
 libpthread-sysdep_routines += errno-loc
 endif
 
diff --git a/sysdeps/nptl/bits/pthread-common.h b/sysdeps/nptl/bits/pthread-common.h
new file mode 100644
index 0000000000..2e0fc899c3
--- /dev/null
+++ b/sysdeps/nptl/bits/pthread-common.h
@@ -0,0 +1,29 @@
+/* pthread function declarations common to all architectures.
+   Copyright (C) 2017 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
+# error "Never include <bits/pthread-common.h> directly; use <pthread.h> instead".
+#endif
+
+__BEGIN_DECLS
+
+/* Return a number uniquely identifying THREAD, even after its
+   termination.  */
+__uint64_t pthread_thread_number_np (pthread_t __thread_id) __THROW;
+
+__END_DECLS
diff --git a/sysdeps/nptl/dl-inittcb.c b/sysdeps/nptl/dl-inittcb.c
new file mode 100644
index 0000000000..c25424dfa6
--- /dev/null
+++ b/sysdeps/nptl/dl-inittcb.c
@@ -0,0 +1,27 @@
+/* Initialize TCB contents.  NPTL version.
+   Copyright (C) 2017 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 <ldsodefs.h>
+#include <tls.h>
+
+void
+__dl_inittcb (void)
+{
+  /* The main thread has number 1.  */
+  THREAD_SELF->number = 1;
+}
diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h
index 787ac6e4cd..3e3ba5a238 100644
--- a/sysdeps/nptl/pthread.h
+++ b/sysdeps/nptl/pthread.h
@@ -1156,4 +1156,7 @@ __NTH (pthread_equal (pthread_t __thread1, pthread_t __thread2))
 
 __END_DECLS
 
+/* Common declarations for all architectures.  */
+#include <bits/pthread-common.h>
+
 #endif	/* pthread.h */
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 90c9bc84e1..faa7171f41 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2114,6 +2114,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf128 F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index fd2d81fb68..e7080beaa4 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2025,6 +2025,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf128 F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index 044ec102c2..a87740050c 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -115,6 +115,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
 GLIBC_2.27 strfromf64 F
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 2360130abe..9f28dcf4d1 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -1879,6 +1879,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
 GLIBC_2.27 strfromf64 F
diff --git a/sysdeps/unix/sysv/linux/hppa/pthread.h b/sysdeps/unix/sysv/linux/hppa/pthread.h
index 3d69ddcd00..c28ce058c3 100644
--- a/sysdeps/unix/sysv/linux/hppa/pthread.h
+++ b/sysdeps/unix/sysv/linux/hppa/pthread.h
@@ -1132,4 +1132,7 @@ __NTH (pthread_equal (pthread_t __thread1, pthread_t __thread2))
 
 __END_DECLS
 
+/* Common declarations for all architectures.  */
+#include <bits/pthread-common.h>
+
 #endif	/* pthread.h */
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 39c993fd79..f14b9cf624 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2044,6 +2044,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
 GLIBC_2.27 strfromf64 F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index 68496aa6ac..9aaa06f278 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1908,6 +1908,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
 GLIBC_2.27 strfromf64 F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index b676025261..cb06ac5add 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -116,6 +116,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
 GLIBC_2.27 strfromf64 F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index cdd1df55d0..00ca22237c 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -1993,6 +1993,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
 GLIBC_2.27 strfromf64 F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index e4265fd74d..7b2d7c183b 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2114,6 +2114,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
 GLIBC_2.27 strfromf64 F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 3a7e0b4c29..e9ab73a95d 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1968,6 +1968,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
 GLIBC_2.27 strfromf64 F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 5e805924fa..2a817eda1f 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1966,6 +1966,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
 GLIBC_2.27 strfromf64 F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 1973fac36d..486aa10a92 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1964,6 +1964,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf128 F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index 5e18ab83b4..93fe34b413 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1959,6 +1959,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf128 F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index cc5885ab9b..5ff22dd9d2 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2155,6 +2155,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
 GLIBC_2.27 strfromf64 F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 676aa50c81..8df287ea1e 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -1997,6 +1997,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
 GLIBC_2.27 strfromf64 F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index 2016c7c1e5..8c86997b4f 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -2002,6 +2002,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
 GLIBC_2.27 strfromf64 F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
index 3d19e38dbd..835e6ae0dd 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2209,6 +2209,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
 GLIBC_2.27 strfromf64 F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index c57ab21b82..8f23491a62 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -116,6 +116,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
 GLIBC_2.27 strfromf64 F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 25903720e3..605bc2220d 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -1997,6 +1997,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf128 F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index 5d6800c236..787bbf83b6 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1898,6 +1898,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf128 F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index c04872ca7f..20ae3fa1aa 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1883,6 +1883,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
 GLIBC_2.27 strfromf64 F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 85cbe308d6..d6e37b80eb 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -1990,6 +1990,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf128 F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index f7a1ab8edb..0572308fb1 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1927,6 +1927,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf128 F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx32/libc.abilist
index ab56ecee44..5e858e2226 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx32/libc.abilist
@@ -2121,6 +2121,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
 GLIBC_2.27 strfromf64 F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx64/libc.abilist
index f2518c08ff..f10ad6c931 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx64/libc.abilist
@@ -2121,6 +2121,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
 GLIBC_2.27 strfromf64 F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index 2a3cc40674..ea6653b142 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1885,6 +1885,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
 GLIBC_2.27 strfromf64 F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 8bc16b9004..8e22fcc12e 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2128,6 +2128,7 @@ GLIBC_2.27 pkey_free F
 GLIBC_2.27 pkey_get F
 GLIBC_2.27 pkey_mprotect F
 GLIBC_2.27 pkey_set F
+GLIBC_2.27 pthread_thread_number_np F
 GLIBC_2.27 strfromf32 F
 GLIBC_2.27 strfromf32x F
 GLIBC_2.27 strfromf64 F
