public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] nptl: Add pthread_thread_number_np function
@ 2017-12-14 18:56 Florian Weimer
  2017-12-14 20:24 ` Florian Weimer
                   ` (3 more replies)
  0 siblings, 4 replies; 28+ messages in thread
From: Florian Weimer @ 2017-12-14 18:56 UTC (permalink / raw)
  To: libc-alpha

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-14  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/pthread.h (pthread_thread_number_np): Declare.
	* sysdeps/unix/sysv/linux/libc**.abilist: Update.

diff --git a/csu/libc-tls.c b/csu/libc-tls.c
index 00138eb43a..af81cba12c 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 8563555079..66ce2953a4 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -30,7 +30,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 cfd3729b8e..214e2312fa 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..6c62ff3da0 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,29 @@ 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 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 ae388d1112..087fb6a8b5 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -30,7 +30,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
@@ -302,7 +302,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 \
@@ -318,7 +319,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 \
@@ -433,9 +436,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..8b6c839408 100644
--- a/nptl/Versions
+++ b/nptl/Versions
@@ -28,6 +28,9 @@ libc {
     pthread_cond_wait; pthread_cond_signal;
     pthread_cond_broadcast; pthread_cond_timedwait;
   }
+  GLBIC_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..0e1cf3939e 100644
--- a/nptl/allocatestack.c
+++ b/nptl/allocatestack.c
@@ -413,16 +413,21 @@ 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.  */
+    static uint64_t global_thread_number = 1;
+    thread_number = ++global_thread_number;
+
+    /* 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 +763,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 c83b17b674..49e266139e 100644
--- a/nptl/descr.h
+++ b/nptl/descr.h
@@ -395,6 +395,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..a9fdaa508b
--- /dev/null
+++ b/nptl/thread_number.c
@@ -0,0 +1,26 @@
+/* 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"
+
+__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..e26f19e44a
--- /dev/null
+++ b/nptl/tst-thread_number-multi.c
@@ -0,0 +1,99 @@
+/* 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>
+
+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 arround.  */
+  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..43497205c7
--- /dev/null
+++ b/nptl/tst-thread_number-single.c
@@ -0,0 +1,38 @@
+/* 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>
+
+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 7a65dc641c..99f2e58875 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1056,6 +1056,10 @@ void __libc_setup_tls (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/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 2b2b386ab3..e0714ed951 100644
--- a/sysdeps/nptl/pthread.h
+++ b/sysdeps/nptl/pthread.h
@@ -1148,6 +1148,10 @@ extern int pthread_atfork (void (*__prepare) (void),
 			   void (*__child) (void)) __THROW;
 
 
+/* Return a number uniquely identifying THREAD, even after its
+   termination.  */
+__uint64_t pthread_thread_number_np (pthread_t __thread_id) __THROW;
+
 #ifdef __USE_EXTERN_INLINES
 /* Optimizations.  */
 __extern_inline int
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index ec0ead15dd..e206f77540 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -1,3 +1,5 @@
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.17 GLIBC_2.17 A
 GLIBC_2.17 _Exit F
 GLIBC_2.17 _IO_2_1_stderr_ D 0xe0
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 5355769974..92429a8d78 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
 GCC_3.0 __deregister_frame_info_bases F
 GCC_3.0 __register_frame_info_bases F
 GCC_3.0 __register_frame_info_table_bases F
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.0 GLIBC_2.0 A
 GLIBC_2.0 _IO_adjust_column F
 GLIBC_2.0 _IO_default_doallocate F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index 9bafe71b51..bcd54ecdf5 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -1,3 +1,5 @@
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.10 GLIBC_2.10 A
 GLIBC_2.10 __cxa_at_quick_exit F
 GLIBC_2.10 __posix_getopt F
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 90aa8d034f..84445a123e 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -1,3 +1,5 @@
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.10 GLIBC_2.10 A
 GLIBC_2.10 __cxa_at_quick_exit F
 GLIBC_2.10 __posix_getopt F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 4d44c30c64..caa8dff010 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
 GCC_3.0 __deregister_frame_info_bases F
 GCC_3.0 __register_frame_info_bases F
 GCC_3.0 __register_frame_info_table_bases F
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.0 GLIBC_2.0 A
 GLIBC_2.0 _IO_adjust_column F
 GLIBC_2.0 _IO_default_doallocate F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index 112fc57634..02301da334 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1,3 +1,5 @@
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.10 GLIBC_2.10 A
 GLIBC_2.10 __cxa_at_quick_exit F
 GLIBC_2.10 __posix_getopt F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 2e8b6a4586..a3fbcb831f 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -1,3 +1,5 @@
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.10 GLIBC_2.10 A
 GLIBC_2.10 __cxa_at_quick_exit F
 GLIBC_2.10 __posix_getopt F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 3c33400f67..203a63aa27 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
 GCC_3.0 __deregister_frame_info_bases F
 GCC_3.0 __register_frame_info_bases F
 GCC_3.0 __register_frame_info_table_bases F
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.0 GLIBC_2.0 A
 GLIBC_2.0 _IO_adjust_column F
 GLIBC_2.0 _IO_default_doallocate F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index e1b1a579d2..a3be97ef65 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -1,3 +1,5 @@
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.18 GLIBC_2.18 A
 GLIBC_2.18 _Exit F
 GLIBC_2.18 _IO_2_1_stderr_ D 0x98
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index c1550323f3..94de2ef489 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
 GCC_3.0 __deregister_frame_info_bases F
 GCC_3.0 __register_frame_info_bases F
 GCC_3.0 __register_frame_info_table_bases F
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.0 GLIBC_2.0 A
 GLIBC_2.0 _IO_adjust_column F
 GLIBC_2.0 _IO_default_doallocate F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 3b3a172e4f..878bee4bb5 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
 GCC_3.0 __deregister_frame_info_bases F
 GCC_3.0 __register_frame_info_bases F
 GCC_3.0 __register_frame_info_table_bases F
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.0 GLIBC_2.0 A
 GLIBC_2.0 _IO_adjust_column F
 GLIBC_2.0 _IO_default_doallocate F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 101ca7a241..94706fccb4 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
 GCC_3.0 __deregister_frame_info_bases F
 GCC_3.0 __register_frame_info_bases F
 GCC_3.0 __register_frame_info_table_bases F
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.0 GLIBC_2.0 A
 GLIBC_2.0 _IO_adjust_column F
 GLIBC_2.0 _IO_default_doallocate F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index 2d129f7170..adc3de5c88 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
 GCC_3.0 __deregister_frame_info_bases F
 GCC_3.0 __register_frame_info_bases F
 GCC_3.0 __register_frame_info_table_bases F
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.0 GLIBC_2.0 A
 GLIBC_2.0 _IO_adjust_column F
 GLIBC_2.0 _IO_default_doallocate F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 8bc350aff8..f6198b3dbb 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -1,3 +1,5 @@
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.21 GLIBC_2.21 A
 GLIBC_2.21 _Exit F
 GLIBC_2.21 _IO_2_1_stderr_ D 0x98
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 127c426e1c..363a3a2e10 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
 GCC_3.0 __deregister_frame_info_bases F
 GCC_3.0 __register_frame_info_bases F
 GCC_3.0 __register_frame_info_table_bases F
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.0 GLIBC_2.0 A
 GLIBC_2.0 _IO_adjust_column F
 GLIBC_2.0 _IO_default_doallocate F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index a9411318e2..dfa0463282 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
 GCC_3.0 __deregister_frame_info_bases F
 GCC_3.0 __register_frame_info_bases F
 GCC_3.0 __register_frame_info_table_bases F
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.0 GLIBC_2.0 A
 GLIBC_2.0 _IO_adjust_column F
 GLIBC_2.0 _IO_default_doallocate F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
index d7bf5db601..37a34eb833 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -1,3 +1,5 @@
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.17 GLIBC_2.17 A
 GLIBC_2.17 _Exit F
 GLIBC_2.17 _IO_2_1_stderr_ D 0xe0
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index a3415a72ac..a0dbaf366a 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -1,3 +1,5 @@
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.10 GLIBC_2.10 A
 GLIBC_2.10 __cxa_at_quick_exit F
 GLIBC_2.10 __posix_getopt F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 414338f9a2..a30b304817 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
 GCC_3.0 __deregister_frame_info_bases F
 GCC_3.0 __register_frame_info_bases F
 GCC_3.0 __register_frame_info_table_bases F
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.0 GLIBC_2.0 A
 GLIBC_2.0 _IO_adjust_column F
 GLIBC_2.0 _IO_default_doallocate F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index f0f7a69b64..a759aa9cf5 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
 GCC_3.0 __deregister_frame_info_bases F
 GCC_3.0 __register_frame_info_bases F
 GCC_3.0 __register_frame_info_table_bases F
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.10 GLIBC_2.10 A
 GLIBC_2.10 __cxa_at_quick_exit F
 GLIBC_2.10 __posix_getopt F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index 9f95aba898..133e0a55ef 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
 GCC_3.0 __deregister_frame_info_bases F
 GCC_3.0 __register_frame_info_bases F
 GCC_3.0 __register_frame_info_table_bases F
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.10 GLIBC_2.10 A
 GLIBC_2.10 __cxa_at_quick_exit F
 GLIBC_2.10 __posix_getopt F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 83fbdf2d7e..e525ed69d6 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
 GCC_3.0 __deregister_frame_info_bases F
 GCC_3.0 __register_frame_info_bases F
 GCC_3.0 __register_frame_info_table_bases F
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.0 .div F
 GLIBC_2.0 .mul F
 GLIBC_2.0 .rem F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index ee84ad10bc..d4fb34eceb 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
 GCC_3.0 __deregister_frame_info_bases F
 GCC_3.0 __register_frame_info_bases F
 GCC_3.0 __register_frame_info_table_bases F
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.10 GLIBC_2.10 A
 GLIBC_2.10 __cxa_at_quick_exit F
 GLIBC_2.10 __posix_getopt F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
index dcbfbc05ac..f598149374 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
@@ -1,3 +1,5 @@
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.12 GLIBC_2.12 A
 GLIBC_2.12 _Exit F
 GLIBC_2.12 _IO_2_1_stderr_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
index 53dc99c45a..cb0054f532 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
@@ -1,3 +1,5 @@
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.12 GLIBC_2.12 A
 GLIBC_2.12 _Exit F
 GLIBC_2.12 _IO_2_1_stderr_ D 0xe0
diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
index dcbfbc05ac..f598149374 100644
--- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
@@ -1,3 +1,5 @@
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.12 GLIBC_2.12 A
 GLIBC_2.12 _Exit F
 GLIBC_2.12 _IO_2_1_stderr_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index ae4dcaa47e..70a15fa003 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1,3 +1,5 @@
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.10 GLIBC_2.10 A
 GLIBC_2.10 __cxa_at_quick_exit F
 GLIBC_2.10 __posix_getopt F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 0dbda14796..afbdec65d5 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -1,3 +1,5 @@
+GLBIC_2.27 GLBIC_2.27 A
+GLBIC_2.27 pthread_thread_number_np F
 GLIBC_2.16 GLIBC_2.16 A
 GLIBC_2.16 _Exit F
 GLIBC_2.16 _IO_2_1_stderr_ D 0xa0

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2017-12-14 18:56 [PATCH] nptl: Add pthread_thread_number_np function Florian Weimer
@ 2017-12-14 20:24 ` Florian Weimer
  2017-12-14 23:34 ` Nix
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 28+ messages in thread
From: Florian Weimer @ 2017-12-14 20:24 UTC (permalink / raw)
  To: libc-alpha

On 12/14/2017 07:56 PM, Florian Weimer wrote:
> 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.

And once again, I forgot the NEWS entry.

I should say that this is something completely different from gettid, 
and by itself usable for logging, certain concurrency-related 
algorithms, and writing DRBGs (where the current thread's number can be 
used to ensure that different threads get different bit sequences).

