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