From 74d463c50bb1096efef47022405c7db33f83fb5a Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Wed, 12 Mar 2025 10:16:31 +0100 Subject: Linux: Add the pthread_gettid_np function (bug 27880) Current Bionic has this function, with enhanced error checking (the undefined case terminates the process). Reviewed-by: Joseph Myers --- nptl/Makefile | 2 ++ nptl/Versions | 3 ++ nptl/pthread_gettid_np.c | 30 +++++++++++++++++ nptl/tst-pthread_gettid_np.c | 79 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 nptl/pthread_gettid_np.c create mode 100644 nptl/tst-pthread_gettid_np.c (limited to 'nptl') diff --git a/nptl/Makefile b/nptl/Makefile index f70d1e55bd..eca00936d7 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -124,6 +124,7 @@ routines = \ pthread_getname \ pthread_getschedparam \ pthread_getspecific \ + pthread_gettid_np \ pthread_join \ pthread_join_common \ pthread_key_create \ @@ -326,6 +327,7 @@ tests = \ tst-pthread-timedlock-lockloop \ tst-pthread_exit-nothreads \ tst-pthread_exit-nothreads-static \ + tst-pthread_gettid_np \ tst-robust-fork \ tst-robustpi1 \ tst-robustpi2 \ diff --git a/nptl/Versions b/nptl/Versions index 3221de89d1..ef55376dd9 100644 --- a/nptl/Versions +++ b/nptl/Versions @@ -378,6 +378,9 @@ libc { tss_get; tss_set; } + GLIBC_2.42 { + pthread_gettid_np; + } GLIBC_PRIVATE { __libc_alloca_cutoff; __lll_lock_wake_private; diff --git a/nptl/pthread_gettid_np.c b/nptl/pthread_gettid_np.c new file mode 100644 index 0000000000..bf3a12cd52 --- /dev/null +++ b/nptl/pthread_gettid_np.c @@ -0,0 +1,30 @@ +/* Get the Linux TID from a pthread_t handle. + Copyright (C) 2025 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; see the file COPYING.LIB. If + not, see . */ + +#include +#include + +pid_t +pthread_gettid_np (pthread_t threadid) +{ + /* The kernel may concurrently set this field. */ + pid_t tid = atomic_load_relaxed (&((struct pthread *) threadid)->tid); + if (tid <= 0) + return -1; + return tid; +} diff --git a/nptl/tst-pthread_gettid_np.c b/nptl/tst-pthread_gettid_np.c new file mode 100644 index 0000000000..6a98d864e2 --- /dev/null +++ b/nptl/tst-pthread_gettid_np.c @@ -0,0 +1,79 @@ +/* Test for pthread_gettid_np. + Copyright (C) 2025 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; see the file COPYING.LIB. If + not, see . */ + +#include +#include +#include +#include +#include +#include +#include + +static pthread_barrier_t barrier; + +static pid_t thread_tid; + +static void * +thread_func (void *ignored) +{ + thread_tid = gettid (); + TEST_VERIFY (thread_tid != getpid ()); + TEST_COMPARE (thread_tid, pthread_gettid_np (pthread_self ())); + xpthread_barrier_wait (&barrier); + /* The main thread calls pthread_gettid_np here. */ + xpthread_barrier_wait (&barrier); + return NULL; +} + +static int +do_test (void) +{ + TEST_COMPARE (pthread_gettid_np (pthread_self ()), getpid ()); + TEST_COMPARE (pthread_gettid_np (pthread_self ()), gettid ()); + + xpthread_barrier_init (&barrier, NULL, 2); + + pthread_t thr = xpthread_create (NULL, thread_func, NULL); + xpthread_barrier_wait (&barrier); + TEST_COMPARE (thread_tid, pthread_gettid_np (thr)); + xpthread_barrier_wait (&barrier); + + while (true) + { + /* Check if the kernel thread is still running. */ + if (tgkill (getpid (), thread_tid, 0)) + { + TEST_COMPARE (errno, ESRCH); + break; + } + + pid_t tid = pthread_gettid_np (thr); + if (tid != thread_tid) + { + TEST_COMPARE (tid, -1); + break; + } + TEST_COMPARE (sched_yield (), 0); + } + + TEST_VERIFY (xpthread_join (thr) == NULL); + + return 0; +} + +#include -- cgit v1.2.3