[libc-commits] [libc] [libc] Add an extension macro to get numerical thread id (PR #195202)

Alexey Samsonov via libc-commits libc-commits at lists.llvm.org
Mon May 4 23:26:36 PDT 2026


https://github.com/vonosmas updated https://github.com/llvm/llvm-project/pull/195202

>From 45905f10f83fb271a3db6f6c4f563b84c7570e35 Mon Sep 17 00:00:00 2001
From: Alexey Samsonov <vonosmas at gmail.com>
Date: Fri, 1 May 2026 00:07:14 +0000
Subject: [PATCH 1/2] [libc] Add an extension macro to get numerical thread id

---
 libc/include/CMakeLists.txt                     |  1 +
 libc/include/llvm-libc-macros/CMakeLists.txt    |  9 +++++++++
 libc/include/llvm-libc-macros/pthread-macros.h  |  5 +++++
 libc/include/llvm-libc-macros/threads-macros.h  | 17 +++++++++++++++++
 libc/include/pthread.yaml                       |  2 ++
 libc/include/threads.yaml                       |  2 ++
 .../src/pthread/pthread_create_test.cpp         |  1 +
 .../src/pthread/pthread_equal_test.cpp          |  5 +++++
 .../integration/src/threads/thrd_equal_test.cpp |  5 +++++
 libc/test/integration/src/threads/thrd_test.cpp |  1 +
 10 files changed, 48 insertions(+)
 create mode 100644 libc/include/llvm-libc-macros/threads-macros.h

diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index aa3791b2ead2c..452f43ce91efe 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -323,6 +323,7 @@ add_header_macro(
   threads.h
   DEPENDS
     .llvm_libc_common_h
+    .llvm-libc-macros.threads_macros
     .llvm-libc-types.__call_once_func_t
     .llvm-libc-types.once_flag
     .llvm-libc-types.cnd_t
diff --git a/libc/include/llvm-libc-macros/CMakeLists.txt b/libc/include/llvm-libc-macros/CMakeLists.txt
index 86085b50d4c4c..b2ac0d3958e22 100644
--- a/libc/include/llvm-libc-macros/CMakeLists.txt
+++ b/libc/include/llvm-libc-macros/CMakeLists.txt
@@ -386,6 +386,7 @@ add_macro_header(
     pthread-macros.h
   DEPENDS
     .null_macro
+    .stdint_macros
 )
 
 add_macro_header(
@@ -406,6 +407,14 @@ add_macro_header(
     sysexits-macros.h
 )
 
+add_macro_header(
+  threads_macros
+  HDR
+    threads-macros.h
+  DEPENDS
+    .stdint_macros
+)
+
 if (LIBC_CONF_MODULAR_FORMAT)
   add_macro_header(
     _LIBC_MODULAR_FORMAT_PRINTF
diff --git a/libc/include/llvm-libc-macros/pthread-macros.h b/libc/include/llvm-libc-macros/pthread-macros.h
index 1619ad123d2c1..d50dbd5d3cfc5 100644
--- a/libc/include/llvm-libc-macros/pthread-macros.h
+++ b/libc/include/llvm-libc-macros/pthread-macros.h
@@ -9,6 +9,8 @@
 #ifndef LLVM_LIBC_MACROS_PTHREAD_MACRO_H
 #define LLVM_LIBC_MACROS_PTHREAD_MACRO_H
 
+#include "stdint-macros.h"
+
 #define PTHREAD_NULL {0}
 
 #define PTHREAD_CREATE_JOINABLE 0
@@ -77,4 +79,7 @@
 #define PTHREAD_RWLOCK_PREFER_WRITER_NP 1
 #define PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP 2
 
+// LLVM libc extensions
+#define __PTHREAD_GET_ID(t) (reinterpret_cast<uintptr_t>((t).__attrib))
+
 #endif // LLVM_LIBC_MACROS_PTHREAD_MACRO_H
diff --git a/libc/include/llvm-libc-macros/threads-macros.h b/libc/include/llvm-libc-macros/threads-macros.h
new file mode 100644
index 0000000000000..2e6ee4316bac1
--- /dev/null
+++ b/libc/include/llvm-libc-macros/threads-macros.h
@@ -0,0 +1,17 @@
+//===-- Definition of threads macros --------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_MACROS_THREADS_MACRO_H
+#define LLVM_LIBC_MACROS_THREADS_MACRO_H
+
+#include "stdint-macros.h"
+
+// LLVM libc extensions
+#define __THRD_GET_ID(t) (reinterpret_cast<uintptr_t>((t).__attrib))
+
+#endif // LLVM_LIBC_MACROS_THREADS_MACRO_H
diff --git a/libc/include/pthread.yaml b/libc/include/pthread.yaml
index bb735780ab555..8f7a8e03b82c5 100644
--- a/libc/include/pthread.yaml
+++ b/libc/include/pthread.yaml
@@ -50,6 +50,8 @@ macros:
     standards:
       - gnu
     macro_header: pthread-macros.h
+  - macro_name: __PTHREAD_GET_ID
+    macro_header: pthread-macros.h
 types:
   - type_name: pthread_t
   - type_name: pthread_once_t
diff --git a/libc/include/threads.yaml b/libc/include/threads.yaml
index 6f7796e090ab6..67df046005bc1 100644
--- a/libc/include/threads.yaml
+++ b/libc/include/threads.yaml
@@ -4,6 +4,8 @@ standards:
 macros:
   - macro_name: ONCE_FLAG_INIT
     macro_value: '{0}'
+  - macro_name: __THRD_GET_ID
+    macro_header: threads-macros.h
 types:
   - type_name: once_flag
   - type_name: __call_once_func_t
diff --git a/libc/test/integration/src/pthread/pthread_create_test.cpp b/libc/test/integration/src/pthread/pthread_create_test.cpp
index a067a829e039b..a1e3182468142 100644
--- a/libc/test/integration/src/pthread/pthread_create_test.cpp
+++ b/libc/test/integration/src/pthread/pthread_create_test.cpp
@@ -179,6 +179,7 @@ static void run_success_config(int detachstate, size_t guardsize,
   ASSERT_EQ(LIBC_NAMESPACE::pthread_create(&tid, attr, successThread,
                                            reinterpret_cast<void *>(th_arg)),
             0);
+  ASSERT_NE(__PTHREAD_GET_ID(tid), 0);
   ASSERT_ERRNO_SUCCESS();
 
   if (detachstate == PTHREAD_CREATE_JOINABLE) {
diff --git a/libc/test/integration/src/pthread/pthread_equal_test.cpp b/libc/test/integration/src/pthread/pthread_equal_test.cpp
index 01569798537e3..ccc3087600408 100644
--- a/libc/test/integration/src/pthread/pthread_equal_test.cpp
+++ b/libc/test/integration/src/pthread/pthread_equal_test.cpp
@@ -21,12 +21,14 @@
 
 pthread_t child_thread;
 pthread_mutex_t mutex;
+uintptr_t child_self_thread_id;
 
 static void *child_func(void *arg) {
   LIBC_NAMESPACE::pthread_mutex_lock(&mutex);
   int *ret = reinterpret_cast<int *>(arg);
   auto self = LIBC_NAMESPACE::pthread_self();
   *ret = LIBC_NAMESPACE::pthread_equal(child_thread, self);
+  child_self_thread_id = __PTHREAD_GET_ID(self);
   LIBC_NAMESPACE::pthread_mutex_unlock(&mutex);
   return nullptr;
 }
@@ -50,10 +52,12 @@ TEST_MAIN() {
             0);
   // This new thread should of course not be equal to the main thread.
   ASSERT_EQ(LIBC_NAMESPACE::pthread_equal(th, main_thread), 0);
+  ASSERT_NE(__PTHREAD_GET_ID(th), __PTHREAD_GET_ID(main_thread));
 
   // Set the |child_thread| global var and unlock to allow the child to perform
   // the comparison.
   child_thread = th;
+  uintptr_t child_thread_id = __PTHREAD_GET_ID(child_thread);
   ASSERT_EQ(LIBC_NAMESPACE::pthread_mutex_unlock(&mutex), 0);
 
   void *retval;
@@ -62,6 +66,7 @@ TEST_MAIN() {
   // The child thread should see that pthread_self return value is the same as
   // |child_thread|.
   ASSERT_NE(result, 0);
+  ASSERT_EQ(child_thread_id, child_self_thread_id);
 
   LIBC_NAMESPACE::pthread_mutex_destroy(&mutex);
   return 0;
diff --git a/libc/test/integration/src/threads/thrd_equal_test.cpp b/libc/test/integration/src/threads/thrd_equal_test.cpp
index 4f8866f088b92..509e258448f1e 100644
--- a/libc/test/integration/src/threads/thrd_equal_test.cpp
+++ b/libc/test/integration/src/threads/thrd_equal_test.cpp
@@ -21,12 +21,14 @@
 
 thrd_t child_thread;
 mtx_t mutex;
+uintptr_t child_self_thread_id;
 
 static int child_func(void *arg) {
   LIBC_NAMESPACE::mtx_lock(&mutex);
   int *ret = reinterpret_cast<int *>(arg);
   auto self = LIBC_NAMESPACE::thrd_current();
   *ret = LIBC_NAMESPACE::thrd_equal(child_thread, self);
+  child_self_thread_id = __THRD_GET_ID(self);
   LIBC_NAMESPACE::mtx_unlock(&mutex);
   return 0;
 }
@@ -50,10 +52,12 @@ TEST_MAIN() {
             int(thrd_success));
   // This new thread should of course not be equal to the main thread.
   ASSERT_EQ(LIBC_NAMESPACE::thrd_equal(th, main_thread), 0);
+  ASSERT_NE(__THRD_GET_ID(th), __THRD_GET_ID(main_thread));
 
   // Set the |child_thread| global var and unlock to allow the child to perform
   // the comparison.
   child_thread = th;
+  uintptr_t child_thread_id = __THRD_GET_ID(child_thread);
   ASSERT_EQ(LIBC_NAMESPACE::mtx_unlock(&mutex), int(thrd_success));
 
   int retval;
@@ -62,6 +66,7 @@ TEST_MAIN() {
   // The child thread should see that thrd_current return value is the same as
   // |child_thread|.
   ASSERT_NE(result, 0);
+  ASSERT_EQ(child_thread_id, child_self_thread_id);
 
   LIBC_NAMESPACE::mtx_destroy(&mutex);
   return 0;
diff --git a/libc/test/integration/src/threads/thrd_test.cpp b/libc/test/integration/src/threads/thrd_test.cpp
index 58728366b53ee..9f701224cc212 100644
--- a/libc/test/integration/src/threads/thrd_test.cpp
+++ b/libc/test/integration/src/threads/thrd_test.cpp
@@ -27,6 +27,7 @@ void create_and_join() {
     ASSERT_EQ(LIBC_NAMESPACE::thrd_create(&thread, thread_func, nullptr),
               (int)thrd_success);
     int retval = thread_count + 1; // Start with a retval we dont expect.
+    ASSERT_NE(__THRD_GET_ID(thread), 0);
     ASSERT_EQ(LIBC_NAMESPACE::thrd_join(thread, &retval), (int)thrd_success);
     ASSERT_EQ(retval, 0);
     ASSERT_EQ(counter, old_counter_val + 1);

>From 850cb2c9b4fdcd62106edb292c88b03a03164034 Mon Sep 17 00:00:00 2001
From: Alexey Samsonov <vonosmas at gmail.com>
Date: Tue, 5 May 2026 06:22:54 +0000
Subject: [PATCH 2/2] Fix header in C mode, add header test.

---
 libc/include/llvm-libc-macros/pthread-macros.h |  4 +++-
 libc/include/llvm-libc-macros/threads-macros.h |  4 +++-
 libc/test/include/CMakeLists.txt               | 13 +++++++++++++
 libc/test/include/pthread_test.c               | 18 ++++++++++++++++++
 4 files changed, 37 insertions(+), 2 deletions(-)
 create mode 100644 libc/test/include/pthread_test.c

diff --git a/libc/include/llvm-libc-macros/pthread-macros.h b/libc/include/llvm-libc-macros/pthread-macros.h
index d50dbd5d3cfc5..ffc5d282321c7 100644
--- a/libc/include/llvm-libc-macros/pthread-macros.h
+++ b/libc/include/llvm-libc-macros/pthread-macros.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_LIBC_MACROS_PTHREAD_MACRO_H
 #define LLVM_LIBC_MACROS_PTHREAD_MACRO_H
 
+#include "__llvm-libc-common.h"
 #include "stdint-macros.h"
 
 #define PTHREAD_NULL {0}
@@ -80,6 +81,7 @@
 #define PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP 2
 
 // LLVM libc extensions
-#define __PTHREAD_GET_ID(t) (reinterpret_cast<uintptr_t>((t).__attrib))
+#define __PTHREAD_GET_ID(t)                                                    \
+  __LLVM_LIBC_CAST(reinterpret_cast, uintptr_t, (t).__attrib)
 
 #endif // LLVM_LIBC_MACROS_PTHREAD_MACRO_H
diff --git a/libc/include/llvm-libc-macros/threads-macros.h b/libc/include/llvm-libc-macros/threads-macros.h
index 2e6ee4316bac1..786efbb79cd9f 100644
--- a/libc/include/llvm-libc-macros/threads-macros.h
+++ b/libc/include/llvm-libc-macros/threads-macros.h
@@ -9,9 +9,11 @@
 #ifndef LLVM_LIBC_MACROS_THREADS_MACRO_H
 #define LLVM_LIBC_MACROS_THREADS_MACRO_H
 
+#include "__llvm-libc-common.h"
 #include "stdint-macros.h"
 
 // LLVM libc extensions
-#define __THRD_GET_ID(t) (reinterpret_cast<uintptr_t>((t).__attrib))
+#define __THRD_GET_ID(t)                                                       \
+  __LLVM_LIBC_CAST(reinterpret_cast, uintptr_t, (t).__attrib)
 
 #endif // LLVM_LIBC_MACROS_THREADS_MACRO_H
diff --git a/libc/test/include/CMakeLists.txt b/libc/test/include/CMakeLists.txt
index 85915f5a2fbda..3244a59d72e04 100644
--- a/libc/test/include/CMakeLists.txt
+++ b/libc/test/include/CMakeLists.txt
@@ -228,6 +228,19 @@ add_libc_test(
     libc.include.llvm-libc-macros.netinet_in_macros
 )
 
+add_libc_test(
+  pthread_test
+  C_TEST
+  UNIT_TEST_ONLY
+  SUITE
+    libc_include_tests
+  SRCS
+    pthread_test.c
+  DEPENDS
+    libc.include.llvm-libc-macros.pthread_macros
+    libc.include.llvm-libc-types.pthread_t
+)
+
 add_libc_test(
   signbit_test
   SUITE
diff --git a/libc/test/include/pthread_test.c b/libc/test/include/pthread_test.c
new file mode 100644
index 0000000000000..fd6f5328e6ac5
--- /dev/null
+++ b/libc/test/include/pthread_test.c
@@ -0,0 +1,18 @@
+//===-- Unittests for pthread macro ---------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "include/llvm-libc-macros/pthread-macros.h"
+#include "include/llvm-libc-types/pthread_t.h"
+
+#include <assert.h>
+
+pthread_t p = PTHREAD_NULL;
+
+int main(void) {
+  assert(__PTHREAD_GET_ID(p) == 0);
+  return 0;
+}



More information about the libc-commits mailing list