[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