[PATCH 4/6] nptl: Remove INVALID_TD_P

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Thu Dec 18 17:15:29 GMT 2025



On 18/12/25 10:50, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>> And use 'joinstate' to get the thread state instead of 'tid'.  The
>> joinstate is set by the kernel when the thread exits.
> 
>> diff --git a/sysdeps/nptl/pthreadP.h b/sysdeps/nptl/pthreadP.h
>> index 4b76af7771..0bf44ac003 100644
>> --- a/sysdeps/nptl/pthreadP.h
>> +++ b/sysdeps/nptl/pthreadP.h
>> @@ -217,6 +217,11 @@ libc_hidden_proto (__pthread_current_priority)
>>     nothing.  And if the test triggers the thread descriptor is
>>     guaranteed to be invalid.  */
>>  #define INVALID_TD_P(pd) __builtin_expect ((pd)->tid <= 0, 0)
>> +static inline bool
>> +__pthread_descriptor_valid (struct pthread *pd)
>> +{
>> +  return atomic_load_relaxed (&pd->joinstate) != THREAD_STATE_EXITED;
>> +}
> 
> This does not match the commit message: INVALID_TD_P is still there, but
> unused.  Please also mention __pthread_descriptor_valid in the commit
> message.

Indeed, I forgot to remove the unused macro.  I updated the commit as well:
Are you ok with the following patch:

>From 32d9930fad88af49652a0bed8b390aba476bd9dd Mon Sep 17 00:00:00 2001
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Thu, 11 Dec 2025 17:47:20 -0300
Subject: [PATCH 4/6] nptl: Remove INVALID_TD_P

And use the new __pthread_descriptor_valid function that checks
for 'joinstate' to get the thread state instead of 'tid'.  The
joinstate is set by the kernel when the thread exits.

Checked on x86_64-linux-gnu.
---
 nptl/pthread_getcpuclockid.c         |   2 +-
 nptl/pthread_getschedparam.c         |   2 +-
 nptl/pthread_setschedparam.c         |   2 +-
 nptl/pthread_setschedprio.c          |   2 +-
 sysdeps/nptl/pthreadP.h              |   6 +-
 sysdeps/pthread/Makefile             |   1 +
 sysdeps/pthread/tst-pthread-exited.c | 119 +++++++++++++++++++++++++++
 7 files changed, 129 insertions(+), 5 deletions(-)
 create mode 100644 sysdeps/pthread/tst-pthread-exited.c

diff --git a/nptl/pthread_getcpuclockid.c b/nptl/pthread_getcpuclockid.c
index 0cd9f77bea..70677d0138 100644
--- a/nptl/pthread_getcpuclockid.c
+++ b/nptl/pthread_getcpuclockid.c
@@ -29,7 +29,7 @@ __pthread_getcpuclockid (pthread_t threadid, clockid_t *clockid)
   struct pthread *pd = (struct pthread *) threadid;
 
   /* Make sure the descriptor is valid.  */
-  if (INVALID_TD_P (pd))
+  if (!__pthread_descriptor_valid (pd))
     /* Not a valid thread handle.  */
     return ESRCH;
 