Thanks,
Florian

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2017-12-14 18:56 [PATCH] nptl: Add pthread_thread_number_np function Florian Weimer
  2017-12-14 20:24 ` Florian Weimer
@ 2017-12-14 23:34 ` Nix
  2017-12-15  6:41   ` Florian Weimer
  2017-12-15  0:29 ` Andrew Pinski
  2017-12-15  4:08 ` Carlos O'Donell
  3 siblings, 1 reply; 28+ messages in thread
From: Nix @ 2017-12-14 23:34 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha

On 14 Dec 2017, Florian Weimer uttered the following:
> diff --git a/nptl/Versions b/nptl/Versions
> index 0ae5def464..8b6c839408 100644
> --- a/nptl/Versions
> +++ b/nptl/Versions
> @@ -28,6 +28,9 @@ libc {
>      pthread_cond_wait; pthread_cond_signal;
>      pthread_cond_broadcast; pthread_cond_timedwait;
>    }
> +  GLBIC_2.27 {
> +    pthread_thread_number_np;
> +  }
>    GLIBC_PRIVATE {
>      __libc_alloca_cutoff;
>      # Internal libc interface to libpthread

GLBIC is a definite typo (repeated, of course, in all the abilist
files).

-- 
NULL && (void)

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2017-12-14 18:56 [PATCH] nptl: Add pthread_thread_number_np function Florian Weimer
  2017-12-14 20:24 ` Florian Weimer
  2017-12-14 23:34 ` Nix
@ 2017-12-15  0:29 ` Andrew Pinski
  2017-12-15  7:47   ` Florian Weimer
  2017-12-15  7:54   ` Andrew Pinski
  2017-12-15  4:08 ` Carlos O'Donell
  3 siblings, 2 replies; 28+ messages in thread
From: Andrew Pinski @ 2017-12-15  0:29 UTC (permalink / raw)
  To: Florian Weimer; +Cc: GNU C Library

On Thu, Dec 14, 2017 at 10:56 AM, Florian Weimer <fweimer@redhat.com> wrote:
> 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-14  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/pthread.h (pthread_thread_number_np): Declare.
>         * sysdeps/unix/sysv/linux/libc**.abilist: Update.
>
> diff --git a/csu/libc-tls.c b/csu/libc-tls.c
> index 00138eb43a..af81cba12c 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 8563555079..66ce2953a4 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -30,7 +30,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 cfd3729b8e..214e2312fa 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..6c62ff3da0 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,29 @@ 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 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 ae388d1112..087fb6a8b5 100644
> --- a/nptl/Makefile
> +++ b/nptl/Makefile
> @@ -30,7 +30,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
> @@ -302,7 +302,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 \
> @@ -318,7 +319,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 \
> @@ -433,9 +436,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..8b6c839408 100644
> --- a/nptl/Versions
> +++ b/nptl/Versions
> @@ -28,6 +28,9 @@ libc {
>      pthread_cond_wait; pthread_cond_signal;
>      pthread_cond_broadcast; pthread_cond_timedwait;
>    }
> +  GLBIC_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..0e1cf3939e 100644
> --- a/nptl/allocatestack.c
> +++ b/nptl/allocatestack.c
> @@ -413,16 +413,21 @@ 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.  */
> +    static uint64_t global_thread_number = 1;
> +    thread_number = ++global_thread_number;
> +
> +    /* 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);


Why can't you just make global_thread_number  do an atomic addition
instead of the lock here?   It will be slightly faster.  But I notice
you don't handle the case where you create and destroy over 2^64-1
threads (that is an overflow of global_thread_number).  You don't even
mention this limitation any where.  I can think of (maybe bad)
examples where this could be the case.  Treating threads as cheap as
run pools.  Yes it is not a good idea to do that but people can do it.

Thanks,
Andrew

>
>    /* Get memory for the stack.  */
>    if (__glibc_unlikely (attr->flags & ATTR_FLAG_STACKADDR))
> @@ -758,6 +763,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 c83b17b674..49e266139e 100644
> --- a/nptl/descr.h
> +++ b/nptl/descr.h
> @@ -395,6 +395,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..a9fdaa508b
> --- /dev/null
> +++ b/nptl/thread_number.c
> @@ -0,0 +1,26 @@
> +/* 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"
> +
> +__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..e26f19e44a
> --- /dev/null
> +++ b/nptl/tst-thread_number-multi.c
> @@ -0,0 +1,99 @@
> +/* 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>
> +
> +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 arround.  */
> +  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..43497205c7
> --- /dev/null
> +++ b/nptl/tst-thread_number-single.c
> @@ -0,0 +1,38 @@
> +/* 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>
> +
> +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 7a65dc641c..99f2e58875 100644
> --- a/sysdeps/generic/ldsodefs.h
> +++ b/sysdeps/generic/ldsodefs.h
> @@ -1056,6 +1056,10 @@ void __libc_setup_tls (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/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 2b2b386ab3..e0714ed951 100644
> --- a/sysdeps/nptl/pthread.h
> +++ b/sysdeps/nptl/pthread.h
> @@ -1148,6 +1148,10 @@ extern int pthread_atfork (void (*__prepare) (void),
>                            void (*__child) (void)) __THROW;
>
>
> +/* Return a number uniquely identifying THREAD, even after its
> +   termination.  */
> +__uint64_t pthread_thread_number_np (pthread_t __thread_id) __THROW;
> +
>  #ifdef __USE_EXTERN_INLINES
>  /* Optimizations.  */
>  __extern_inline int
> diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> index ec0ead15dd..e206f77540 100644
> --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> @@ -1,3 +1,5 @@
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.17 GLIBC_2.17 A
>  GLIBC_2.17 _Exit F
>  GLIBC_2.17 _IO_2_1_stderr_ D 0xe0
> diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
> index 5355769974..92429a8d78 100644
> --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>  GCC_3.0 __deregister_frame_info_bases F
>  GCC_3.0 __register_frame_info_bases F
>  GCC_3.0 __register_frame_info_table_bases F
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.0 GLIBC_2.0 A
>  GLIBC_2.0 _IO_adjust_column F
>  GLIBC_2.0 _IO_default_doallocate F
> diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
> index 9bafe71b51..bcd54ecdf5 100644
> --- a/sysdeps/unix/sysv/linux/arm/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
> @@ -1,3 +1,5 @@
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.10 GLIBC_2.10 A
>  GLIBC_2.10 __cxa_at_quick_exit F
>  GLIBC_2.10 __posix_getopt F
> diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
> index 90aa8d034f..84445a123e 100644
> --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
> @@ -1,3 +1,5 @@
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.10 GLIBC_2.10 A
>  GLIBC_2.10 __cxa_at_quick_exit F
>  GLIBC_2.10 __posix_getopt F
> diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
> index 4d44c30c64..caa8dff010 100644
> --- a/sysdeps/unix/sysv/linux/i386/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>  GCC_3.0 __deregister_frame_info_bases F
>  GCC_3.0 __register_frame_info_bases F
>  GCC_3.0 __register_frame_info_table_bases F
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.0 GLIBC_2.0 A
>  GLIBC_2.0 _IO_adjust_column F
>  GLIBC_2.0 _IO_default_doallocate F
> diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
> index 112fc57634..02301da334 100644
> --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
> @@ -1,3 +1,5 @@
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.10 GLIBC_2.10 A
>  GLIBC_2.10 __cxa_at_quick_exit F
>  GLIBC_2.10 __posix_getopt F
> diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> index 2e8b6a4586..a3fbcb831f 100644
> --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> @@ -1,3 +1,5 @@
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.10 GLIBC_2.10 A
>  GLIBC_2.10 __cxa_at_quick_exit F
>  GLIBC_2.10 __posix_getopt F
> diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> index 3c33400f67..203a63aa27 100644
> --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>  GCC_3.0 __deregister_frame_info_bases F
>  GCC_3.0 __register_frame_info_bases F
>  GCC_3.0 __register_frame_info_table_bases F
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.0 GLIBC_2.0 A
>  GLIBC_2.0 _IO_adjust_column F
>  GLIBC_2.0 _IO_default_doallocate F
> diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> index e1b1a579d2..a3be97ef65 100644
> --- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> @@ -1,3 +1,5 @@
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.18 GLIBC_2.18 A
>  GLIBC_2.18 _Exit F
>  GLIBC_2.18 _IO_2_1_stderr_ D 0x98
> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> index c1550323f3..94de2ef489 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>  GCC_3.0 __deregister_frame_info_bases F
>  GCC_3.0 __register_frame_info_bases F
>  GCC_3.0 __register_frame_info_table_bases F
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.0 GLIBC_2.0 A
>  GLIBC_2.0 _IO_adjust_column F
>  GLIBC_2.0 _IO_default_doallocate F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> index 3b3a172e4f..878bee4bb5 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>  GCC_3.0 __deregister_frame_info_bases F
>  GCC_3.0 __register_frame_info_bases F
>  GCC_3.0 __register_frame_info_table_bases F
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.0 GLIBC_2.0 A
>  GLIBC_2.0 _IO_adjust_column F
>  GLIBC_2.0 _IO_default_doallocate F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> index 101ca7a241..94706fccb4 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>  GCC_3.0 __deregister_frame_info_bases F
>  GCC_3.0 __register_frame_info_bases F
>  GCC_3.0 __register_frame_info_table_bases F
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.0 GLIBC_2.0 A
>  GLIBC_2.0 _IO_adjust_column F
>  GLIBC_2.0 _IO_default_doallocate F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> index 2d129f7170..adc3de5c88 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>  GCC_3.0 __deregister_frame_info_bases F
>  GCC_3.0 __register_frame_info_bases F
>  GCC_3.0 __register_frame_info_table_bases F
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.0 GLIBC_2.0 A
>  GLIBC_2.0 _IO_adjust_column F
>  GLIBC_2.0 _IO_default_doallocate F
> diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
> index 8bc350aff8..f6198b3dbb 100644
> --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
> @@ -1,3 +1,5 @@
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.21 GLIBC_2.21 A
>  GLIBC_2.21 _Exit F
>  GLIBC_2.21 _IO_2_1_stderr_ D 0x98
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> index 127c426e1c..363a3a2e10 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>  GCC_3.0 __deregister_frame_info_bases F
>  GCC_3.0 __register_frame_info_bases F
>  GCC_3.0 __register_frame_info_table_bases F
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.0 GLIBC_2.0 A
>  GLIBC_2.0 _IO_adjust_column F
>  GLIBC_2.0 _IO_default_doallocate F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> index a9411318e2..dfa0463282 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>  GCC_3.0 __deregister_frame_info_bases F
>  GCC_3.0 __register_frame_info_bases F
>  GCC_3.0 __register_frame_info_table_bases F
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.0 GLIBC_2.0 A
>  GLIBC_2.0 _IO_adjust_column F
>  GLIBC_2.0 _IO_default_doallocate F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
> index d7bf5db601..37a34eb833 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
> @@ -1,3 +1,5 @@
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.17 GLIBC_2.17 A
>  GLIBC_2.17 _Exit F
>  GLIBC_2.17 _IO_2_1_stderr_ D 0xe0
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
> index a3415a72ac..a0dbaf366a 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
> @@ -1,3 +1,5 @@
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.10 GLIBC_2.10 A
>  GLIBC_2.10 __cxa_at_quick_exit F
>  GLIBC_2.10 __posix_getopt F
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> index 414338f9a2..a30b304817 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>  GCC_3.0 __deregister_frame_info_bases F
>  GCC_3.0 __register_frame_info_bases F
>  GCC_3.0 __register_frame_info_table_bases F
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.0 GLIBC_2.0 A
>  GLIBC_2.0 _IO_adjust_column F
>  GLIBC_2.0 _IO_default_doallocate F
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> index f0f7a69b64..a759aa9cf5 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>  GCC_3.0 __deregister_frame_info_bases F
>  GCC_3.0 __register_frame_info_bases F
>  GCC_3.0 __register_frame_info_table_bases F
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.10 GLIBC_2.10 A
>  GLIBC_2.10 __cxa_at_quick_exit F
>  GLIBC_2.10 __posix_getopt F
> diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
> index 9f95aba898..133e0a55ef 100644
> --- a/sysdeps/unix/sysv/linux/sh/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>  GCC_3.0 __deregister_frame_info_bases F
>  GCC_3.0 __register_frame_info_bases F
>  GCC_3.0 __register_frame_info_table_bases F
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.10 GLIBC_2.10 A
>  GLIBC_2.10 __cxa_at_quick_exit F
>  GLIBC_2.10 __posix_getopt F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> index 83fbdf2d7e..e525ed69d6 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>  GCC_3.0 __deregister_frame_info_bases F
>  GCC_3.0 __register_frame_info_bases F
>  GCC_3.0 __register_frame_info_table_bases F
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.0 .div F
>  GLIBC_2.0 .mul F
>  GLIBC_2.0 .rem F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> index ee84ad10bc..d4fb34eceb 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>  GCC_3.0 __deregister_frame_info_bases F
>  GCC_3.0 __register_frame_info_bases F
>  GCC_3.0 __register_frame_info_table_bases F
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.10 GLIBC_2.10 A
>  GLIBC_2.10 __cxa_at_quick_exit F
>  GLIBC_2.10 __posix_getopt F
> diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
> index dcbfbc05ac..f598149374 100644
> --- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
> @@ -1,3 +1,5 @@
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.12 GLIBC_2.12 A
>  GLIBC_2.12 _Exit F
>  GLIBC_2.12 _IO_2_1_stderr_ D 0xa0
> diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
> index 53dc99c45a..cb0054f532 100644
> --- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
> @@ -1,3 +1,5 @@
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.12 GLIBC_2.12 A
>  GLIBC_2.12 _Exit F
>  GLIBC_2.12 _IO_2_1_stderr_ D 0xe0
> diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
> index dcbfbc05ac..f598149374 100644
> --- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
> @@ -1,3 +1,5 @@
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.12 GLIBC_2.12 A
>  GLIBC_2.12 _Exit F
>  GLIBC_2.12 _IO_2_1_stderr_ D 0xa0
> diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> index ae4dcaa47e..70a15fa003 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> @@ -1,3 +1,5 @@
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.10 GLIBC_2.10 A
>  GLIBC_2.10 __cxa_at_quick_exit F
>  GLIBC_2.10 __posix_getopt F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> index 0dbda14796..afbdec65d5 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> @@ -1,3 +1,5 @@
> +GLBIC_2.27 GLBIC_2.27 A
> +GLBIC_2.27 pthread_thread_number_np F
>  GLIBC_2.16 GLIBC_2.16 A
>  GLIBC_2.16 _Exit F
>  GLIBC_2.16 _IO_2_1_stderr_ D 0xa0<div id="DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2"><br />
<table style="border-top: 1px solid #D3D4DE;">
	<tr>
        <td style="width: 55px; padding-top: 13px;"><a
href="http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail"
target="_blank"><img
src="https://ipmcdn.avast.com/images/icons/icon-envelope-tick-green-avg-v1.png"
alt="" width="46" height="29" style="width: 46px; height: 29px;"
/></a></td>
		<td style="width: 470px; padding-top: 12px; color: #41424e;
font-size: 13px; font-family: Arial, Helvetica, sans-serif;
line-height: 18px;">Virus-free. <a
href="http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail"
target="_blank" style="color: #4453ea;">www.avg.com</a>
		</td>
	</tr>
</table><a href="#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2" width="1"
height="1"></a></div>

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2017-12-14 18:56 [PATCH] nptl: Add pthread_thread_number_np function Florian Weimer
                   ` (2 preceding siblings ...)
  2017-12-15  0:29 ` Andrew Pinski
@ 2017-12-15  4:08 ` Carlos O'Donell
  2017-12-15  7:48   ` Florian Weimer
  3 siblings, 1 reply; 28+ messages in thread
From: Carlos O'Donell @ 2017-12-15  4:08 UTC (permalink / raw)
  To: Florian Weimer, libc-alpha

On 12/14/2017 10:56 AM, Florian Weimer wrote:
> 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.

High level:

The addition of a new API to libc.so needs a strong justification.

Do you have a use in mind for this API?

When would users use this number?

Why would they use this number?

Do any of the uses you envision overlap with the longstanding 
requests for gettid()?

Design level:

We make claims that the thread number is never reused, but then the
implementation wraps the uint64_t global counter, and reuses the
number. If we really don't allow reuse, then we limit the implementation
to only ever starting 2^64-1 threads, similar to the discussions around
dlopen and void* cookies, I don't know if this kind of limit is a good
idea or not. My instinct tells me we should not limit the implementation
in such ways.

We could allocate the thread numbers lazily, and that would certainly
avoid limiting ourselves to only allocating 2^64-1 threads. On top of
that if the function could return an error then we could return such
an error at overflow:

 int pthread_thread_number_np (uint64_t* thread_number, pthread_t @var{thread})

Returns 0 if the thread has a unique number, otherwise -1 if it does not.

Implementation level:

Just some minor textual nits, and missing comments.


> 2017-12-14  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/pthread.h (pthread_thread_number_np): Declare.
> 	* sysdeps/unix/sysv/linux/libc**.abilist: Update.
> 
> diff --git a/csu/libc-tls.c b/csu/libc-tls.c
> index 00138eb43a..af81cba12c 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 8563555079..66ce2953a4 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -30,7 +30,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 cfd3729b8e..214e2312fa 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..6c62ff3da0 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,29 @@ 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.

We should be clear here that uint64_t (the return type) only has 64-bits,
and while theoretically difficult to reach, this has a limit. The only way
not to reuse the numbers is to limit the implementation to only allowing
uint64_t worth of threads to ever be started. That's a limit that never
existed before the existence of this API.

My worry here is that once you open pandoras box and say that they thread
number *might* be reused after 2^64-1 pthread_create's, then users will
start writing code *not* to treat it as unique.

Thus, see my notes above about changing the interface slightly.

> +
> +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 process IDs or thread IDs assigned by the kernel.

Suggest:

They bear no relationship to POSIX thread IDs (pthread_t), process IDs,
or Linux kernel thread IDs.

> +@end deftypefun
> +
>  @c FIXME these are undocumented:
>  @c pthread_atfork
>  @c pthread_attr_destroy
> diff --git a/nptl/Makefile b/nptl/Makefile
> index ae388d1112..087fb6a8b5 100644
> --- a/nptl/Makefile
> +++ b/nptl/Makefile
> @@ -30,7 +30,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
> @@ -302,7 +302,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 \
> @@ -318,7 +319,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 \
> @@ -433,9 +436,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..8b6c839408 100644
> --- a/nptl/Versions
> +++ b/nptl/Versions
> @@ -28,6 +28,9 @@ libc {
>      pthread_cond_wait; pthread_cond_signal;
>      pthread_cond_broadcast; pthread_cond_timedwait;
>    }
> +  GLBIC_2.27 {

Typo. GLIBC.

> +    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..0e1cf3939e 100644
> --- a/nptl/allocatestack.c
> +++ b/nptl/allocatestack.c
> @@ -413,16 +413,21 @@ 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);

You need to add some P&C comments explaining that __default_pthread_attr_lock
is now *also* protecting the global_thread_number global and why.

> +  {
> +    /* Number 1 is reserved for the initial thread.  */
> +    static uint64_t global_thread_number = 1;
> +    thread_number = ++global_thread_number;

Andrew asked this already, but we either need a comment about not worrying
about overflow, or handling it properly.

> +
> +    /* 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 +763,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 c83b17b674..49e266139e 100644
> --- a/nptl/descr.h
> +++ b/nptl/descr.h
> @@ -395,6 +395,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..a9fdaa508b
> --- /dev/null
> +++ b/nptl/thread_number.c
> @@ -0,0 +1,26 @@
> +/* 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"
> +
> +__uint64_t
> +pthread_thread_number_np (pthread_t threadid)
> +{
> +  struct pthread *pd = (struct pthread *) threadid;
> +  return pd->number;
> +}

OK.

> 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..e26f19e44a
> --- /dev/null
> +++ b/nptl/tst-thread_number-multi.c
> @@ -0,0 +1,99 @@
> +/* 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>
> +
> +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);

Why do we isolate this in a subprocess?
> +
> +  /* Create thread_count threads, half of which are joined
> +     immediately, have of which stay arround.  */

s/arround/around/g

> +  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);

Again, why in a subprocess?

> +
> +  /* 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);

Likewise.

> +
> +  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..43497205c7
> --- /dev/null
> +++ b/nptl/tst-thread_number-single.c
> @@ -0,0 +1,38 @@
> +/* 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>
> +
> +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);

Likewise. 

> +
> +  return 0;
> +}
> +
> +#include <support/test-driver.c>
> diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
> index 7a65dc641c..99f2e58875 100644
> --- a/sysdeps/generic/ldsodefs.h
> +++ b/sysdeps/generic/ldsodefs.h
> @@ -1056,6 +1056,10 @@ void __libc_setup_tls (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/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;

OK.

> +}
> diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h
> index 2b2b386ab3..e0714ed951 100644
> --- a/sysdeps/nptl/pthread.h
> +++ b/sysdeps/nptl/pthread.h
> @@ -1148,6 +1148,10 @@ extern int pthread_atfork (void (*__prepare) (void),
>  			   void (*__child) (void)) __THROW;
>  
>  
> +/* Return a number uniquely identifying THREAD, even after its
> +   termination.  */
> +__uint64_t pthread_thread_number_np (pthread_t __thread_id) __THROW;
> +
>  #ifdef __USE_EXTERN_INLINES
>  /* Optimizations.  */
>  __extern_inline int

[abilist updates]

As Nix noted there is a typo in nptl/Versions which propagates to the
abilist files too.

-- 
Cheers,
Carlos.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2017-12-14 23:34 ` Nix
@ 2017-12-15  6:41   ` Florian Weimer
  0 siblings, 0 replies; 28+ messages in thread
From: Florian Weimer @ 2017-12-15  6:41 UTC (permalink / raw)
  To: Nix; +Cc: libc-alpha

On 12/15/2017 12:34 AM, Nix wrote:
> On 14 Dec 2017, Florian Weimer uttered the following:
>> diff --git a/nptl/Versions b/nptl/Versions
>> index 0ae5def464..8b6c839408 100644
>> --- a/nptl/Versions
>> +++ b/nptl/Versions
>> @@ -28,6 +28,9 @@ libc {
>>       pthread_cond_wait; pthread_cond_signal;
>>       pthread_cond_broadcast; pthread_cond_timedwait;
>>     }
>> +  GLBIC_2.27 {
>> +    pthread_thread_number_np;
>> +  }
>>     GLIBC_PRIVATE {
>>       __libc_alloca_cutoff;
>>       # Internal libc interface to libpthread
> 
> GLBIC is a definite typo (repeated, of course, in all the abilist
> files).

Oops, I'll send an updated patch in respond to Carlos' message.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2017-12-15  0:29 ` Andrew Pinski
@ 2017-12-15  7:47   ` Florian Weimer
  2017-12-15  7:54   ` Andrew Pinski
  1 sibling, 0 replies; 28+ messages in thread
