[libcxx-commits] [libcxx] [libc++] Introduce a free function __thread_hardware_concurrency() (PR #232284)

Michael G. Kazakov via libcxx-commits libcxx-commits at lists.llvm.org
Thu Oct 15 08:03:38 PDT 2026


https://github.com/mikekazakov updated https://github.com/llvm/llvm-project/pull/232284

>From ed1b1aca39f64b3b1d237889a4cb402361940358 Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Thu, 15 Oct 2026 12:30:56 +0100
Subject: [PATCH 1/4] Introduce a free function __thread_hardware_concurrency()

---
 libcxx/include/CMakeLists.txt                 |  1 +
 libcxx/include/__configuration/availability.h |  6 +++
 .../include/__thread/hardware_concurrency.h   | 37 ++++++++++++++
 libcxx/include/__thread/thread.h              |  9 +++-
 libcxx/include/module.modulemap.in            |  1 +
 libcxx/src/thread.cpp                         | 49 ++++++++++---------
 6 files changed, 79 insertions(+), 24 deletions(-)
 create mode 100644 libcxx/include/__thread/hardware_concurrency.h

diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 9af3d00f36f7e6..0de8b813a1dfb7 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -828,6 +828,7 @@ set(files
   __system_error/system_error.h
   __system_error/throw_system_error.h
   __thread/formatter.h
+  __thread/hardware_concurrency.h
   __thread/id.h
   __thread/jthread.h
   __thread/poll_with_backoff.h
diff --git a/libcxx/include/__configuration/availability.h b/libcxx/include/__configuration/availability.h
index 75d911438e4af1..805a9edab14bbf 100644
--- a/libcxx/include/__configuration/availability.h
+++ b/libcxx/include/__configuration/availability.h
@@ -260,6 +260,12 @@
 
 #endif
 
+// This controls the availability of the free function std::__thread_hardware_concurrency().
+// It has the same semantics as std::[j]thread::hardware_concurrency(), but allows to query this information
+// without depending on std::thread itself.
+#define _LIBCPP_AVAILABILITY_HAS_HARDWARE_CONCURRENCY_FREE_FUNCTION _LIBCPP_INTRODUCED_IN_LLVM_24
+#define _LIBCPP_AVAILABILITY_HARDWARE_CONCURRENCY_FREE_FUNCTION _LIBCPP_INTRODUCED_IN_LLVM_24_ATTRIBUTE
+
 // This controls the availability of the C++26 debugging functions.
 // The platform specific implementation is built in the library.
 #define _LIBCPP_AVAILABILITY_HAS_DEBUGGING _LIBCPP_INTRODUCED_IN_LLVM_24
diff --git a/libcxx/include/__thread/hardware_concurrency.h b/libcxx/include/__thread/hardware_concurrency.h
new file mode 100644
index 00000000000000..c5ee41686a939c
--- /dev/null
+++ b/libcxx/include/__thread/hardware_concurrency.h
@@ -0,0 +1,37 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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 _LIBCPP___THREAD_HARDWARE_CONCURRENCY_H
+#define _LIBCPP___THREAD_HARDWARE_CONCURRENCY_H
+
+#include <__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+_LIBCPP_BEGIN_EXPLICIT_ABI_ANNOTATIONS
+
+#if _LIBCPP_HAS_THREADS
+
+[[__nodiscard__]] _LIBCPP_AVAILABILITY_HARDWARE_CONCURRENCY_FREE_FUNCTION
+    _LIBCPP_EXPORTED_FROM_ABI unsigned __thread_hardware_concurrency() _NOEXCEPT;
+
+#endif // _LIBCPP_HAS_THREADS
+
+_LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___THREAD_HARDWARE_CONCURRENCY_H
diff --git a/libcxx/include/__thread/thread.h b/libcxx/include/__thread/thread.h
index 4fd51c12a6dc2b..314fa2d48f6cee 100644
--- a/libcxx/include/__thread/thread.h
+++ b/libcxx/include/__thread/thread.h
@@ -22,6 +22,7 @@
 #include <__memory/unique_ptr.h>
 #include <__mutex/mutex.h>
 #include <__system_error/throw_system_error.h>
+#include <__thread/hardware_concurrency.h>
 #include <__thread/id.h>
 #include <__thread/support.h>
 #include <__type_traits/decay.h>
@@ -262,7 +263,13 @@ class _LIBCPP_EXPORTED_FROM_ABI thread {
   [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI id get_id() const _NOEXCEPT { return __libcpp_thread_get_id(&__t_); }
   [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() _NOEXCEPT { return __t_; }
 
-  [[__nodiscard__]] static unsigned hardware_concurrency() _NOEXCEPT;
+#  if defined(_LIBCPP_BUILDING_LIBRARY) || !_LIBCPP_AVAILABILITY_HAS_HARDWARE_CONCURRENCY_FREE_FUNCTION
+  [[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI static unsigned hardware_concurrency() _NOEXCEPT;
+#  else
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static unsigned hardware_concurrency() _NOEXCEPT {
+    return std::__thread_hardware_concurrency();
+  }
+#  endif
 };
 
 inline _LIBCPP_HIDE_FROM_ABI void swap(thread& __x, thread& __y) _NOEXCEPT { __x.swap(__y); }
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 2f6640f8469a5b..460299aea1ed04 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -2202,6 +2202,7 @@ module std {
 
   module thread {
     module formatter              { header "__thread/formatter.h" }
+    module hardware_concurrency   { header "__thread/hardware_concurrency.h" }
     module id                     { header "__thread/id.h" }
     module jthread                { header "__thread/jthread.h" }
     module poll_with_backoff      { header "__thread/poll_with_backoff.h" }
diff --git a/libcxx/src/thread.cpp b/libcxx/src/thread.cpp
index 7b0890858e9d64..e931c9288710d1 100644
--- a/libcxx/src/thread.cpp
+++ b/libcxx/src/thread.cpp
@@ -64,29 +64,8 @@ void thread::detach() {
     std::__throw_system_error(ec, "thread::detach failed");
 }
 
-unsigned thread::hardware_concurrency() noexcept {
-#if defined(_SC_NPROCESSORS_ONLN)
-  long result = sysconf(_SC_NPROCESSORS_ONLN);
-  // sysconf returns -1 if the name is invalid, the option does not exist or
-  // does not have a definite limit.
-  // if sysconf returns some other negative number, we have no idea
-  // what is going on. Default to something safe.
-  if (result < 0)
-    return 0;
-  return static_cast<unsigned>(result);
-#elif defined(_WIN32)
-  return static_cast<unsigned>(GetActiveProcessorCount(ALL_PROCESSOR_GROUPS));
-#else // defined(CTL_HW) && defined(HW_NCPU)
-  // TODO: grovel through /proc or check cpuid on x86 and similar
-  // instructions on other architectures.
-#  if defined(_LIBCPP_WARNING)
-  _LIBCPP_WARNING("hardware_concurrency not yet implemented")
-#  else
-#    warning hardware_concurrency not yet implemented
-#  endif
-  return 0; // Means not computable [thread.thread.static]
-#endif // defined(CTL_HW) && defined(HW_NCPU)
-}
+// Defined here only for backwards compatibility
+unsigned thread::hardware_concurrency() noexcept { return __thread_hardware_concurrency(); }
 
 namespace this_thread {
 
@@ -171,5 +150,29 @@ void __thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m
 
 void __thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s) { __p_->__make_ready_at_thread_exit(__s); }
 
+unsigned __thread_hardware_concurrency() noexcept {
+#if defined(_SC_NPROCESSORS_ONLN)
+  long result = sysconf(_SC_NPROCESSORS_ONLN);
+  // sysconf returns -1 if the name is invalid, the option does not exist or
+  // does not have a definite limit.
+  // if sysconf returns some other negative number, we have no idea
+  // what is going on. Default to something safe.
+  if (result < 0)
+    return 0;
+  return static_cast<unsigned>(result);
+#elif defined(_WIN32)
+  return static_cast<unsigned>(GetActiveProcessorCount(ALL_PROCESSOR_GROUPS));
+#else // defined(CTL_HW) && defined(HW_NCPU)
+  // TODO: grovel through /proc or check cpuid on x86 and similar
+  // instructions on other architectures.
+#  if defined(_LIBCPP_WARNING)
+  _LIBCPP_WARNING("hardware_concurrency not yet implemented")
+#  else
+#    warning hardware_concurrency not yet implemented
+#  endif
+  return 0; // Means not computable [thread.thread.static]
+#endif // defined(CTL_HW) && defined(HW_NCPU)
+}
+
 _LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS
 _LIBCPP_END_NAMESPACE_STD

>From ec805b15beb7aa95e192392746c5729f3cd3f213 Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Thu, 15 Oct 2026 12:50:12 +0100
Subject: [PATCH 2/4] Updating the abilist

---
 ...nknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
index 69c32bd5be8775..880cb2504c0843 100644
--- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1234,6 +1234,7 @@
 {'is_defined': True, 'name': '_ZNSt3__126__atomic_wait_global_tableEPKvi', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__127__from_chars_floating_pointIdEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__127__from_chars_floating_pointIfEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__129__thread_hardware_concurrencyEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__132__atomic_notify_all_global_tableEPKv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__132__atomic_notify_one_global_tableEPKv', 'type': 'FUNC'}

>From 8c69b9379f15cfde6fe4a3ee9958ac8936afa4ee Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Thu, 15 Oct 2026 16:02:52 +0100
Subject: [PATCH 3/4] Updated more abilists

---
 ...m64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist | 1 +
 ...-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist | 1 +
 .../powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist | 1 +
 ...owerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist | 1 +
 ...-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist | 1 +
 ...nown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist | 1 +
 6 files changed, 6 insertions(+)

diff --git a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
index 74e0af974e4538..186159115eaced 100644
--- a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1586,6 +1586,7 @@
 {'is_defined': True, 'name': '__ZNSt3__126__atomic_wait_global_tableEPKvx', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__127__from_chars_floating_pointIdEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__127__from_chars_floating_pointIfEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__129__thread_hardware_concurrencyEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__132__atomic_notify_all_global_tableEPKv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__132__atomic_notify_one_global_tableEPKv', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/i686-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/i686-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist
index 1b0cd758bfcf36..f423cab70fff68 100644
--- a/libcxx/lib/abi/i686-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/i686-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1223,6 +1223,7 @@
 {'is_defined': True, 'name': '_ZNSt6__ndk126__atomic_wait_global_tableEPKvi', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk127__from_chars_floating_pointIdEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk127__from_chars_floating_pointIfEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt6__ndk129__thread_hardware_concurrencyEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk132__atomic_notify_all_global_tableEPKv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk132__atomic_notify_one_global_tableEPKv', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
index c61db56dc2b904..d121aba28c6626 100644
--- a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -573,6 +573,7 @@
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__126__atomic_wait_global_tableEPKvi', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__129__thread_hardware_concurrencyEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__132__atomic_notify_all_global_tableEPKv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__132__atomic_notify_one_global_tableEPKv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
index 7663aa877a096f..69b0833420bc82 100644
--- a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -573,6 +573,7 @@
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__126__atomic_wait_global_tableEPKvl', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__129__thread_hardware_concurrencyEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__132__atomic_notify_all_global_tableEPKv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__132__atomic_notify_one_global_tableEPKv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist
index 536614e0ccfa64..cc027ffd7eb0ae 100644
--- a/libcxx/lib/abi/x86_64-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1223,6 +1223,7 @@
 {'is_defined': True, 'name': '_ZNSt6__ndk126__atomic_wait_global_tableEPKvi', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk127__from_chars_floating_pointIdEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk127__from_chars_floating_pointIfEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt6__ndk129__thread_hardware_concurrencyEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk132__atomic_notify_all_global_tableEPKv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk132__atomic_notify_one_global_tableEPKv', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
index b6850b2ec80938..b5187b4ec82d45 100644
--- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
@@ -1205,6 +1205,7 @@
 {'is_defined': True, 'name': '_ZNSt3__126__atomic_wait_global_tableEPKvi', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__127__from_chars_floating_pointIdEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__127__from_chars_floating_pointIfEENS_19__from_chars_resultIT_EEPKcS5_NS_12chars_formatE', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__129__thread_hardware_concurrencyEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__132__atomic_notify_all_global_tableEPKv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__132__atomic_notify_one_global_tableEPKv', 'type': 'FUNC'}

>From 16aa57075de237102c12c83213c138965c8c230d Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Thu, 15 Oct 2026 16:03:16 +0100
Subject: [PATCH 4/4] Don't put _LIBCPP_EXPORTED_FROM_ABI twice

---
 libcxx/include/__thread/thread.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/include/__thread/thread.h b/libcxx/include/__thread/thread.h
index 314fa2d48f6cee..89c1fefd654043 100644
--- a/libcxx/include/__thread/thread.h
+++ b/libcxx/include/__thread/thread.h
@@ -264,7 +264,7 @@ class _LIBCPP_EXPORTED_FROM_ABI thread {
   [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() _NOEXCEPT { return __t_; }
 
 #  if defined(_LIBCPP_BUILDING_LIBRARY) || !_LIBCPP_AVAILABILITY_HAS_HARDWARE_CONCURRENCY_FREE_FUNCTION
-  [[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI static unsigned hardware_concurrency() _NOEXCEPT;
+  [[__nodiscard__]] static unsigned hardware_concurrency() _NOEXCEPT;
 #  else
   [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static unsigned hardware_concurrency() _NOEXCEPT {
     return std::__thread_hardware_concurrency();



More information about the libcxx-commits mailing list