diff --git a/nptl/pthread_getschedparam.c b/nptl/pthread_getschedparam.c
index bb74ed959c..aab0d836ce 100644
--- a/nptl/pthread_getschedparam.c
+++ b/nptl/pthread_getschedparam.c
@@ -28,7 +28,7 @@ __pthread_getschedparam (pthread_t threadid, int *policy,
   struct pthread *pd = (struct pthread *) threadid;
 
   /* Make sure the descriptor is valid.  */
-  if (INVALID_TD_P (pd))
+  if (!__pthread_descriptor_valid (pd))
     /* Not a valid thread handle.  */
     return ESRCH;
 
diff --git a/nptl/pthread_setschedparam.c b/nptl/pthread_setschedparam.c
index 1b43eb1f71..b057f8228f 100644
--- a/nptl/pthread_setschedparam.c
+++ b/nptl/pthread_setschedparam.c
@@ -29,7 +29,7 @@ __pthread_setschedparam (pthread_t threadid, int policy,
   struct pthread *pd = (struct pthread *) threadid;
 
   /* Make sure the descriptor is valid.  */
-  if (INVALID_TD_P (pd))
+  if (!__pthread_descriptor_valid (pd))
     /* Not a valid thread handle.  */
     return ESRCH;
 
diff --git a/nptl/pthread_setschedprio.c b/nptl/pthread_setschedprio.c
index c355716593..8cf7f5380f 100644
--- a/nptl/pthread_setschedprio.c
+++ b/nptl/pthread_setschedprio.c
@@ -29,7 +29,7 @@ __pthread_setschedprio (pthread_t threadid, int prio)
   struct pthread *pd = (struct pthread *) threadid;
 
   /* Make sure the descriptor is valid.  */
-  if (INVALID_TD_P (pd))
+  if (!__pthread_descriptor_valid (pd))
     /* Not a valid thread handle.  */
     return ESRCH;
 
diff --git a/sysdeps/nptl/pthreadP.h b/sysdeps/nptl/pthreadP.h
index 4b76af7771..ac4a1a055e 100644
--- a/sysdeps/nptl/pthreadP.h
+++ b/sysdeps/nptl/pthreadP.h
@@ -216,7 +216,11 @@ libc_hidden_proto (__pthread_current_priority)
 /* This will not catch all invalid descriptors but is better than
    nothing.  And if the test triggers the thread descriptor is
    guaranteed to be invalid.  */
-#define INVALID_TD_P(pd) __builtin_expect ((pd)->tid <= 0, 0)
+static inline bool
+__pthread_descriptor_valid (struct pthread *pd)
+{
+  return atomic_load_relaxed (&pd->joinstate) != THREAD_STATE_EXITED;
+}
 
 extern void __pthread_unwind (__pthread_unwind_buf_t *__buf)
      __cleanup_fct_attribute __attribute ((__noreturn__))
diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
index c6ea59ee16..73bd5e6162 100644
--- a/sysdeps/pthread/Makefile
+++ b/sysdeps/pthread/Makefile
@@ -212,6 +212,7 @@ tests += \
   tst-pt-vfork1 \
   tst-pt-vfork2 \
   tst-pthread-exit-signal \
+  tst-pthread-exited \
   tst-pthread-mutexattr \
   tst-pthread-mutexattr-2 \
   tst-pthread-raise-blocked-self \
diff --git a/sysdeps/pthread/tst-pthread-exited.c b/sysdeps/pthread/tst-pthread-exited.c
new file mode 100644
index 0000000000..91c242c50c
--- /dev/null
+++ b/sysdeps/pthread/tst-pthread-exited.c
@@ -0,0 +1,119 @@
+/* Test pthread interface which should return ESRCH when issued
+   with a terminated pthread_t.
+
+   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; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <signal.h>
+#include <stddef.h>
+#include <grp.h>
+#include <pwd.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/xthread.h>
+#include <unistd.h>
+
+static void *
+noop_thread (void *closure)
+{
+  return NULL;
+}
+
+enum { nthreads = 8 };
+
+static int
+do_test_default (void)
+{
+  pthread_t thrs[nthreads];
+  for (int i = 0; i < nthreads; i++)
+    thrs[i] = xpthread_create (NULL, noop_thread, NULL);
+
+  support_wait_for_thread_exit ();
+
+  for (int i = 0; i < nthreads; i++)
+    {
+      clockid_t clk;
+      TEST_COMPARE (pthread_getcpuclockid (thrs[i], &clk), ESRCH);
+
+      struct sched_param sch = { 0 };
+      int policy;
+      TEST_COMPARE (pthread_getschedparam (thrs[i], &policy, &sch), ESRCH);
+
+      TEST_COMPARE (pthread_setschedparam (thrs[i], SCHED_FIFO, &sch), ESRCH);
+
+      TEST_COMPARE (pthread_setschedprio (thrs[i], 0), ESRCH);
+    }
+
+  for (int i = 0; i < nthreads; i++)
+    xpthread_join (thrs[i]);
+
+  return 0;
+}
+
+
+static void *
+detached_pause_thread (void *closure)
+{
+  pthread_detach (pthread_self ());
+  pause ();
+  return NULL;
+}
+
+static void
+do_test_detached (void)
+{
+  pthread_t thrs[nthreads];
+  for (int i = 0; i < nthreads; i++)
+    thrs[i] = xpthread_create (NULL, detached_pause_thread, NULL);
+
+  for (int i = 0; i < nthreads; i++)
+    {
+      clockid_t clk;
+      TEST_COMPARE (pthread_getcpuclockid (thrs[i], &clk), 0);
+
+      struct sched_param sch = { 0 };
+      int policy;
+      TEST_COMPARE (pthread_getschedparam (thrs[i], &policy, &sch), 0);
+
+      sch.sched_priority = 8;
+      TEST_COMPARE (pthread_setschedparam (thrs[i], SCHED_FIFO, &sch), EPERM);
+
+      TEST_COMPARE (pthread_setschedprio (thrs[i], 0), 0);
+    }
+}
+
+static int
+do_test (void)
+{
+  /* The test relies on pthread setup failures that succeed as root.  */
+  if (geteuid () == 0)
+    {
+      struct passwd *pwd = getpwnam ("nobody");
+      if (pwd == NULL)
+	FAIL_UNSUPPORTED ("iuser nobody doesn't exist");
+
+      TEST_VERIFY_EXIT (setresuid (pwd->pw_uid, pwd->pw_uid, -1) == 0);
+    }
+
+  do_test_default ();
+  do_test_detached ();
+
+  return 0;
+}
+
+#include <support/test-driver.c>
-- 
2.43.0




More information about the Libc-alpha mailing list