From: Florian Weimer @ 2017-12-15  7:47 UTC (permalink / raw)
  To: Andrew Pinski; +Cc: GNU C Library

On 12/15/2017 01:29 AM, Andrew Pinski wrote:
> Why can't you just make global_thread_number  do an atomic addition
> instead of the lock here?   It will be slightly faster.

Not sure about that.  In the common case (no stack size specified) we 
already acquire a lock.  So we'd have to perform three atomic operations 
instead of two if we don't reuse the lock.

There's also the problem of 32-bit architectures without 64-bit atomic 
operations.

> But I notice
> you don't handle the case where you create and destroy over 2^64-1
> threads (that is an overflow of global_thread_number).

Yes, I should add a sanity check and an abort for this case.

> You don't even mention this limitation any where.

Traditionally, we have been ignoring 64-bit counter overflows, treating 
them as impossible.  For a simple counter with no countermeasures 
against contention, I really don't see how the overflow can happen any 
time soon.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2017-12-15  4:08 ` Carlos O'Donell
@ 2017-12-15  7:48   ` Florian Weimer
  2017-12-20  8:06     ` Carlos O'Donell
                       ` (2 more replies)
  0 siblings, 3 replies; 28+ messages in thread
From: Florian Weimer @ 2017-12-15  7:48 UTC (permalink / raw)
  To: Carlos O'Donell; +Cc: libc-alpha

[-- Attachment #1: Type: text/plain, Size: 6395 bytes --]

On 12/15/2017 05:08 AM, Carlos O'Donell wrote:
> On 12/14/2017 10:56 AM, Florian Weimer wrote:
>> 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.
> 
> High level:
> 
> The addition of a new API to libc.so needs a strong justification.
> 
> Do you have a use in mind for this API?
> 
> When would users use this number?
> 
> Why would they use this number?

Logging, and discriminating between threads, for example in random bit 
generators.

> Do any of the uses you envision overlap with the longstanding
> requests for gettid()?

Barely, because gettid does not return a unique number over time, and 
the number returned from pthread_thread_number_np cannot be used with 
existing interfaces.

> Design level:
> 
> We make claims that the thread number is never reused, but then the
> implementation wraps the uint64_t global counter, and reuses the
> number. If we really don't allow reuse, then we limit the implementation
> to only ever starting 2^64-1 threads, similar to the discussions around
> dlopen and void* cookies, I don't know if this kind of limit is a good
> idea or not. My instinct tells me we should not limit the implementation
> in such ways.

The implementation of condition variables uses a 64-bit counter in a 
similar way.  I assumed that we had consensus that we can assume that a 
simple 64-bit counter would never overflow.

> We could allocate the thread numbers lazily, and that would certainly
> avoid limiting ourselves to only allocating 2^64-1 threads. On top of
> that if the function could return an error then we could return such
> an error at overflow:
> 
>   int pthread_thread_number_np (uint64_t* thread_number, pthread_t @var{thread})
> 
> Returns 0 if the thread has a unique number, otherwise -1 if it does not.

That's a bad interface.  If you are worried about 64-bit overflow, we 
should use a 128-bit counter instead, but I'm not convinced this is 
necessary.

Lazy allocation would make the function not safe for use in signal handlers.

>> +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.
> 
> We should be clear here that uint64_t (the return type) only has 64-bits,
> and while theoretically difficult to reach, this has a limit. The only way
> not to reuse the numbers is to limit the implementation to only allowing
> uint64_t worth of threads to ever be started. That's a limit that never
> existed before the existence of this API.

This  restriction already existed:

    We use two 64b counters: __wseq and __g1_start.  They are
    monotonically increasing and single-writer-multiple-readers
    counters, so we can implement load, fetch-and-add, and
    fetch-and-xor operations even when we just have 32b atomics.
    Values we add or xor are less than or equal to 1<<31 (*), so we
    only have to make overflow-and-addition atomic wrt. to concurrent
    load operations and xor operations.  To do that, we split each
    counter into two 32b values of which we reserve the MSB of each to
    represent an overflow from the lower-order half to the higher-order
    half.

> My worry here is that once you open pandoras box and say that they thread
> number *might* be reused after 2^64-1 pthread_create's, then users will
> start writing code *not* to treat it as unique.

I'm going to put in a __libc_fatal, just to be on the safe side.

> Thus, see my notes above about changing the interface slightly.
> 
>> +
>> +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 process IDs or thread IDs assigned by the kernel.
> 
> Suggest:
> 
> They bear no relationship to POSIX thread IDs (pthread_t), process IDs,
> or Linux kernel thread IDs.

“
They bear no relationship to POSIX thread IDs (@code{pthread_t} values), 
process IDs or thread IDs assigned by the kernel.
”

(This is in the generic part of the manual, so we shouldn't reference 
Linux unless absolutely necessary.)

>> +    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..0e1cf3939e 100644
>> --- a/nptl/allocatestack.c
>> +++ b/nptl/allocatestack.c
>> @@ -413,16 +413,21 @@ 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);
> 
> You need to add some P&C comments explaining that __default_pthread_attr_lock
> is now *also* protecting the global_thread_number global and why.

I now have:

   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");

