diff mbox series

Add pthread_getname_np and pthread_setname_np for Hurd

Message ID mh7drffxysrrqc2nnvtezuukevcdlf47277yjd3irx3fxugk2w@kfaxtdwjj7bd
State New
Headers show
Series Add pthread_getname_np and pthread_setname_np for Hurd | expand

Commit Message

Flavio Cruz July 10, 2024, 4:04 p.m. UTC
Some notable differences with Linux:
- We are not inheriting the program name.
- The name can be up to 64 chars (versus Linux's 16).

Also added a mach_RPC_CHECK to check for the existing of gnumach RPCs.
---
 config.h.in                                 |  3 +
 htl/Makefile                                |  2 +
 htl/Versions                                |  5 ++
 htl/pt-alloc.c                              |  3 +
 htl/pt-getname-np.c                         | 51 ++++++++++++++++
 htl/pt-internal.h                           |  4 ++
 sysdeps/htl/pthread.h                       | 11 ++++
 sysdeps/mach/configure                      | 46 ++++++++++++--
 sysdeps/mach/configure.ac                   | 27 ++++++---
 sysdeps/mach/htl/pt-setname-np.c            | 66 +++++++++++++++++++++
 sysdeps/mach/hurd/i386/libpthread.abilist   |  2 +
 sysdeps/mach/hurd/x86_64/libpthread.abilist |  2 +
 12 files changed, 209 insertions(+), 13 deletions(-)
 create mode 100644 htl/pt-getname-np.c
 create mode 100644 sysdeps/mach/htl/pt-setname-np.c

Comments

Sergey Bugaev July 10, 2024, 6:07 p.m. UTC | #1
Hi Flavio,

in general, what's this useful for? Debugging, maybe?

Do you expect the process itself to query its threads' names locally,
or do you expect another process (GDB) to issue thread_get_name
remotely?

On Wed, Jul 10, 2024 at 7:04 PM Flavio Cruz <flaviocruz@gmail.com> wrote:
> diff --git a/htl/pt-internal.h b/htl/pt-internal.h
> index 85a7d905..b6ccbe12 100644
> --- a/htl/pt-internal.h
> +++ b/htl/pt-internal.h
> @@ -105,6 +105,10 @@ struct __pthread
>    /* Initial sigset for the thread.  */
>    sigset_t init_sigset;
>
> +  /* Used to store the thread name through pthread_setname_np.  */
> +  pthread_mutex_t name_lock;

I see other members of struct __pthread are also using
pthread_mutex_t, but is there really a reason why we need that over a
simple libc_lock?

> +  char *thread_name;

Does it make sense to store the name locally? Could pthread_getname_np
call thread_get_name also, if we don't expect it to be a frequent
operation?

Not saying you shouldn't store the name, but let's think of the space
vs performance trade-off and document it.

If you do store it, you should make sure to free it in pt-dealloc.

> +
>    /* Thread context.  */
>    struct pthread_mcontext mcontext;
>
> diff --git a/sysdeps/htl/pthread.h b/sysdeps/htl/pthread.h
> index fa626ebc..cf42383f 100644
> --- a/sysdeps/htl/pthread.h
> +++ b/sysdeps/htl/pthread.h
> @@ -891,6 +891,17 @@ extern int pthread_setschedparam (pthread_t __thr, int __policy,
>  /* Set thread THREAD's scheduling priority.  */
>  extern int pthread_setschedprio (pthread_t __thr, int __prio) __THROW;
>
> +#ifdef __USE_GNU
> +/* Get thread name visible in the kernel and its interfaces.  */
> +extern int pthread_getname_np (pthread_t __target_thread, char *__buf,
> +                              size_t __buflen)
> +     __THROW __nonnull ((2));

__attr_access ((__write_only__, 2, 3)) perhaps?

> +
> +/* Set thread name visible in the kernel and its interfaces.  */
> +extern int pthread_setname_np (pthread_t __target_thread, const char *__name)
> +     __THROW __nonnull ((2));

Same here, __attr_access ((__read_only__, 2))

> diff --git a/sysdeps/mach/htl/pt-setname-np.c b/sysdeps/mach/htl/pt-setname-np.c
> new file mode 100644
> index 00000000..abc20bf5
> --- /dev/null
> +++ b/sysdeps/mach/htl/pt-setname-np.c
> @@ -0,0 +1,66 @@
> +/* pthread_setname_np.  Mach version.
> +   Copyright (C) 2024 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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <ldsodefs.h>
> +#include <pthread.h>
> +#include <pthreadP.h>
> +#include <string.h>
> +
> +#include <pt-internal.h>
> +#include <hurdlock.h>

What's hurdlock.h for?

> +
> +int
> +__pthread_setname_np (pthread_t thread, const char *name)
> +{
> +#ifdef HAVE_MACH_THREAD_SET_NAME
> +/* Same as the Mach kernel's thread name size.  */
> +#define THREAD_NAME_SIZE 64
> +  struct __pthread *pthread;
> +  char *oldname, *cp, newname[THREAD_NAME_SIZE];
> +
> +  /* Lookup the thread structure for THREAD.  */
> +  pthread = __pthread_getid (thread);
> +  if (pthread == NULL)
> +    return ESRCH;
> +
> +  /* Check for overflow and copy the name into a buffer.  */
> +  if (strlen (name) >= THREAD_NAME_SIZE)
> +    return ERANGE;
> +  strncpy (newname, name, THREAD_NAME_SIZE);
> +
> +  oldname = pthread->thread_name;
> +  cp = strdup (newname);
> +  if (cp == NULL)
> +    return ENOMEM;
> +
> +  __pthread_mutex_lock (&pthread->name_lock);
> +  oldname = pthread->thread_name;
> +  pthread->thread_name = cp;
> +  __thread_set_name (pthread->kernel_thread, cp);

No checking the return value?

> +  __pthread_mutex_unlock (&pthread->name_lock);
> +
> +  if (oldname != NULL)
> +    free (oldname);

Nitpick: no need to check for NULL before freeing.

Sergey
Samuel Thibault July 10, 2024, 6:29 p.m. UTC | #2
Sergey Bugaev, le mer. 10 juil. 2024 21:07:21 +0300, a ecrit:
> in general, what's this useful for? Debugging, maybe?

Yes, but also because we see more and more software assuming that these
functions are available... (just because they are on Linux)

Samuel
Samuel Thibault July 10, 2024, 8:30 p.m. UTC | #3
Sergey Bugaev, le mer. 10 juil. 2024 21:07:21 +0300, a ecrit:
> Do you expect the process itself to query its threads' names locally,
> or do you expect another process (GDB) to issue thread_get_name
> remotely?

We'll want e.g. gdb to use thread_get_name to get it indeed.

> On Wed, Jul 10, 2024 at 7:04 PM Flavio Cruz <flaviocruz@gmail.com> wrote:
> > diff --git a/htl/pt-internal.h b/htl/pt-internal.h
> > index 85a7d905..b6ccbe12 100644
> > --- a/htl/pt-internal.h
> > +++ b/htl/pt-internal.h
> > +  char *thread_name;
> 
> Does it make sense to store the name locally? Could pthread_getname_np
> call thread_get_name also, if we don't expect it to be a frequent
> operation?
> 
> Not saying you shouldn't store the name, but let's think of the space
> vs performance trade-off and document it.

I don't think pthread_getname_np will be a frequent operation, so it's
probably not worth storing it inside glibc. That'll make the
implementation much simpler and avoid the question of the mutex :)

Samuel
Flavio Cruz July 11, 2024, 10:39 p.m. UTC | #4
On Wed, Jul 10, 2024 at 9:31 PM Samuel Thibault <samuel.thibault@gnu.org>
wrote:

> Sergey Bugaev, le mer. 10 juil. 2024 21:07:21 +0300, a ecrit:
> > Do you expect the process itself to query its threads' names locally,
> > or do you expect another process (GDB) to issue thread_get_name
> > remotely?
>
> We'll want e.g. gdb to use thread_get_name to get it indeed.
>
> > On Wed, Jul 10, 2024 at 7:04 PM Flavio Cruz <flaviocruz@gmail.com>
> wrote:
> > > diff --git a/htl/pt-internal.h b/htl/pt-internal.h
> > > index 85a7d905..b6ccbe12 100644
> > > --- a/htl/pt-internal.h
> > > +++ b/htl/pt-internal.h
> > > +  char *thread_name;
> >
> > Does it make sense to store the name locally? Could pthread_getname_np
> > call thread_get_name also, if we don't expect it to be a frequent
> > operation?
> >
> > Not saying you shouldn't store the name, but let's think of the space
> > vs performance trade-off and document it.
>
> I don't think pthread_getname_np will be a frequent operation, so it's
> probably not worth storing it inside glibc. That'll make the
> implementation much simpler and avoid the question of the mutex :)
>

