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