>> +static int
>> +do_test (void)
>> +{
>> +  TEST_COMPARE (pthread_thread_number_np (pthread_self ()), 1U);
>> +  support_isolate_in_subprocess (subprocess, NULL);
> 
> Why do we isolate this in a subprocess?

To check that the main thread has thread number 1 in a subprocess.  I'll 
add a comment.

New patch attached.

Thanks,
Florian

[-- Attachment #2: thread_number.patch --]
[-- Type: text/x-patch, Size: 35339 bytes --]

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-14  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/pthread.h (pthread_thread_number_np): Declare.
	* sysdeps/unix/sysv/linux/libc**.abilist: Update.

diff --git a/NEWS b/NEWS
index c5607c855f..257b252a63 100644
--- a/NEWS
+++ b/NEWS
@@ -46,7 +46,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 00138eb43a..af81cba12c 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 8563555079..66ce2953a4 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -30,7 +30,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 cfd3729b8e..214e2312fa 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 ae388d1112..087fb6a8b5 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -30,7 +30,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
@@ -302,7 +302,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 \
@@ -318,7 +319,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 \
@@ -433,9 +436,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 c83b17b674..49e266139e 100644
--- a/nptl/descr.h
+++ b/nptl/descr.h
@@ -395,6 +395,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..a9fdaa508b
--- /dev/null
+++ b/nptl/thread_number.c
@@ -0,0 +1,26 @@
+/* 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"
+
+__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 7a65dc641c..99f2e58875 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1056,6 +1056,10 @@ void __libc_setup_tls (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/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 2b2b386ab3..e0714ed951 100644
--- a/sysdeps/nptl/pthread.h
+++ b/sysdeps/nptl/pthread.h
@@ -1148,6 +1148,10 @@ extern int pthread_atfork (void (*__prepare) (void),
 			   void (*__child) (void)) __THROW;
 
 
+/* Return a number uniquely identifying THREAD, even after its
+   termination.  */
+__uint64_t pthread_thread_number_np (pthread_t __thread_id) __THROW;
+
 #ifdef __USE_EXTERN_INLINES
 /* Optimizations.  */
 __extern_inline int
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index ec0ead15dd..e9ba69cd43 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2113,6 +2113,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 5355769974..71258b014b 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2024,6 +2024,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 9bafe71b51..df5eb357f8 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -114,6 +114,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 90aa8d034f..3c37cf48ec 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -1878,6 +1878,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/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 4d44c30c64..aba40e2119 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2043,6 +2043,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 112fc57634..6ef38f5150 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1907,6 +1907,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 2e8b6a4586..63cda3a92e 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/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/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 3c33400f67..4b0d923e1c 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -1992,6 +1992,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 e1b1a579d2..68c927f54e 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2113,6 +2113,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 c1550323f3..71f3785cdd 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1967,6 +1967,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 3b3a172e4f..09d7344ce9 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1965,6 +1965,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 101ca7a241..fea609bd3a 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1963,6 +1963,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 2d129f7170..3cd9e072a3 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1958,6 +1958,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 8bc350aff8..b8b2941999 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2154,6 +2154,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 127c426e1c..60f5c63cc9 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -1996,6 +1996,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 a9411318e2..f538a91cb2 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -2001,6 +2001,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 d7bf5db601..f83d43c8cb 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2208,6 +2208,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 a3415a72ac..e61ce85a68 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/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/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 414338f9a2..ae74cb8184 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -1996,6 +1996,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 f0f7a69b64..fffbcb3d3e 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1897,6 +1897,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 9f95aba898..cb8eb05b2e 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1882,6 +1882,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 83fbdf2d7e..4184dcff17 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -1989,6 +1989,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 ee84ad10bc..cb9a0ae97f 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1926,6 +1926,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/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
index dcbfbc05ac..c305690b5a 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
@@ -2120,6 +2120,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/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
index 53dc99c45a..be6507ee22 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
@@ -2120,6 +2120,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/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
index dcbfbc05ac..c305690b5a 100644
--- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
@@ -2120,6 +2120,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 ae4dcaa47e..f418549369 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1884,6 +1884,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 0dbda14796..6bc513a7ed 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2127,6 +2127,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

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2017-12-15  0:29 ` Andrew Pinski
  2017-12-15  7:47   ` Florian Weimer
@ 2017-12-15  7:54   ` Andrew Pinski
  1 sibling, 0 replies; 28+ messages in thread
From: Andrew Pinski @ 2017-12-15  7:54 UTC (permalink / raw)
  To: Florian Weimer; +Cc: GNU C Library

On Thu, Dec 14, 2017 at 4:29 PM, Andrew Pinski <pinskia@gmail.com> wrote:
> On Thu, Dec 14, 2017 at 10:56 AM, Florian Weimer <fweimer@redhat.com> wrote:
>> 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-14  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/pthread.h (pthread_thread_number_np): Declare.
>>         * sysdeps/unix/sysv/linux/libc**.abilist: Update.
>>
>> diff --git a/csu/libc-tls.c b/csu/libc-tls.c
>> index 00138eb43a..af81cba12c 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 8563555079..66ce2953a4 100644
>> --- a/elf/Makefile
>> +++ b/elf/Makefile
>> @@ -30,7 +30,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 cfd3729b8e..214e2312fa 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..6c62ff3da0 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,29 @@ 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 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 ae388d1112..087fb6a8b5 100644
>> --- a/nptl/Makefile
>> +++ b/nptl/Makefile
>> @@ -30,7 +30,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
>> @@ -302,7 +302,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 \
>> @@ -318,7 +319,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 \
>> @@ -433,9 +436,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..8b6c839408 100644
>> --- a/nptl/Versions
>> +++ b/nptl/Versions
>> @@ -28,6 +28,9 @@ libc {
>>      pthread_cond_wait; pthread_cond_signal;
>>      pthread_cond_broadcast; pthread_cond_timedwait;
>>    }
>> +  GLBIC_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..0e1cf3939e 100644
>> --- a/nptl/allocatestack.c
>> +++ b/nptl/allocatestack.c
>> @@ -413,16 +413,21 @@ 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.  */
>> +    static uint64_t global_thread_number = 1;
>> +    thread_number = ++global_thread_number;
>> +
>> +    /* 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);
>
>
> Why can't you just make global_thread_number  do an atomic addition
> instead of the lock here?   It will be slightly faster.  But I notice
> you don't handle the case where you create and destroy over 2^64-1
> threads (that is an overflow of global_thread_number).  You don't even
> mention this limitation any where.  I can think of (maybe bad)
> examples where this could be the case.  Treating threads as cheap as
> run pools.  Yes it is not a good idea to do that but people can do it.


So I did the math and I take back my objection with respect to the
overflow.  It would take more than a million years to overflow 64bit.
Even if creating a thread was less than 1 microsecond.

Thanks,
Andrew

>
> Thanks,
> Andrew
>
>>
>>    /* Get memory for the stack.  */
>>    if (__glibc_unlikely (attr->flags & ATTR_FLAG_STACKADDR))
>> @@ -758,6 +763,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 c83b17b674..49e266139e 100644
>> --- a/nptl/descr.h
>> +++ b/nptl/descr.h
>> @@ -395,6 +395,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..a9fdaa508b
>> --- /dev/null
>> +++ b/nptl/thread_number.c
>> @@ -0,0 +1,26 @@
>> +/* 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"
>> +
>> +__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..e26f19e44a
>> --- /dev/null
>> +++ b/nptl/tst-thread_number-multi.c
>> @@ -0,0 +1,99 @@
>> +/* 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>
>> +
>> +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 arround.  */
>> +  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..43497205c7
>> --- /dev/null
>> +++ b/nptl/tst-thread_number-single.c
>> @@ -0,0 +1,38 @@
>> +/* 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>
>> +
>> +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 7a65dc641c..99f2e58875 100644
>> --- a/sysdeps/generic/ldsodefs.h
>> +++ b/sysdeps/generic/ldsodefs.h
>> @@ -1056,6 +1056,10 @@ void __libc_setup_tls (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/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 2b2b386ab3..e0714ed951 100644
>> --- a/sysdeps/nptl/pthread.h
>> +++ b/sysdeps/nptl/pthread.h
>> @@ -1148,6 +1148,10 @@ extern int pthread_atfork (void (*__prepare) (void),
>>                            void (*__child) (void)) __THROW;
>>
>>
>> +/* Return a number uniquely identifying THREAD, even after its
>> +   termination.  */
>> +__uint64_t pthread_thread_number_np (pthread_t __thread_id) __THROW;
>> +
>>  #ifdef __USE_EXTERN_INLINES
>>  /* Optimizations.  */
>>  __extern_inline int
>> diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
>> index ec0ead15dd..e206f77540 100644
>> --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
>> @@ -1,3 +1,5 @@
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.17 GLIBC_2.17 A
>>  GLIBC_2.17 _Exit F
>>  GLIBC_2.17 _IO_2_1_stderr_ D 0xe0
>> diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
>> index 5355769974..92429a8d78 100644
>> --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
>> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>>  GCC_3.0 __deregister_frame_info_bases F
>>  GCC_3.0 __register_frame_info_bases F
>>  GCC_3.0 __register_frame_info_table_bases F
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.0 GLIBC_2.0 A
>>  GLIBC_2.0 _IO_adjust_column F
>>  GLIBC_2.0 _IO_default_doallocate F
>> diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
>> index 9bafe71b51..bcd54ecdf5 100644
>> --- a/sysdeps/unix/sysv/linux/arm/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
>> @@ -1,3 +1,5 @@
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.10 GLIBC_2.10 A
>>  GLIBC_2.10 __cxa_at_quick_exit F
>>  GLIBC_2.10 __posix_getopt F
>> diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
>> index 90aa8d034f..84445a123e 100644
>> --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
>> @@ -1,3 +1,5 @@
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.10 GLIBC_2.10 A
>>  GLIBC_2.10 __cxa_at_quick_exit F
>>  GLIBC_2.10 __posix_getopt F
>> diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
>> index 4d44c30c64..caa8dff010 100644
>> --- a/sysdeps/unix/sysv/linux/i386/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
>> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>>  GCC_3.0 __deregister_frame_info_bases F
>>  GCC_3.0 __register_frame_info_bases F
>>  GCC_3.0 __register_frame_info_table_bases F
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.0 GLIBC_2.0 A
>>  GLIBC_2.0 _IO_adjust_column F
>>  GLIBC_2.0 _IO_default_doallocate F
>> diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
>> index 112fc57634..02301da334 100644
>> --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
>> @@ -1,3 +1,5 @@
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.10 GLIBC_2.10 A
>>  GLIBC_2.10 __cxa_at_quick_exit F
>>  GLIBC_2.10 __posix_getopt F
>> diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
>> index 2e8b6a4586..a3fbcb831f 100644
>> --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
>> @@ -1,3 +1,5 @@
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.10 GLIBC_2.10 A
>>  GLIBC_2.10 __cxa_at_quick_exit F
>>  GLIBC_2.10 __posix_getopt F
>> diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
>> index 3c33400f67..203a63aa27 100644
>> --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
>> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>>  GCC_3.0 __deregister_frame_info_bases F
>>  GCC_3.0 __register_frame_info_bases F
>>  GCC_3.0 __register_frame_info_table_bases F
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.0 GLIBC_2.0 A
>>  GLIBC_2.0 _IO_adjust_column F
>>  GLIBC_2.0 _IO_default_doallocate F
>> diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
>> index e1b1a579d2..a3be97ef65 100644
>> --- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
>> @@ -1,3 +1,5 @@
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.18 GLIBC_2.18 A
>>  GLIBC_2.18 _Exit F
>>  GLIBC_2.18 _IO_2_1_stderr_ D 0x98
>> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
>> index c1550323f3..94de2ef489 100644
>> --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
>> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>>  GCC_3.0 __deregister_frame_info_bases F
>>  GCC_3.0 __register_frame_info_bases F
>>  GCC_3.0 __register_frame_info_table_bases F
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.0 GLIBC_2.0 A
>>  GLIBC_2.0 _IO_adjust_column F
>>  GLIBC_2.0 _IO_default_doallocate F
>> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
>> index 3b3a172e4f..878bee4bb5 100644
>> --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
>> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>>  GCC_3.0 __deregister_frame_info_bases F
>>  GCC_3.0 __register_frame_info_bases F
>>  GCC_3.0 __register_frame_info_table_bases F
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.0 GLIBC_2.0 A
>>  GLIBC_2.0 _IO_adjust_column F
>>  GLIBC_2.0 _IO_default_doallocate F
>> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
>> index 101ca7a241..94706fccb4 100644
>> --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
>> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>>  GCC_3.0 __deregister_frame_info_bases F
>>  GCC_3.0 __register_frame_info_bases F
>>  GCC_3.0 __register_frame_info_table_bases F
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.0 GLIBC_2.0 A
>>  GLIBC_2.0 _IO_adjust_column F
>>  GLIBC_2.0 _IO_default_doallocate F
>> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
>> index 2d129f7170..adc3de5c88 100644
>> --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
>> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>>  GCC_3.0 __deregister_frame_info_bases F
>>  GCC_3.0 __register_frame_info_bases F
>>  GCC_3.0 __register_frame_info_table_bases F
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.0 GLIBC_2.0 A
>>  GLIBC_2.0 _IO_adjust_column F
>>  GLIBC_2.0 _IO_default_doallocate F
>> diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
>> index 8bc350aff8..f6198b3dbb 100644
>> --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
>> @@ -1,3 +1,5 @@
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.21 GLIBC_2.21 A
>>  GLIBC_2.21 _Exit F
>>  GLIBC_2.21 _IO_2_1_stderr_ D 0x98
>> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
>> index 127c426e1c..363a3a2e10 100644
>> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
>> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>>  GCC_3.0 __deregister_frame_info_bases F
>>  GCC_3.0 __register_frame_info_bases F
>>  GCC_3.0 __register_frame_info_table_bases F
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.0 GLIBC_2.0 A
>>  GLIBC_2.0 _IO_adjust_column F
>>  GLIBC_2.0 _IO_default_doallocate F
>> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
>> index a9411318e2..dfa0463282 100644
>> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
>> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>>  GCC_3.0 __deregister_frame_info_bases F
>>  GCC_3.0 __register_frame_info_bases F
>>  GCC_3.0 __register_frame_info_table_bases F
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.0 GLIBC_2.0 A
>>  GLIBC_2.0 _IO_adjust_column F
>>  GLIBC_2.0 _IO_default_doallocate F
>> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
>> index d7bf5db601..37a34eb833 100644
>> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
>> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
>> @@ -1,3 +1,5 @@
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.17 GLIBC_2.17 A
>>  GLIBC_2.17 _Exit F
>>  GLIBC_2.17 _IO_2_1_stderr_ D 0xe0
>> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
>> index a3415a72ac..a0dbaf366a 100644
>> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
>> @@ -1,3 +1,5 @@
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.10 GLIBC_2.10 A
>>  GLIBC_2.10 __cxa_at_quick_exit F
>>  GLIBC_2.10 __posix_getopt F
>> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
>> index 414338f9a2..a30b304817 100644
>> --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
>> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>>  GCC_3.0 __deregister_frame_info_bases F
>>  GCC_3.0 __register_frame_info_bases F
>>  GCC_3.0 __register_frame_info_table_bases F
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.0 GLIBC_2.0 A
>>  GLIBC_2.0 _IO_adjust_column F
>>  GLIBC_2.0 _IO_default_doallocate F
>> diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
>> index f0f7a69b64..a759aa9cf5 100644
>> --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
>> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>>  GCC_3.0 __deregister_frame_info_bases F
>>  GCC_3.0 __register_frame_info_bases F
>>  GCC_3.0 __register_frame_info_table_bases F
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.10 GLIBC_2.10 A
>>  GLIBC_2.10 __cxa_at_quick_exit F
>>  GLIBC_2.10 __posix_getopt F
>> diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
>> index 9f95aba898..133e0a55ef 100644
>> --- a/sysdeps/unix/sysv/linux/sh/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
>> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>>  GCC_3.0 __deregister_frame_info_bases F
>>  GCC_3.0 __register_frame_info_bases F
>>  GCC_3.0 __register_frame_info_table_bases F
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.10 GLIBC_2.10 A
>>  GLIBC_2.10 __cxa_at_quick_exit F
>>  GLIBC_2.10 __posix_getopt F
>> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
>> index 83fbdf2d7e..e525ed69d6 100644
>> --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
>> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>>  GCC_3.0 __deregister_frame_info_bases F
>>  GCC_3.0 __register_frame_info_bases F
>>  GCC_3.0 __register_frame_info_table_bases F
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.0 .div F
>>  GLIBC_2.0 .mul F
>>  GLIBC_2.0 .rem F
>> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
>> index ee84ad10bc..d4fb34eceb 100644
>> --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
>> @@ -3,6 +3,8 @@ GCC_3.0 _Unwind_Find_FDE F
>>  GCC_3.0 __deregister_frame_info_bases F
>>  GCC_3.0 __register_frame_info_bases F
>>  GCC_3.0 __register_frame_info_table_bases F
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.10 GLIBC_2.10 A
>>  GLIBC_2.10 __cxa_at_quick_exit F
>>  GLIBC_2.10 __posix_getopt F
>> diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
>> index dcbfbc05ac..f598149374 100644
>> --- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
>> @@ -1,3 +1,5 @@
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.12 GLIBC_2.12 A
>>  GLIBC_2.12 _Exit F
>>  GLIBC_2.12 _IO_2_1_stderr_ D 0xa0
>> diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
>> index 53dc99c45a..cb0054f532 100644
>> --- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
>> @@ -1,3 +1,5 @@
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.12 GLIBC_2.12 A
>>  GLIBC_2.12 _Exit F
>>  GLIBC_2.12 _IO_2_1_stderr_ D 0xe0
>> diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
>> index dcbfbc05ac..f598149374 100644
>> --- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
>> @@ -1,3 +1,5 @@
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.12 GLIBC_2.12 A
>>  GLIBC_2.12 _Exit F
>>  GLIBC_2.12 _IO_2_1_stderr_ D 0xa0
>> diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
>> index ae4dcaa47e..70a15fa003 100644
>> --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
>> @@ -1,3 +1,5 @@
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.10 GLIBC_2.10 A
>>  GLIBC_2.10 __cxa_at_quick_exit F
>>  GLIBC_2.10 __posix_getopt F
>> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
>> index 0dbda14796..afbdec65d5 100644
>> --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
>> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
>> @@ -1,3 +1,5 @@
>> +GLBIC_2.27 GLBIC_2.27 A
>> +GLBIC_2.27 pthread_thread_number_np F
>>  GLIBC_2.16 GLIBC_2.16 A
>>  GLIBC_2.16 _Exit F
>>  GLIBC_2.16 _IO_2_1_stderr_ D 0xa0<div id="DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2"><br />
> <table style="border-top: 1px solid #D3D4DE;">
>         <tr>
>         <td style="width: 55px; padding-top: 13px;"><a
> href="http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail"
> target="_blank"><img
> src="https://ipmcdn.avast.com/images/icons/icon-envelope-tick-green-avg-v1.png"
> alt="" width="46" height="29" style="width: 46px; height: 29px;"
> /></a></td>
>                 <td style="width: 470px; padding-top: 12px; color: #41424e;
> font-size: 13px; font-family: Arial, Helvetica, sans-serif;
> line-height: 18px;">Virus-free. <a
> href="http://www.avg.com/email-signature?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail"
> target="_blank" style="color: #4453ea;">www.avg.com</a>
>                 </td>
>         </tr>
> </table><a href="#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2" width="1"
> height="1"></a></div>

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2017-12-15  7:48   ` Florian Weimer
@ 2017-12-20  8:06     ` Carlos O'Donell
  2017-12-20 14:34       ` Florian Weimer
  2017-12-21  9:26     ` Carlos O'Donell
  2018-03-02 18:04     ` Rich Felker
  2 siblings, 1 reply; 28+ messages in thread
From: Carlos O'Donell @ 2017-12-20  8:06 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha

On 12/14/2017 11:47 PM, Florian Weimer wrote:
> On 12/15/2017 05:08 AM, Carlos O'Donell wrote:
>> On 12/14/2017 10:56 AM, Florian Weimer wrote:
>>> 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.
>>
>> High level:
>>
>> The addition of a new API to libc.so needs a strong justification.
>>
>> Do you have a use in mind for this API?
>>
>> When would users use this number?
>>
>> Why would they use this number?
> 
> Logging, and discriminating between threads, for example in random
> bit generators.

Good. You should mention these uses in the NEWS entry for the new
function. Please add a NEWS entry in v2.

If by "random bit generators" we are talking about arc4random, we could
add this as an internal interface for direct use by arc4random? That
wouldn't be a problem. I would not want this review to block arc4random.

>> Do any of the uses you envision overlap with the longstanding
>> requests for gettid()?
> 
> Barely, because gettid does not return a unique number over time, and
> the number returned from pthread_thread_number_np cannot be used with
> existing interfaces.

I like that answer. Thanks.
 
>> Design level:
>>
>> We make claims that the thread number is never reused, but then the
>> implementation wraps the uint64_t global counter, and reuses the
>> number. If we really don't allow reuse, then we limit the implementation
>> to only ever starting 2^64-1 threads, similar to the discussions around
>> dlopen and void* cookies, I don't know if this kind of limit is a good
>> idea or not. My instinct tells me we should not limit the implementation
>> in such ways.
> 
> The implementation of condition variables uses a 64-bit counter in a
> similar way.  I assumed that we had consensus that we can assume that
> a simple 64-bit counter would never overflow.

The comparison is not valid.

One can create and destroy an infinite number of condition variables.

The design of the pthread_thread_number_np API immediately limits the
number of creatable threads to the size of the return type. If we allow
creating more threads than that then we break the API.

My objection is not with the internal implementation of a 64-bit counter.

My objection is to the external exposing of a limit on number of threads.

This is the same problem with using an integer cookie for dlopen returns.
 
>> We could allocate the thread numbers lazily, and that would certainly
>> avoid limiting ourselves to only allocating 2^64-1 threads. On top of
>> that if the function could return an error then we could return such
>> an error at overflow:
>>
>>   int pthread_thread_number_np (uint64_t* thread_number, pthread_t @var{thread})
>>
>> Returns 0 if the thread has a unique number, otherwise -1 if it does not.
> 
> That's a bad interface.  If you are worried about 64-bit overflow, we
> should use a 128-bit counter instead, but I'm not convinced this is
> necessary.

I *might* be convinced a 128-bit return is enough.

I would like to see a quick discussion of why we can't make an interface
that doesn't limit the number of threads?

We should not impose arbitrary limits on our interfaces.

Anything that uniquely identifies an object is going to, by the nature of
the requirement, be a variable-sized opaque value.

The implementation can have an internal 64-bit limit, that's fine, but the
external interface would then support an unlimited number of threads.

We can even provide a convenience function to turn the opaque value into
an ASCII string, and such an implementation can just print a 64-bit value
to the string buffer.

Would such an interface be truly terrible?

> Lazy allocation would make the function not safe for use in signal handlers.

Are you going to mark this function as AS-safe in the documentation?

Yes, you used '@assafe{}' in the manual, OK.

Note that your '@acsafe{}' markup in the manual is wrong, since this function
holds locks and is therefore not AS-safe.

>> My worry here is that once you open pandoras box and say that they thread
>> number *might* be reused after 2^64-1 pthread_create's, then users will
>> start writing code *not* to treat it as unique.
> 
> I'm going to put in a __libc_fatal, just to be on the safe side.

That's a good idea.

>> Thus, see my notes above about changing the interface slightly.
>>
>>> +
>>> +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 process IDs or thread IDs assigned by the kernel.
>>
>> Suggest:
>>
>> They bear no relationship to POSIX thread IDs (pthread_t), process IDs,
>> or Linux kernel thread IDs.
> 
> “
> They bear no relationship to POSIX thread IDs (@code{pthread_t} values), process IDs or thread IDs assigned by the kernel.
> ”
> 
> (This is in the generic part of the manual, so we shouldn't reference Linux unless absolutely necessary.)

Looks good.

>>> +    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..0e1cf3939e 100644
>>> --- a/nptl/allocatestack.c
>>> +++ b/nptl/allocatestack.c
>>> @@ -413,16 +413,21 @@ 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);
>>
>> You need to add some P&C comments explaining that __default_pthread_attr_lock
>> is now *also* protecting the global_thread_number global and why.
> 
> I now have:
> 
>   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.  */

OK.

>     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");
> 
>>> +static int
>>> +do_test (void)
>>> +{
>>> +  TEST_COMPARE (pthread_thread_number_np (pthread_self ()), 1U);
>>> +  support_isolate_in_subprocess (subprocess, NULL);
>>
>> Why do we isolate this in a subprocess?
> 
> To check that the main thread has thread number 1 in a subprocess.  I'll add a comment.
> 
> New patch attached.

Changes requested:

- Please add another comment in nptl/vars.c adding notes that show that 
  __default_pthread_attr_lock is being used to protect the thread number.

- Explore an interface that doesn't limit the number of threads we can
  create, or continue to convince me I'm crazy. Yes, with a 128-bit counter
  you could have zeptsecond thread creation times and still not overflow
  before the sun expires. That is to say that I'm looking to be convinced
  that a variable sized cookie interface for external uses is a bad idea.

-- 
Cheers,
Carlos.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2017-12-20  8:06     ` Carlos O'Donell
@ 2017-12-20 14:34       ` Florian Weimer
  2017-12-20 17:58         ` Carlos O'Donell
  0 siblings, 1 reply; 28+ messages in thread
From: Florian Weimer @ 2017-12-20 14:34 UTC (permalink / raw)
  To: Carlos O'Donell; +Cc: libc-alpha

On 12/20/2017 09:06 AM, Carlos O'Donell wrote:

> If by "random bit generators" we are talking about arc4random, we could
> add this as an internal interface for direct use by arc4random? That
> wouldn't be a problem. I would not want this review to block arc4random.

I need to split the patch into manageable pieces anyway.

> One can create and destroy an infinite number of condition variables.

That's true.  But you cannot perform an arbitrary number of operations 
on a single condition variable.  Eventually, the sequence counter will 
overflow.  Which is why I think the comparison is still valid, as far as 
the implementation is concerned.

> The design of the pthread_thread_number_np API immediately limits the
> number of creatable threads to the size of the return type. If we allow
> creating more threads than that then we break the API.

> My objection is not with the internal implementation of a 64-bit counter.
> 
> My objection is to the external exposing of a limit on number of threads.

Well, the counterargument is that 2**64 is so large that by the time we 
have such machines which create as many threads within the life-time of 
a single process, we will have a new ABI (for off128_t) and can switch 
the return value to uint128_t.

The problem is that the 128-bit number actually *reduces* the usefulness 
of this interface because you cannot assume that a register-wide number 
confers uniqueness.  So using uint64_t here may not be entirely 
future-proof, but it will be good enough for currently-existing machines.

Current hardware can do around 200 million shared counter increments per 
second.  And that's just the counter, with single-threaded atomic 
increments.  As soon as multiple threads are involved, the performance 
drops.  Even if we assume a hundred-fold speed increase for the 
single-threaded case, we still end up with thirty years of run time 
until the wraparound happens.

I started to implement an alternative with two 64-bit counters in them, 
but to be honest, I don't think this interface has much value.

> The implementation can have an internal 64-bit limit, that's fine, but the
> external interface would then support an unlimited number of threads.
> 
> We can even provide a convenience function to turn the opaque value into
> an ASCII string, and such an implementation can just print a 64-bit value
> to the string buffer.
> 
> Would such an interface be truly terrible?

It would be pretty much useless for anything but logging.  Random bit 
stream generators typically need a fixed-size personalization string, 
and concurrency algorithms really need a register-sized thread number.

>> Lazy allocation would make the function not safe for use in signal handlers.
> 
> Are you going to mark this function as AS-safe in the documentation?
> 
> Yes, you used '@assafe{}' in the manual, OK.
> 
> Note that your '@acsafe{}' markup in the manual is wrong, since this function
> holds locks and is therefore not AS-safe.

The actual function doesn't use locking.  The only locking occurs during 
thread creation.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2017-12-20 14:34       ` Florian Weimer
@ 2017-12-20 17:58         ` Carlos O'Donell
  0 siblings, 0 replies; 28+ messages in thread
From: Carlos O'Donell @ 2017-12-20 17:58 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha

On 12/20/2017 06:34 AM, Florian Weimer wrote:
>> The design of the pthread_thread_number_np API immediately limits the
>> number of creatable threads to the size of the return type. If we allow
>> creating more threads than that then we break the API.
> 
>> My objection is not with the internal implementation of a 64-bit counter.
>>
>> My objection is to the external exposing of a limit on number of threads.
> 
> Well, the counterargument is that 2**64 is so large that by the time
> we have such machines which create as many threads within the
> life-time of a single process, we will have a new ABI (for off128_t)
> and can switch the return value to uint128_t.

OK, so you argue that the uint64_t is temporary, and we will provide
larger types as the computing infrastructure changes, with the ability
to handle more unique thread creation events in the future?

I am happier with this line of reasoning. Let me review the patch again
with this in mind and make some suggestions.

-- 
Cheers,
Carlos.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2017-12-15  7:48   ` Florian Weimer
  2017-12-20  8:06     ` Carlos O'Donell
@ 2017-12-21  9:26     ` Carlos O'Donell
  2017-12-21 11:03       ` Florian Weimer
  2018-03-02 18:04     ` Rich Felker
  2 siblings, 1 reply; 28+ messages in thread
From: Carlos O'Donell @ 2017-12-21  9:26 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha

On 12/14/2017 11:47 PM, Florian Weimer wrote:
> Subject: [PATCH] nptl: Add pthread_thread_number_np function
> To: libc-alpha@sourceware.org

I am re-reviewing this v2 of the patch, and in light of our discussion
downstream in this same thread. The intent is not to create an artificial
limit on the number of threads, but to provide vitally useful functions
for logging and uniquely identifying threads.

It is currently accepted, by both yourself, and Andrew Pinski, that the
64-bit thread identifier is large enough that no such overflow would be
probable within the lifetime of the hardware this code would run upon.
Even then we might extend this to 128-bit at a future date, which would
last until the sun burned out (unless we get massive parallelism, but
by then I hope pthreads is not be the interface in use)

I also understand that using a default of 128-bit, which would certainly
be future-proof, would be less useful because the type is harder to
manipulate efficiently, and makes the interface less useful.

We need a v3.

- See my suggestions for the manual.
- See my questions about preventing user abuse of monotonically increasing
  values from 1 for purposes we do not intend.

> 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-14  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/pthread.h (pthread_thread_number_np): Declare.
> 	* sysdeps/unix/sysv/linux/libc**.abilist: Update.
> 
> diff --git a/NEWS b/NEWS
> index c5607c855f..257b252a63 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -46,7 +46,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.

OK.

>  
>  * 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 00138eb43a..af81cba12c 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 ();

OK.

>  
>    /* Update the executable's link map with enough information to make
>       the TLS routines happy.  */
> diff --git a/elf/Makefile b/elf/Makefile
> index 8563555079..66ce2953a4 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -30,7 +30,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 \

OK.

>  				  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)
> +{
> +}

OK.

> diff --git a/elf/rtld.c b/elf/rtld.c
> index cfd3729b8e..214e2312fa 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 ();

OK.

>    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.

OK.

>  @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.

I would like us to add something like this:
~~~
While the return type of this function is only 64-bits wide, the intent
is not to impose an artificial limit on the number of threads that can be
created by the runtime. In the future this interface may be extended
to 128-bits to support creating as many threads as a user may need
for the lifetime of the process.
~~~

That way the intent of the interface and future changes are clear.

I figure it's implied that this function cannot fail because it has no
error code, and therefore any internal failure aborts the process, as
you added with the assert.

> +@end deftypefun
> +
>  @c FIXME these are undocumented:
>  @c pthread_atfork
>  @c pthread_attr_destroy
> diff --git a/nptl/Makefile b/nptl/Makefile
> index ae388d1112..087fb6a8b5 100644
> --- a/nptl/Makefile
> +++ b/nptl/Makefile
> @@ -30,7 +30,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

OK.

>  shared-only-routines = forward
>  
>  # We need to provide certain routines for compatibility with existing
> @@ -302,7 +302,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 \

OK.

>  
>  tests-internal := tst-rwlock19 tst-rwlock20 \
>  		  tst-sem11 tst-sem12 tst-sem13 \
> @@ -318,7 +319,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 \
> @@ -433,9 +436,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 \

OK.

> +
>  tests += tst-cancel21-static tst-cancel24-static \
> -	 tst-cond8-static
> +  tst-cond8-static tst-thread_number-single-static \
> +  tst-thread_number-multi-static \
> +

OK.

>  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;
> +  }

OK. Typo fixed.

>    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.  */

OK.

> +    static uint64_t global_thread_number = 1;
> +    thread_number = ++global_thread_number;

Alright, here comes serious worry #1.

If we say "Thread numbers are not necessarily assigned in a consecutive fashion.",
and we assign them in a consecutive fashion, users will ignore this statement
and use what empirically appears to be true.

People start relying on this counter incrementing from 1 upwards.

People start using this monotonic property for indexing.

Soon we can't change it because it's implied API behaviour.

I think we should disabuse them from doing something low cost to roll the value:

* Do nothing for thread 1, leaving it 1.
* Check global_thread_number for overflow instead.
* Pick a random number of bits to roll between 0-63 (picked at process startup)
* Roll the value by some that number of bits.
* Use the rolled value as the thread_number

Alternatively just pick __GLIBC_MINOR__ as the number of bits 
to roll so this changes with each major release.

> +
> +    /* 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");

OK. Perfect, overflow has defined fatal behaviour. This is good.

> +
> +    /* 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);

OK.

>  
>    /* 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;

OK.

> +
>    /* We place the thread descriptor at the end of the stack.  */
>    *pdp = pd;
>  
> diff --git a/nptl/descr.h b/nptl/descr.h
> index c83b17b674..49e266139e 100644
> --- a/nptl/descr.h
> +++ b/nptl/descr.h
> @@ -395,6 +395,9 @@ struct pthread
>    /* Resolver state.  */
>    struct __res_state res;
>  
> +  /* Unique number assigned to this thread.  */
> +  uint64_t number;

OK.

> +
>    /* 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..a9fdaa508b
> --- /dev/null
> +++ b/nptl/thread_number.c
> @@ -0,0 +1,26 @@
> +/* 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"
> +
> +__uint64_t
> +pthread_thread_number_np (pthread_t threadid)
> +{
> +  struct pthread *pd = (struct pthread *) threadid;
> +  return pd->number;
> +}

OK.

> 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"

OK.

> 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);
> +}

OK.

> +
> +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);

OK.

> +      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]);

OK.

> +
> +  /* Main thread ID should remain at 1.  */
> +  TEST_COMPARE (pthread_thread_number_np (pthread_self ()), 1U);
> +  support_isolate_in_subprocess (subprocess, NULL);

OK.

> +
> +  /* 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"

OK.

> 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 7a65dc641c..99f2e58875 100644
> --- a/sysdeps/generic/ldsodefs.h
> +++ b/sysdeps/generic/ldsodefs.h
> @@ -1056,6 +1056,10 @@ void __libc_setup_tls (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;

OK.

> +
>  /* 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/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;
> +}

OK.

> diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h
> index 2b2b386ab3..e0714ed951 100644
> --- a/sysdeps/nptl/pthread.h
> +++ b/sysdeps/nptl/pthread.h
> @@ -1148,6 +1148,10 @@ extern int pthread_atfork (void (*__prepare) (void),
>  			   void (*__child) (void)) __THROW;
>  
>  
> +/* Return a number uniquely identifying THREAD, even after its
> +   termination.  */
> +__uint64_t pthread_thread_number_np (pthread_t __thread_id) __THROW;
> +

OK.

>  #ifdef __USE_EXTERN_INLINES
>  /* Optimizations.  */
>  __extern_inline int
> diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> index ec0ead15dd..e9ba69cd43 100644
> --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> @@ -2113,6 +2113,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 5355769974..71258b014b 100644
> --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
> @@ -2024,6 +2024,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 9bafe71b51..df5eb357f8 100644
> --- a/sysdeps/unix/sysv/linux/arm/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
> @@ -114,6 +114,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 90aa8d034f..3c37cf48ec 100644
> --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
> @@ -1878,6 +1878,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/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
> index 4d44c30c64..aba40e2119 100644
> --- a/sysdeps/unix/sysv/linux/i386/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
> @@ -2043,6 +2043,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 112fc57634..6ef38f5150 100644
> --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
> @@ -1907,6 +1907,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 2e8b6a4586..63cda3a92e 100644
> --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/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/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> index 3c33400f67..4b0d923e1c 100644
> --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> @@ -1992,6 +1992,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 e1b1a579d2..68c927f54e 100644
> --- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> @@ -2113,6 +2113,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 c1550323f3..71f3785cdd 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> @@ -1967,6 +1967,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 3b3a172e4f..09d7344ce9 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> @@ -1965,6 +1965,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 101ca7a241..fea609bd3a 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> @@ -1963,6 +1963,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 2d129f7170..3cd9e072a3 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> @@ -1958,6 +1958,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 8bc350aff8..b8b2941999 100644
> --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
> @@ -2154,6 +2154,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 127c426e1c..60f5c63cc9 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> @@ -1996,6 +1996,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 a9411318e2..f538a91cb2 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> @@ -2001,6 +2001,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 d7bf5db601..f83d43c8cb 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
> @@ -2208,6 +2208,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 a3415a72ac..e61ce85a68 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/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/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> index 414338f9a2..ae74cb8184 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> @@ -1996,6 +1996,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 f0f7a69b64..fffbcb3d3e 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> @@ -1897,6 +1897,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 9f95aba898..cb8eb05b2e 100644
> --- a/sysdeps/unix/sysv/linux/sh/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
> @@ -1882,6 +1882,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 83fbdf2d7e..4184dcff17 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> @@ -1989,6 +1989,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 ee84ad10bc..cb9a0ae97f 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> @@ -1926,6 +1926,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/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
> index dcbfbc05ac..c305690b5a 100644
> --- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
> @@ -2120,6 +2120,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/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
> index 53dc99c45a..be6507ee22 100644
> --- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
> @@ -2120,6 +2120,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/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
> index dcbfbc05ac..c305690b5a 100644
> --- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
> @@ -2120,6 +2120,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 ae4dcaa47e..f418549369 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> @@ -1884,6 +1884,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 0dbda14796..6bc513a7ed 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> @@ -2127,6 +2127,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

OK.

-- 
Cheers,
Carlos.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2017-12-21  9:26     ` Carlos O'Donell
@ 2017-12-21 11:03       ` Florian Weimer
  2017-12-21 19:19         ` Carlos O'Donell
  0 siblings, 1 reply; 28+ messages in thread
From: Florian Weimer @ 2017-12-21 11:03 UTC (permalink / raw)
  To: Carlos O'Donell; +Cc: libc-alpha

On 12/21/2017 10:26 AM, Carlos O'Donell wrote:

>> +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.
> 
> I would like us to add something like this:
> ~~~
> While the return type of this function is only 64-bits wide, the intent
> is not to impose an artificial limit on the number of threads that can be
> created by the runtime. In the future this interface may be extended
> to 128-bits to support creating as many threads as a user may need
> for the lifetime of the process.
> ~~~
> 
> That way the intent of the interface and future changes are clear.

So how would a programmer use this interface in a future-proof way?  I 
think such a statement would raise more questions than it answers.

>> 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.  */
> 
> OK.
> 
>> +    static uint64_t global_thread_number = 1;
>> +    thread_number = ++global_thread_number;
> 
> Alright, here comes serious worry #1.
> 
> If we say "Thread numbers are not necessarily assigned in a consecutive fashion.",
> and we assign them in a consecutive fashion, users will ignore this statement
> and use what empirically appears to be true.

The above does not actually assign thread numbers in a consecutive 
fashion, from an application perspective because the implementation can 
create its own threads for its own internal use.  (librt and libanl do 
this.)

> People start relying on this counter incrementing from 1 upwards.
> 
> People start using this monotonic property for indexing.
> 
> Soon we can't change it because it's implied API behaviour.
> 
> I think we should disabuse them from doing something low cost to roll the value:
> 
> * Do nothing for thread 1, leaving it 1.
> * Check global_thread_number for overflow instead.
> * Pick a random number of bits to roll between 0-63 (picked at process startup)
> * Roll the value by some that number of bits.
> * Use the rolled value as the thread_number

Not sure if I understand this.  Do you want us to start at a random 
value?  Or assign IDs randomly?  The latter will have a collision much 
sooner.

I can switch the thread numbers to a fixed, but random-looking 
permutation of the integers in [0, 2**64), but this looks excessive.

In my opinion, we need to assume at one point that programmers read the 
documentation.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2017-12-21 11:03       ` Florian Weimer
@ 2017-12-21 19:19         ` Carlos O'Donell
  2017-12-22 16:25           ` Florian Weimer
  0 siblings, 1 reply; 28+ messages in thread
From: Carlos O'Donell @ 2017-12-21 19:19 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha

On 12/21/2017 03:03 AM, Florian Weimer wrote:
> On 12/21/2017 10:26 AM, Carlos O'Donell wrote:
> 
>>> +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.
>>
>> I would like us to add something like this:
>> ~~~
>> While the return type of this function is only 64-bits wide, the intent
>> is not to impose an artificial limit on the number of threads that can be
>> created by the runtime. In the future this interface may be extended
>> to 128-bits to support creating as many threads as a user may need
>> for the lifetime of the process.
>> ~~~
>>
>> That way the intent of the interface and future changes are clear.
> 
> So how would a programmer use this interface in a future-proof way?
> I think such a statement would raise more questions than it answers.

I went to bed thinking much the same thing and worried that perhaps this
text was not appropriate for the manual, but could serve as a comment in
the source code for future maintainers. Since this is really a question
about GNU ethos and avoiding artificial limits.

Would you be opposed to adding the comment to the new function sources?

>>> 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.  */
>>
>> OK.
>>
>>> +    static uint64_t global_thread_number = 1;
>>> +    thread_number = ++global_thread_number;
>>
>> Alright, here comes serious worry #1.
>>
>> If we say "Thread numbers are not necessarily assigned in a consecutive fashion.",
>> and we assign them in a consecutive fashion, users will ignore this statement
>> and use what empirically appears to be true.
> 
> The above does not actually assign thread numbers in a consecutive
> fashion, from an application perspective because the implementation
> can create its own threads for its own internal use.  (librt and
> libanl do this.)

That's a good point.

I know that aio has a helper thraed, so does the notification, so does some
of the related timer routines.

All of those would help break this notion, but these are also rarer features.
 
>> People start relying on this counter incrementing from 1 upwards.
>>
>> People start using this monotonic property for indexing.
>>
>> Soon we can't change it because it's implied API behaviour.
>>
>> I think we should disabuse them from doing something low cost to roll the value:
>>
>> * Do nothing for thread 1, leaving it 1.
>> * Check global_thread_number for overflow instead.
>> * Pick a random number of bits to roll between 0-63 (picked at process startup)
>> * Roll the value by some that number of bits.
>> * Use the rolled value as the thread_number
> 
> Not sure if I understand this.  Do you want us to start at a random
> value?  Or assign IDs randomly?  The latter will have a collision
> much sooner.
> 
> I can switch the thread numbers to a fixed, but random-looking
> permutation of the integers in [0, 2**64), but this looks excessive.

I want a low cost solution that avoids abuses of the interface for
indexing into arrays, or other issues that would break when we change
this in the future. We do not want users to make assumptions about the
values we hand out.

The lowest cost option I can think of is to circular shift the global
counter value by some number of bits.

I don't care for it to be random.

> In my opinion, we need to assume at one point that programmers read
> the documentation.

The implementation should be robust against abuse. That's what makes
it high quality.

-- 
Cheers,
Carlos.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2017-12-21 19:19         ` Carlos O'Donell
@ 2017-12-22 16:25           ` Florian Weimer
  2017-12-22 17:09             ` Carlos O'Donell
  0 siblings, 1 reply; 28+ messages in thread
From: Florian Weimer @ 2017-12-22 16:25 UTC (permalink / raw)
  To: Carlos O'Donell; +Cc: libc-alpha

On 12/21/2017 08:19 PM, Carlos O'Donell wrote:
> On 12/21/2017 03:03 AM, Florian Weimer wrote:
>> On 12/21/2017 10:26 AM, Carlos O'Donell wrote:
>>
>>>> +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.
>>>
>>> I would like us to add something like this:
>>> ~~~
>>> While the return type of this function is only 64-bits wide, the intent
>>> is not to impose an artificial limit on the number of threads that can be
>>> created by the runtime. In the future this interface may be extended
>>> to 128-bits to support creating as many threads as a user may need
>>> for the lifetime of the process.
>>> ~~~
>>>
>>> That way the intent of the interface and future changes are clear.
>>
>> So how would a programmer use this interface in a future-proof way?
>> I think such a statement would raise more questions than it answers.
> 
> I went to bed thinking much the same thing and worried that perhaps this
> text was not appropriate for the manual, but could serve as a comment in
> the source code for future maintainers. Since this is really a question
> about GNU ethos and avoiding artificial limits.
> 
> Would you be opposed to adding the comment to the new function sources?

What about this?

/* 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.  */

>>> People start relying on this counter incrementing from 1 upwards.
>>>
>>> People start using this monotonic property for indexing.
>>>
>>> Soon we can't change it because it's implied API behaviour.
>>>
>>> I think we should disabuse them from doing something low cost to roll the value:
>>>
>>> * Do nothing for thread 1, leaving it 1.
>>> * Check global_thread_number for overflow instead.
>>> * Pick a random number of bits to roll between 0-63 (picked at process startup)
>>> * Roll the value by some that number of bits.
>>> * Use the rolled value as the thread_number
>>
>> Not sure if I understand this.  Do you want us to start at a random
>> value?  Or assign IDs randomly?  The latter will have a collision
>> much sooner.
>>
>> I can switch the thread numbers to a fixed, but random-looking
>> permutation of the integers in [0, 2**64), but this looks excessive.
> 
> I want a low cost solution that avoids abuses of the interface for
> indexing into arrays, or other issues that would break when we change
> this in the future. We do not want users to make assumptions about the
> values we hand out.

But the result will be that the numbers are no longer short and easily 
compared for logging/debugging purposes.  I think the value of that is 
higher than trying to punish developers who do not read the manual.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2017-12-22 16:25           ` Florian Weimer
@ 2017-12-22 17:09             ` Carlos O'Donell
  2017-12-22 17:43               ` Joseph Myers
  0 siblings, 1 reply; 28+ messages in thread
From: Carlos O'Donell @ 2017-12-22 17:09 UTC (permalink / raw)
  To: Florian Weimer, Siddhesh Poyarekar; +Cc: libc-alpha

On 12/22/2017 08:24 AM, Florian Weimer wrote:
> On 12/21/2017 08:19 PM, Carlos O'Donell wrote:
>> On 12/21/2017 03:03 AM, Florian Weimer wrote:
>>> On 12/21/2017 10:26 AM, Carlos O'Donell wrote:
>>>
>>>>> +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.
>>>>
>>>> I would like us to add something like this:
>>>> ~~~
>>>> While the return type of this function is only 64-bits wide, the intent
>>>> is not to impose an artificial limit on the number of threads that can be
>>>> created by the runtime. In the future this interface may be extended
>>>> to 128-bits to support creating as many threads as a user may need
>>>> for the lifetime of the process.
>>>> ~~~
>>>>
>>>> That way the intent of the interface and future changes are clear.
>>>
>>> So how would a programmer use this interface in a future-proof way?
>>> I think such a statement would raise more questions than it answers.
>>
>> I went to bed thinking much the same thing and worried that perhaps this
>> text was not appropriate for the manual, but could serve as a comment in
>> the source code for future maintainers. Since this is really a question
>> about GNU ethos and avoiding artificial limits.
>>
>> Would you be opposed to adding the comment to the new function sources?
> 
> What about this?
> 
> /* 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.  */

This looks good to me. Thanks.

>>>> People start relying on this counter incrementing from 1 upwards.
>>>>
>>>> People start using this monotonic property for indexing.
>>>>
>>>> Soon we can't change it because it's implied API behaviour.
>>>>
>>>> I think we should disabuse them from doing something low cost to roll the value:
>>>>
>>>> * Do nothing for thread 1, leaving it 1.
>>>> * Check global_thread_number for overflow instead.
>>>> * Pick a random number of bits to roll between 0-63 (picked at process startup)
>>>> * Roll the value by some that number of bits.
>>>> * Use the rolled value as the thread_number
>>>
>>> Not sure if I understand this.  Do you want us to start at a random
>>> value?  Or assign IDs randomly?  The latter will have a collision
>>> much sooner.
>>>
>>> I can switch the thread numbers to a fixed, but random-looking
>>> permutation of the integers in [0, 2**64), but this looks excessive.
>>
>> I want a low cost solution that avoids abuses of the interface for
>> indexing into arrays, or other issues that would break when we change
>> this in the future. We do not want users to make assumptions about the
>> values we hand out.
> 
> But the result will be that the numbers are no longer short and
> easily compared for logging/debugging purposes.  I think the value of
> that is higher than trying to punish developers who do not read the
> manual.

The numbers are meaningless and should be handled by computers, and
compared by log analyzers, just like how PIDs today are meaningless
and not that small. Even PIDs in logs are large enough that I can't
easily remember them, though I agree that 34519 vs. 431234789734231
is really a big difference.

My objection remains that I think we should have some kind of
perturbation logic in the number generation, but my objection is
*not* sustained.

I do not block consensus, perturbation can continue to be discussed
and applied at a later point. Therefore between you and I there is
consensus that this patch looks good for addition as a new POSIX
thread API.

Please place your patches on the "Release blockers" for this release:
https://sourceware.org/glibc/wiki/Release/2.27#Release_blockers.3F,
so we get them checked in fully.

I say this because I want someone else other than me to ACK these
before we consider the new API OK. I'm hesitant to pursue a model
where we add new APIs without at least two senior reivewer's
consent. I would like Siddhesh to just look over the idea, and give
a +1 to the new API, knowing that I have reviewed the technical
details I want a high-level acceptance of the direction the API
is going. Siddhesh was the last to add a new POSIX thread API with
the default thread attribute settings API being his invention.

Siddhesh, Could you review the high-level details of the new API?

-- 
Cheers,
Carlos.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2017-12-22 17:09             ` Carlos O'Donell
@ 2017-12-22 17:43               ` Joseph Myers
  2017-12-22 19:39                 ` Florian Weimer
  0 siblings, 1 reply; 28+ messages in thread
From: Joseph Myers @ 2017-12-22 17:43 UTC (permalink / raw)
  To: Carlos O'Donell; +Cc: Florian Weimer, Siddhesh Poyarekar, libc-alpha

[-- Attachment #1: Type: text/plain, Size: 1417 bytes --]

On Fri, 22 Dec 2017, Carlos O'Donell wrote:

> > /* 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.  */
> 
> This looks good to me. Thanks.

I wonder about representing the intent to allow for a larger type by 
defining and documenting the API to use a pthread_thread_number_t type 
rather than uint64_t.

However, if pthread_thread_number_t is to be conveniently usable, it 
should be specified to be an unsigned integer type, meaning no wider than 
uintmax_t (so you can cast to uintmax_t to print with %ju, for example), 
meaning it can't be unsigned __int128 for any existing glibc ABI as all 
such ABIs have 64-bit uintmax_t.

As with any patch changing the installed pthread.h, the separate hppa 
version of that header needs the same change applied.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2017-12-22 17:43               ` Joseph Myers
@ 2017-12-22 19:39                 ` Florian Weimer
  2017-12-22 20:02                   ` Joseph Myers
  0 siblings, 1 reply; 28+ messages in thread
From: Florian Weimer @ 2017-12-22 19:39 UTC (permalink / raw)
  To: Joseph Myers, Carlos O'Donell; +Cc: Siddhesh Poyarekar, libc-alpha

[-- Attachment #1: Type: text/plain, Size: 1793 bytes --]

On 12/22/2017 06:43 PM, Joseph Myers wrote:
> On Fri, 22 Dec 2017, Carlos O'Donell wrote:
> 
>>> /* 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.  */
>>
>> This looks good to me. Thanks.
> 
> I wonder about representing the intent to allow for a larger type by
> defining and documenting the API to use a pthread_thread_number_t type
> rather than uint64_t.
> 
> However, if pthread_thread_number_t is to be conveniently usable, it
> should be specified to be an unsigned integer type, meaning no wider than
> uintmax_t (so you can cast to uintmax_t to print with %ju, for example),
> meaning it can't be unsigned __int128 for any existing glibc ABI as all
> such ABIs have 64-bit uintmax_t.

Yes, I considered using a different type, but it really has to be a 
fixed type anyway so that the format specifiers work.  That's why I went 
with uint64_t in the end.

> As with any patch changing the installed pthread.h, the separate hppa
> version of that header needs the same change applied.

In the attached patch, I added <bits/pthread-common.h> to simplify this. 
  I verified that it is installed as 
$(DESTDIR)/usr/include/bits/pthread-common.h.

Thanks,
Florian

[-- Attachment #2: thread-number-common.patch --]
[-- Type: text/x-patch, Size: 37547 bytes --]

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

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2017-12-22 19:39                 ` Florian Weimer
@ 2017-12-22 20:02                   ` Joseph Myers
  2017-12-22 22:11                     ` Florian Weimer
  0 siblings, 1 reply; 28+ messages in thread
From: Joseph Myers @ 2017-12-22 20:02 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Carlos O'Donell, Siddhesh Poyarekar, libc-alpha

On Fri, 22 Dec 2017, Florian Weimer wrote:

> > As with any patch changing the installed pthread.h, the separate hppa
> > version of that header needs the same change applied.
> 
> In the attached patch, I added <bits/pthread-common.h> to simplify this.  I
> verified that it is installed as $(DESTDIR)/usr/include/bits/pthread-common.h.

Since almost everything in pthread.h is common, I don't think it makes 
sense to have bits/pthread-common.h just for this one declaration.  
Rather, I think there should be e.g. bits/pthread-initializers.h, for 
which hppa would have a different version.

(If at some point Hurd libpthread gets merged in, it may be desirable to 
share as much as possible of the installed header declaring the API, and 
the testcases, between the two pthreads implementations, but for now it 
would be premature to try to distinguish between headers/tests for glibc 
pthreads and those specifically for the NPTL implementation thereof; Hurd 
people would need to take the lead on such refactoring at an appropriate 
point.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2017-12-22 20:02                   ` Joseph Myers
@ 2017-12-22 22:11                     ` Florian Weimer
  0 siblings, 0 replies; 28+ messages in thread
From: Florian Weimer @ 2017-12-22 22:11 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Carlos O'Donell, Siddhesh Poyarekar, libc-alpha

[-- Attachment #1: Type: text/plain, Size: 1154 bytes --]

On 12/22/2017 09:02 PM, Joseph Myers wrote:
> On Fri, 22 Dec 2017, Florian Weimer wrote:
> 
>>> As with any patch changing the installed pthread.h, the separate hppa
>>> version of that header needs the same change applied.
>>
>> In the attached patch, I added <bits/pthread-common.h> to simplify this.  I
>> verified that it is installed as $(DESTDIR)/usr/include/bits/pthread-common.h.
> 
> Since almost everything in pthread.h is common, I don't think it makes
> sense to have bits/pthread-common.h just for this one declaration.
> Rather, I think there should be e.g. bits/pthread-initializers.h, for
> which hppa would have a different version.
> 
> (If at some point Hurd libpthread gets merged in, it may be desirable to
> share as much as possible of the installed header declaring the API, and
> the testcases, between the two pthreads implementations, but for now it
> would be premature to try to distinguish between headers/tests for glibc
> pthreads and those specifically for the NPTL implementation thereof; Hurd
> people would need to take the lead on such refactoring at an appropriate
> point.)

Okay, so this instead?

Thanks,
Florian

[-- Attachment #2: thread-number-hppa.patch --]
[-- Type: text/x-patch, Size: 36059 bytes --]

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/pthread.h (pthread_thread_number_np): Declare.
	* sysdeps/unix/sysv/linux/hppa/pthread.h (pthread_thread_number_np):
	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/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..c45b518c5d 100644
--- a/sysdeps/nptl/pthread.h
+++ b/sysdeps/nptl/pthread.h
@@ -1145,6 +1145,10 @@ extern int pthread_atfork (void (*__prepare) (void),
 			   void (*__child) (void)) __THROW;
 
 
+/* Return a number uniquely identifying THREAD, even after its
+   termination.  */
+__uint64_t pthread_thread_number_np (pthread_t __thread_id) __THROW;
+
 #ifdef __USE_EXTERN_INLINES
 /* Optimizations.  */
 __extern_inline int
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..cd2addef88 100644
--- a/sysdeps/unix/sysv/linux/hppa/pthread.h
+++ b/sysdeps/unix/sysv/linux/hppa/pthread.h
@@ -1120,6 +1120,9 @@ extern int pthread_atfork (void (*__prepare) (void),
 			   void (*__parent) (void),
 			   void (*__child) (void)) __THROW;
 
+/* Return a number uniquely identifying THREAD, even after its
+   termination.  */
+__uint64_t pthread_thread_number_np (pthread_t __thread_id) __THROW;
 
 #ifdef __USE_EXTERN_INLINES
 /* Optimizations.  */
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

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2017-12-15  7:48   ` Florian Weimer
  2017-12-20  8:06     ` Carlos O'Donell
  2017-12-21  9:26     ` Carlos O'Donell
@ 2018-03-02 18:04     ` Rich Felker
  2018-03-02 18:08       ` Rich Felker
  2 siblings, 1 reply; 28+ messages in thread
From: Rich Felker @ 2018-03-02 18:04 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Carlos O'Donell, libc-alpha

On Fri, Dec 15, 2017 at 08:47:54AM +0100, Florian Weimer wrote:
> >We could allocate the thread numbers lazily, and that would certainly
> >avoid limiting ourselves to only allocating 2^64-1 threads. On top of
> >that if the function could return an error then we could return such
> >an error at overflow:
> >
> >  int pthread_thread_number_np (uint64_t* thread_number, pthread_t @var{thread})
> >
> >Returns 0 if the thread has a unique number, otherwise -1 if it does not.
> 
> That's a bad interface.  If you are worried about 64-bit overflow,
> we should use a 128-bit counter instead, but I'm not convinced this
> is necessary.
> 
> Lazy allocation would make the function not safe for use in signal handlers.

This is trivially false. You just have to block and restore signal
mask around taking and releasing the lock to make it AS-safe.

I'm also rather unhappy with an API whose external interface is an
assumption that you can never create more than 2^64 threads, even
though from a practical standpoint is seems impossible for the
forseeable future. Just documenting a special return value
(UINT64_MAX? 0?) that means the result was not meaningful would be a
decent fix, given that this whole interface is of dubious utility..

Rich

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2018-03-02 18:04     ` Rich Felker
@ 2018-03-02 18:08       ` Rich Felker
  2018-03-09 17:23         ` Florian Weimer
  0 siblings, 1 reply; 28+ messages in thread
From: Rich Felker @ 2018-03-02 18:08 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Carlos O'Donell, libc-alpha

On Fri, Mar 02, 2018 at 01:04:16PM -0500, Rich Felker wrote:
> On Fri, Dec 15, 2017 at 08:47:54AM +0100, Florian Weimer wrote:
> > >We could allocate the thread numbers lazily, and that would certainly
> > >avoid limiting ourselves to only allocating 2^64-1 threads. On top of
> > >that if the function could return an error then we could return such
> > >an error at overflow:
> > >
> > >  int pthread_thread_number_np (uint64_t* thread_number, pthread_t @var{thread})
> > >
> > >Returns 0 if the thread has a unique number, otherwise -1 if it does not.
> > 
> > That's a bad interface.  If you are worried about 64-bit overflow,
> > we should use a 128-bit counter instead, but I'm not convinced this
> > is necessary.
> > 
> > Lazy allocation would make the function not safe for use in signal handlers.
> 
> This is trivially false. You just have to block and restore signal
> mask around taking and releasing the lock to make it AS-safe.
> 
> I'm also rather unhappy with an API whose external interface is an
> assumption that you can never create more than 2^64 threads, even
> though from a practical standpoint is seems impossible for the
> forseeable future. Just documenting a special return value
> (UINT64_MAX? 0?) that means the result was not meaningful would be a
> decent fix, given that this whole interface is of dubious utility..

Further, making it lazy also improves the latter aspect if you're
unwilling to make a dedicated "failure" value. "Libc has to abort if
you ever create more than 2^64 threads" is an awful constraint to be
tied to. "Libc aborts if you ever call this random nonstandard
function from more than 2^64 unique threads" seems tolerable since the
simple mitigation is "don't use that function".

Rich

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2018-03-02 18:08       ` Rich Felker
@ 2018-03-09 17:23         ` Florian Weimer
  2018-03-09 23:29           ` Carlos O'Donell
  0 siblings, 1 reply; 28+ messages in thread
From: Florian Weimer @ 2018-03-09 17:23 UTC (permalink / raw)
  To: Rich Felker; +Cc: Carlos O'Donell, libc-alpha

On 03/02/2018 07:08 PM, Rich Felker wrote:
> Further, making it lazy also improves the latter aspect if you're
> unwilling to make a dedicated "failure" value. "Libc has to abort if
> you ever create more than 2^64 threads" is an awful constraint to be
> tied to. "Libc aborts if you ever call this random nonstandard
> function from more than 2^64 unique threads" seems tolerable since the
> simple mitigation is "don't use that function".

Currently glibc policy is to assume that 2**60 counters never overflow 
(without any checks).  We have functionality which underwent extensive 
peer review with this property.

However, I will come up with something else since there appears to be a 
strong dislike for this interface.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2018-03-09 17:23         ` Florian Weimer
@ 2018-03-09 23:29           ` Carlos O'Donell
  0 siblings, 0 replies; 28+ messages in thread
From: Carlos O'Donell @ 2018-03-09 23:29 UTC (permalink / raw)
  To: Florian Weimer, Rich Felker; +Cc: libc-alpha

On 03/09/2018 11:23 AM, Florian Weimer wrote:
> On 03/02/2018 07:08 PM, Rich Felker wrote:
>> Further, making it lazy also improves the latter aspect if you're 
>> unwilling to make a dedicated "failure" value. "Libc has to abort
>> if you ever create more than 2^64 threads" is an awful constraint
>> to be tied to. "Libc aborts if you ever call this random
>> nonstandard function from more than 2^64 unique threads" seems
>> tolerable since the simple mitigation is "don't use that
>> function".
> 
> Currently glibc policy is to assume that 2**60 counters never
> overflow (without any checks).  We have functionality which underwent
> extensive peer review with this property.

They were internal hidden API details though?

Like pthread cond signal groups, and fork counters.
 
> However, I will come up with something else since there appears to be
> a strong dislike for this interface.

Either lazy allocation, or a dedicated overflow value are both useful
improvements to a "thread identification" API that has inherent limits
on the size of the identification name space (64-bits).

I don't object because we have lots of space-limited objects like inodes,
etc, and all we've done is make new APIs with wider width types to
resolve these problems.

Cheers,
Carlos.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2018-03-02 17:16 ` Joseph Myers
@ 2018-05-15 13:42   ` Florian Weimer
  0 siblings, 0 replies; 28+ messages in thread
From: Florian Weimer @ 2018-05-15 13:42 UTC (permalink / raw)
  To: Joseph Myers; +Cc: libc-alpha

On 03/02/2018 06:16 PM, Joseph Myers wrote:
> On Fri, 2 Mar 2018, Florian Weimer wrote:
> 
>> diff --git a/NEWS b/NEWS
>> index 60dd2f778d..259b33a829 100644
>> --- a/NEWS
>> +++ b/NEWS
>> @@ -104,7 +104,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.
> 
> This is the 2.27 section of NEWS.  You need to update the 2.28 section
> instead.

Thanks, fixed locally.  But I don't intend to submit this patch again 
for now.

Florian

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] nptl: Add pthread_thread_number_np function
  2018-03-02 14:42 Florian Weimer
@ 2018-03-02 17:16 ` Joseph Myers
  2018-05-15 13:42   ` Florian Weimer
  0 siblings, 1 reply; 28+ messages in thread
From: Joseph Myers @ 2018-03-02 17:16 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha

On Fri, 2 Mar 2018, Florian Weimer wrote:

> diff --git a/NEWS b/NEWS
> index 60dd2f778d..259b33a829 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -104,7 +104,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.

This is the 2.27 section of NEWS.  You need to update the 2.28 section 
instead.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH] nptl: Add pthread_thread_number_np function
@ 2018-03-02 14:42 Florian Weimer
  2018-03-02 17:16 ` Joseph Myers
  0 siblings, 1 reply; 28+ messages in thread
From: Florian Weimer @ 2018-03-02 14:42 UTC (permalink / raw)
  To: libc-alpha

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.

2018-03-02  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.28): 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/pthread.h (pthread_thread_number_np): Declare.
	* sysdeps/unix/sysv/linux/hppa/pthread.h (pthread_thread_number_np):
	Likewise.
	* sysdeps/unix/sysv/linux/libc**.abilist: Update.

diff --git a/NEWS b/NEWS
index 60dd2f778d..259b33a829 100644
--- a/NEWS
+++ b/NEWS
@@ -104,7 +104,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 28a79441cd..dd8378c5cc 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 9bdb9220c7..23fcbbd826 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 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 f8d9597cdd..a361099c40 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -739,6 +739,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 94be92c789..8b71a087f1 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -29,7 +29,7 @@ extra-libs-others := $(extra-libs)
 
 routines = alloca_cutoff forward libc-lowlevellock libc-cancellation \
 	   libc-cleanup libc_pthread_init libc_multiple_threads \
-	   register-atfork pthread_atfork pthread_self
+	   register-atfork pthread_atfork pthread_self thread_number
 shared-only-routines = forward
 static-only-routines = pthread_atfork
 
@@ -308,7 +308,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
 	tst-thread_local1 tst-mutex-errorcheck tst-robust10 \
 	tst-robust-fork tst-create-detached tst-memstream \
 	tst-thread-exit-clobber tst-minstack-cancel tst-minstack-exit \
-	tst-minstack-throw
+	tst-minstack-throw tst-thread_number-single tst-thread_number-multi \
 
 tests-internal := tst-rwlock19 tst-rwlock20 \
 		  tst-sem11 tst-sem12 tst-sem13 \
@@ -324,7 +324,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 \
@@ -439,9 +441,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..6cb4f660a0 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.28 {
+    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 b374f4794d..08289c5878 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))
@@ -762,6 +774,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 64ba29e1cb..2b317a528a 100644
--- a/nptl/descr.h
+++ b/nptl/descr.h
@@ -395,6 +395,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 5e1b24ecb5..3d5e0160aa 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1070,6 +1070,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/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 df049abf74..80a350f673 100644
--- a/sysdeps/nptl/pthread.h
+++ b/sysdeps/nptl/pthread.h
@@ -1148,6 +1148,10 @@ extern int pthread_atfork (void (*__prepare) (void),
 			   void (*__child) (void)) __THROW;
 
 
+/* Return a number uniquely identifying THREAD, even after its
+   termination.  */
+__uint64_t pthread_thread_number_np (pthread_t __thread_id) __THROW;
+
 #ifdef __USE_EXTERN_INLINES
 /* Optimizations.  */
 __extern_inline int
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 90c9bc84e1..8d2e2167fc 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2139,3 +2139,5 @@ GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 8674a874b4..2972f79553 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2054,6 +2054,8 @@ GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index 044ec102c2..d05dd88b4c 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -130,6 +130,8 @@ GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 2360130abe..376db4715a 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -1894,6 +1894,8 @@ GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/hppa/pthread.h b/sysdeps/unix/sysv/linux/hppa/pthread.h
index 11a024db59..0933a74ecd 100644
--- a/sysdeps/unix/sysv/linux/hppa/pthread.h
+++ b/sysdeps/unix/sysv/linux/hppa/pthread.h
@@ -1123,6 +1123,9 @@ extern int pthread_atfork (void (*__prepare) (void),
 			   void (*__parent) (void),
 			   void (*__child) (void)) __THROW;
 
+/* Return a number uniquely identifying THREAD, even after its
+   termination.  */
+__uint64_t pthread_thread_number_np (pthread_t __thread_id) __THROW;
 
 #ifdef __USE_EXTERN_INLINES
 /* Optimizations.  */
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 39c993fd79..c3a929c4cf 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2064,6 +2064,8 @@ GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index 68496aa6ac..fa3feb9fb2 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1928,6 +1928,8 @@ GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index b676025261..91b3124b89 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -131,6 +131,8 @@ GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0x98
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index cdd1df55d0..6a681c0e87 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -2008,6 +2008,8 @@ GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index e4265fd74d..dbec79d1fc 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2129,3 +2129,5 @@ GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np 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..706b1ebd29 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1983,6 +1983,8 @@ GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc 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..a5025aba78 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1981,6 +1981,8 @@ GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc 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..be7c8a4460 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1989,6 +1989,8 @@ GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc 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..e67050422b 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1984,6 +1984,8 @@ GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index cc5885ab9b..02c772722e 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2170,3 +2170,5 @@ GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np 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..e260165495 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -2012,6 +2012,8 @@ GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc 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..2c4f7f586b 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -2017,6 +2017,8 @@ GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc 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..32d46fafad 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2229,3 +2229,5 @@ GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index c57ab21b82..f8b3374371 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -131,6 +131,8 @@ GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 _Exit F
 GLIBC_2.3 _IO_2_1_stderr_ D 0xe0
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
index 8ab44ec41f..b9c393fd72 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
@@ -2094,3 +2094,5 @@ GLIBC_2.27 xdrstdio_create F
 GLIBC_2.27 xencrypt F
 GLIBC_2.27 xprt_register F
 GLIBC_2.27 xprt_unregister F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np 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..354cffc89a 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -2022,6 +2022,8 @@ GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc 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..511ae64bcb 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1923,6 +1923,8 @@ GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index c04872ca7f..affe7519bf 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1898,6 +1898,8 @@ GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 85cbe308d6..0ac8fb7fff 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -2015,6 +2015,8 @@ GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index f7a1ab8edb..866d3b4f0b 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1952,6 +1952,8 @@ GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx32/libc.abilist
index ab56ecee44..d3b76a98c5 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx32/libc.abilist
@@ -2136,3 +2136,5 @@ GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx64/libc.abilist
index f2518c08ff..43f670d972 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx64/libc.abilist
@@ -2136,3 +2136,5 @@ GLIBC_2.27 wcstof32x F
 GLIBC_2.27 wcstof32x_l F
 GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np 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..fa53be4c07 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1905,6 +1905,8 @@ GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc 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..56d5118445 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2148,3 +2148,5 @@ GLIBC_2.27 wcstof64 F
 GLIBC_2.27 wcstof64_l F
 GLIBC_2.27 wcstof64x F
 GLIBC_2.27 wcstof64x_l F
+GLIBC_2.28 GLIBC_2.28 A
+GLIBC_2.28 pthread_thread_number_np F

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2018-05-15 13:42 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-14 18:56 [PATCH] nptl: Add pthread_thread_number_np function Florian Weimer
2017-12-14 20:24 ` Florian Weimer
2017-12-14 23:34 ` Nix
2017-12-15  6:41   ` Florian Weimer
2017-12-15  0:29 ` Andrew Pinski
2017-12-15  7:47   ` Florian Weimer
2017-12-15  7:54   ` Andrew Pinski
2017-12-15  4:08 ` Carlos O'Donell
2017-12-15  7:48   ` Florian Weimer
2017-12-20  8:06     ` Carlos O'Donell
2017-12-20 14:34       ` Florian Weimer
2017-12-20 17:58         ` Carlos O'Donell
2017-12-21  9:26     ` Carlos O'Donell
2017-12-21 11:03       ` Florian Weimer
2017-12-21 19:19         ` Carlos O'Donell
2017-12-22 16:25           ` Florian Weimer
2017-12-22 17:09             ` Carlos O'Donell
2017-12-22 17:43               ` Joseph Myers
2017-12-22 19:39                 ` Florian Weimer
2017-12-22 20:02                   ` Joseph Myers
2017-12-22 22:11                     ` Florian Weimer
2018-03-02 18:04     ` Rich Felker
2018-03-02 18:08       ` Rich Felker
2018-03-09 17:23         ` Florian Weimer
2018-03-09 23:29           ` Carlos O'Donell
2018-03-02 14:42 Florian Weimer
2018-03-02 17:16 ` Joseph Myers
2018-05-15 13:42   ` Florian Weimer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).