Thanks Sergey and Samuel for the reviews. I have published a second version
with a
new thread_get_name RPC that is used to implement pthread_getname_np.


> Samuel
>
diff mbox series

Patch

diff --git a/config.h.in b/config.h.in
index 9a83b774..7bf73eda 100644
--- a/config.h.in
+++ b/config.h.in
@@ -159,6 +159,9 @@ 
 /* Mach specific: define if the `host_page_size' RPC is available.  */
 #undef	HAVE_HOST_PAGE_SIZE
 
+/* Mach specific: define if the `thread_set_name' RPC is available.  */
+#undef  HAVE_MACH_THREAD_SET_NAME
+
 /* Mach/i386 specific: define if the `i386_io_perm_*' RPCs are available.  */
 #undef	HAVE_I386_IO_PERM_MODIFY
 
diff --git a/htl/Makefile b/htl/Makefile
index 4028e5a2..c5d1c473 100644
--- a/htl/Makefile
+++ b/htl/Makefile
@@ -145,6 +145,8 @@  libpthread-routines := \
   pt-getcpuclockid \
   pt-setschedprio \
   pt-yield \
+  pt-getname-np \
+  pt-setname-np \
   sem_close \
   sem-destroy \
   sem-getvalue \
diff --git a/htl/Versions b/htl/Versions
index 71005175..e1524117 100644
--- a/htl/Versions
+++ b/htl/Versions
@@ -169,6 +169,11 @@  libpthread {
     sem_clockwait;
   }
 
+  GLIBC_2.40 {
+    pthread_getname_np;
+    pthread_setname_np;
+  }
+
   GLIBC_PRIVATE {
     __pthread_initialize_minimal;
 
diff --git a/htl/pt-alloc.c b/htl/pt-alloc.c
index c5674a47..90f999a8 100644
--- a/htl/pt-alloc.c
+++ b/htl/pt-alloc.c
@@ -56,6 +56,9 @@  initialize_pthread (struct __pthread *new)
   new->state_cond = (pthread_cond_t) PTHREAD_COND_INITIALIZER;
   new->terminated = FALSE;
 
+  new->name_lock = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
+  new->thread_name = NULL;
+
   memset (&new->res_state, '\0', sizeof (new->res_state));
 
   new->tcb = NULL;
diff --git a/htl/pt-getname-np.c b/htl/pt-getname-np.c
new file mode 100644
index 00000000..b32abb84
--- /dev/null
+++ b/htl/pt-getname-np.c
@@ -0,0 +1,51 @@ 
+/* pthread_getname_np.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+//#include <ldsodefs.h>
+#include <pthread.h>
+#include <pthreadP.h>
+#include <string.h>
+
+#include <pt-internal.h>
+
+int
+__pthread_getname_np (pthread_t thread, char *buf, size_t len)
+{
+  struct __pthread *pthread;
+
+  if (len < 1)
+    return ERANGE;
+
+  /* Lookup the thread structure for THREAD.  */
+  pthread = __pthread_getid (thread);
+  if (pthread == NULL)
+    return ESRCH;
+
+  __pthread_mutex_lock (&pthread->name_lock);
+  if (pthread->thread_name == NULL)
+    buf[0] = '\0';
+  else {
+    strncpy (buf, pthread->thread_name, len - 1);
+    buf[len - 1] = '\0';
+  }
+  __pthread_mutex_unlock (&pthread->name_lock);
+
+  return 0;
+}
+
+weak_alias (__pthread_getname_np, pthread_getname_np)
diff --git a/htl/pt-internal.h b/htl/pt-internal.h
index 85a7d905..b6ccbe12 100644
--- a/htl/pt-internal.h
+++ b/htl/pt-internal.h
@@ -105,6 +105,10 @@  struct __pthread
   /* Initial sigset for the thread.  */
   sigset_t init_sigset;
 
+  /* Used to store the thread name through pthread_setname_np.  */
+  pthread_mutex_t name_lock;
+  char *thread_name;
+
   /* Thread context.  */
   struct pthread_mcontext mcontext;
 
diff --git a/sysdeps/htl/pthread.h b/sysdeps/htl/pthread.h
index fa626ebc..cf42383f 100644
--- a/sysdeps/htl/pthread.h
+++ b/sysdeps/htl/pthread.h
@@ -891,6 +891,17 @@  extern int pthread_setschedparam (pthread_t __thr, int __policy,
 /* Set thread THREAD's scheduling priority.  */
 extern int pthread_setschedprio (pthread_t __thr, int __prio) __THROW;
 
+#ifdef __USE_GNU
+/* Get thread name visible in the kernel and its interfaces.  */
+extern int pthread_getname_np (pthread_t __target_thread, char *__buf,
+			       size_t __buflen)
+     __THROW __nonnull ((2));
+
+/* Set thread name visible in the kernel and its interfaces.  */
+extern int pthread_setname_np (pthread_t __target_thread, const char *__name)
+     __THROW __nonnull ((2));
+#endif
+
 #ifdef __USE_GNU
 /* Yield the processor to another thread or process.
    This function is similar to the POSIX `sched_yield' function but
diff --git a/sysdeps/mach/configure b/sysdeps/mach/configure
index 5779efd1..b2d3ee12 100644
--- a/sysdeps/mach/configure
+++ b/sysdeps/mach/configure
@@ -293,6 +293,9 @@  if test "x$mach_interface_list" = x; then
   as_fn_error $? "what manner of Mach is this?" "$LINENO" 5
 fi
 
+
+
+
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep -e" >&5
 printf %s "checking for egrep -e... " >&6; }
 if test ${ac_cv_path_EGREP_TRADITIONAL+y}
@@ -429,7 +432,7 @@  printf "%s\n" "$ac_cv_path_EGREP_TRADITIONAL" >&6; }
 
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for host_page_size in mach_host.defs" >&5
 printf %s "checking for host_page_size in mach_host.defs... " >&6; }
-if test ${libc_cv_mach_host_page_size+y}
+if test ${libc_cv_mach_rpc_host_page_size+y}
 then :
   printf %s "(cached) " >&6
 else case e in #(
@@ -441,22 +444,53 @@  _ACEOF
 if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
   $EGREP_TRADITIONAL "host_page_size" >/dev/null 2>&1
 then :
-  libc_cv_mach_host_page_size=yes
+  libc_cv_mach_rpc_host_page_size=yes
 else case e in #(
-  e) libc_cv_mach_host_page_size=no ;;
+  e) libc_cv_mach_rpc_host_page_size=no ;;
 esac
 fi
 rm -rf conftest*
  ;;
 esac
 fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_mach_host_page_size" >&5
-printf "%s\n" "$libc_cv_mach_host_page_size" >&6; }
-if test $libc_cv_mach_host_page_size = yes; then
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_mach_rpc_host_page_size" >&5
+printf "%s\n" "$libc_cv_mach_rpc_host_page_size" >&6; }
+if test $libc_cv_mach_rpc_host_page_size = yes; then
   printf "%s\n" "#define HAVE_HOST_PAGE_SIZE 1" >>confdefs.h
 
 fi
 
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for thread_set_name in gnumach.defs" >&5
+printf %s "checking for thread_set_name in gnumach.defs... " >&6; }
+if test ${libc_cv_mach_rpc_thread_set_name+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <mach/gnumach.defs>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP_TRADITIONAL "thread_set_name" >/dev/null 2>&1
+then :
+  libc_cv_mach_rpc_thread_set_name=yes
+else case e in #(
+  e) libc_cv_mach_rpc_thread_set_name=no ;;
+esac
+fi
+rm -rf conftest*
+ ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_mach_rpc_thread_set_name" >&5
+printf "%s\n" "$libc_cv_mach_rpc_thread_set_name" >&6; }
+if test $libc_cv_mach_rpc_thread_set_name = yes; then
+  printf "%s\n" "#define HAVE_MACH_THREAD_SET_NAME 1" >>confdefs.h
+
+fi
+
+
 ac_fn_c_check_header_preproc "$LINENO" "mach/machine/ndr_def.h" "ac_cv_header_mach_machine_ndr_def_h"
 if test "x$ac_cv_header_mach_machine_ndr_def_h" = xyes
 then :
diff --git a/sysdeps/mach/configure.ac b/sysdeps/mach/configure.ac
index 730fb25d..2c390c90 100644
--- a/sysdeps/mach/configure.ac
+++ b/sysdeps/mach/configure.ac
@@ -72,14 +72,27 @@  if test "x$mach_interface_list" = x; then
   AC_MSG_ERROR([what manner of Mach is this?])
 fi
 
-AC_CACHE_CHECK(for host_page_size in mach_host.defs,
-	       libc_cv_mach_host_page_size, [dnl
-AC_EGREP_HEADER(host_page_size, mach/mach_host.defs,
-		libc_cv_mach_host_page_size=yes,
-		libc_cv_mach_host_page_size=no)])
-if test $libc_cv_mach_host_page_size = yes; then
-  AC_DEFINE([HAVE_HOST_PAGE_SIZE])
+dnl
+dnl mach_RPC_CHECK(interface.defs, rpc_method, define)
+dnl
+dnl Check if rpc_method RPC is defined by interface.defs
+dnl and define `define`.
+dnl
+AC_DEFUN([mach_RPC_CHECK], [dnl
+AC_CACHE_CHECK(for $2 in $1, libc_cv_mach_rpc_$2, [dnl
+AC_EGREP_HEADER($2, mach/$1,
+		libc_cv_mach_rpc_$2=yes,
+		libc_cv_mach_rpc_$2=no)])
+if test $libc_cv_mach_rpc_$2 = yes; then
+  AC_DEFINE([$3])
 fi
+])
+
+
+mach_RPC_CHECK(mach_host.defs, host_page_size,
+	       HAVE_HOST_PAGE_SIZE)
+mach_RPC_CHECK(gnumach.defs, thread_set_name,
+	       HAVE_MACH_THREAD_SET_NAME)
 
 AC_CHECK_HEADER(mach/machine/ndr_def.h, [dnl
   DEFINES="$DEFINES -DNDR_DEF_HEADER='<mach/machine/ndr_def.h>'"], [dnl
diff --git a/sysdeps/mach/htl/pt-setname-np.c b/sysdeps/mach/htl/pt-setname-np.c
new file mode 100644
index 00000000..abc20bf5
--- /dev/null
+++ b/sysdeps/mach/htl/pt-setname-np.c
@@ -0,0 +1,66 @@ 
+/* pthread_setname_np.  Mach version.
+   Copyright (C) 2024 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <ldsodefs.h>
+#include <pthread.h>
+#include <pthreadP.h>
+#include <string.h>
+
+#include <pt-internal.h>
+#include <hurdlock.h>
+
+int
+__pthread_setname_np (pthread_t thread, const char *name)
+{
+#ifdef HAVE_MACH_THREAD_SET_NAME
+/* Same as the Mach kernel's thread name size.  */
+#define THREAD_NAME_SIZE 64
+  struct __pthread *pthread;
+  char *oldname, *cp, newname[THREAD_NAME_SIZE];
+
+  /* Lookup the thread structure for THREAD.  */
+  pthread = __pthread_getid (thread);
+  if (pthread == NULL)
+    return ESRCH;
+
+  /* Check for overflow and copy the name into a buffer.  */
+  if (strlen (name) >= THREAD_NAME_SIZE)
+    return ERANGE;
+  strncpy (newname, name, THREAD_NAME_SIZE);
+
+  oldname = pthread->thread_name;
+  cp = strdup (newname);
+  if (cp == NULL)
+    return ENOMEM;
+
+  __pthread_mutex_lock (&pthread->name_lock);
+  oldname = pthread->thread_name;
+  pthread->thread_name = cp;
+  __thread_set_name (pthread->kernel_thread, cp);
+  __pthread_mutex_unlock (&pthread->name_lock);
+
+  if (oldname != NULL)
+    free (oldname);
+
+  return 0;
+#else
+  return ENOTSUP;
+#endif
+}
+
+weak_alias (__pthread_setname_np, pthread_setname_np)
diff --git a/sysdeps/mach/hurd/i386/libpthread.abilist b/sysdeps/mach/hurd/i386/libpthread.abilist
index fa90cc65..3ea7cb41 100644
--- a/sysdeps/mach/hurd/i386/libpthread.abilist
+++ b/sysdeps/mach/hurd/i386/libpthread.abilist
@@ -164,3 +164,5 @@  GLIBC_2.32 tss_create F
 GLIBC_2.32 tss_delete F
 GLIBC_2.32 tss_get F
 GLIBC_2.32 tss_set F
+GLIBC_2.40 pthread_getname_np F
+GLIBC_2.40 pthread_setname_np F
diff --git a/sysdeps/mach/hurd/x86_64/libpthread.abilist b/sysdeps/mach/hurd/x86_64/libpthread.abilist
index 80615d16..69999df5 100644
--- a/sysdeps/mach/hurd/x86_64/libpthread.abilist
+++ b/sysdeps/mach/hurd/x86_64/libpthread.abilist
@@ -163,3 +163,5 @@  GLIBC_2.38 tss_create F
 GLIBC_2.38 tss_delete F
 GLIBC_2.38 tss_get F
 GLIBC_2.38 tss_set F
+GLIBC_2.40 pthread_getname_np F
+GLIBC_2.40 pthread_setname_np F