[libcxx-commits] [libcxx] [libc++] Make __thread_hardware_concurrency() an alias to an existing symbol (PR #234575)

Michael G. Kazakov via libcxx-commits libcxx-commits at lists.llvm.org
Sat Oct 24 02:49:33 PDT 2026


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

>From 3a4c4d806427dc2b789254f5805d5eaf76664d1e Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Thu, 22 Oct 2026 11:49:40 +0100
Subject: [PATCH 1/4] Make __thread_hardware_concurrency() an alias to an
 existing symbol

---
 libcxx/include/__configuration/availability.h |  6 ---
 .../include/__thread/hardware_concurrency.h   | 28 ++++++++++-
 libcxx/include/__thread/thread.h              |  7 ---
 libcxx/lib/abi/CHANGELOG.TXT                  |  6 ---
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |  1 -
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |  1 -
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |  1 -
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |  1 -
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |  1 -
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |  1 -
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |  1 -
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |  1 -
 ...xxabi.v1.stable.noexceptions.nonew.abilist |  1 -
 libcxx/src/thread.cpp                         | 49 +++++++++----------
 .../tmp.hardware_concurrency_func.pass.cpp    | 27 ++++++++++
 15 files changed, 76 insertions(+), 56 deletions(-)
 create mode 100644 libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.static/tmp.hardware_concurrency_func.pass.cpp

diff --git a/libcxx/include/__configuration/availability.h b/libcxx/include/__configuration/availability.h
index 805a9edab14bb..75d911438e4af 100644
--- a/libcxx/include/__configuration/availability.h
+++ b/libcxx/include/__configuration/availability.h
@@ -260,12 +260,6 @@
 
 #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
index c5ee41686a939..043e3883bec6f 100644
--- a/libcxx/include/__thread/hardware_concurrency.h
+++ b/libcxx/include/__thread/hardware_concurrency.h
@@ -24,8 +24,32 @@ _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;
+// __thread_hardware_concurrency() has the same semantics as std::[j]thread::hardware_concurrency(), but allows querying
+// this information without depending on std::thread itself. Rather than adding a new symbol to the built library, it is
+// declared as an alias of std::thread::hardware_concurrency(), which has always been part of the ABI.
+
+#  define _LIBCPP_THREAD_ABI_NAMESPACE_STR _LIBCPP_TOSTRING(_LIBCPP_ABI_NAMESPACE)
+
+#  ifdef _LIBCPP_ABI_MICROSOFT
+#    define _LIBCPP_THREAD_HARDWARE_CONCURRENCY_SYMBOL                                                                 \
+      "?hardware_concurrency at thread@" _LIBCPP_THREAD_ABI_NAMESPACE_STR "@std@@SAIXZ"
+#  else
+// The Itanium mangling of a namespace name is prefixed with its length, which can't be computed by the preprocessor.
+#    define _LIBCPP_THREAD_ABI_NAMESPACE_LENGTH___1 3
+#    define _LIBCPP_THREAD_ABI_NAMESPACE_LENGTH___2 3
+#    define _LIBCPP_THREAD_ABI_NAMESPACE_LENGTH___ndk1 6
+#    define _LIBCPP_THREAD_ABI_NAMESPACE_LENGTH _LIBCPP_CONCAT(_LIBCPP_THREAD_ABI_NAMESPACE_LENGTH_, _LIBCPP_ABI_NAMESPACE)
+#    if _LIBCPP_THREAD_ABI_NAMESPACE_LENGTH == 0
+#      error "Unknown length of _LIBCPP_ABI_NAMESPACE, add it to <__thread/hardware_concurrency.h>"
+#    endif
+#    define _LIBCPP_THREAD_HARDWARE_CONCURRENCY_SYMBOL                                                                 \
+      _LIBCPP_TOSTRING(__USER_LABEL_PREFIX__)                                                                          \
+      "_ZNSt" _LIBCPP_TOSTRING(_LIBCPP_THREAD_ABI_NAMESPACE_LENGTH) _LIBCPP_THREAD_ABI_NAMESPACE_STR                   \
+      "6thread20hardware_concurrencyEv"
+#  endif
+
+[[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI unsigned __thread_hardware_concurrency() _NOEXCEPT
+    __asm__(_LIBCPP_THREAD_HARDWARE_CONCURRENCY_SYMBOL);
 
 #endif // _LIBCPP_HAS_THREADS
 
diff --git a/libcxx/include/__thread/thread.h b/libcxx/include/__thread/thread.h
index 750a2d2a59ce7..42427cb63269f 100644
--- a/libcxx/include/__thread/thread.h
+++ b/libcxx/include/__thread/thread.h
@@ -263,14 +263,7 @@ 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_; }
 
-#  if defined(_LIBCPP_BUILDING_LIBRARY) || !_LIBCPP_AVAILABILITY_HAS_HARDWARE_CONCURRENCY_FREE_FUNCTION
   [[__nodiscard__]] static unsigned hardware_concurrency() _NOEXCEPT;
-#  else
-  // Always inline to avoid an ODR violation with the symbol defined in the built library
-  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE 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/lib/abi/CHANGELOG.TXT b/libcxx/lib/abi/CHANGELOG.TXT
index 05f4a14540270..85d2e596ed51f 100644
--- a/libcxx/lib/abi/CHANGELOG.TXT
+++ b/libcxx/lib/abi/CHANGELOG.TXT
@@ -16,12 +16,6 @@ New entries should be added directly below the "Version" header.
 Version 24.0
 ------------
 
-* [libc++] Add <__thread/hardware_concurrency.h> __thread_hardware_concurrency()
-
-  All platforms
-  -------------
-  Symbol added: _ZNSt3__129__thread_hardware_concurrencyEv
-
 * [libc++] Remove locale::id::__next_id from the ABI
 
   `__next_id` is only ever used inside the dylib, so we can avoid making it public.
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 186159115eace..74e0af974e453 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,7 +1586,6 @@
 {'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 f423cab70fff6..1b0cd758bfcf3 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,7 +1223,6 @@
 {'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 d121aba28c662..c61db56dc2b90 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,7 +573,6 @@
 {'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 69b0833420bc8..7663aa877a096 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,7 +573,6 @@
 {'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-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
index e290f961ba632..00b5949f843ac 100644
--- a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1579,7 +1579,6 @@
 {'is_defined': True, 'name': '__ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__127__from_chars_floating_pointEPKcS1_RdNS_12chars_formatE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__127__from_chars_floating_pointEPKcS1_RfNS_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__destroy_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__134__construct_barrier_algorithm_baseERl', '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 cc027ffd7eb0a..536614e0ccfa6 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,7 +1223,6 @@
 {'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-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
index eb1638841be7a..d655541acdc8d 100644
--- a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1236,7 +1236,6 @@
 {'is_defined': True, 'name': '_ZNSt3__126__atomic_wait_global_tableEPKvl', '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/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 880cb2504c084..69c32bd5be877 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,7 +1234,6 @@
 {'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'}
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 b5187b4ec82d4..b6850b2ec8093 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,7 +1205,6 @@
 {'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'}
diff --git a/libcxx/src/thread.cpp b/libcxx/src/thread.cpp
index 17b36c15f5581..7b0890858e9d6 100644
--- a/libcxx/src/thread.cpp
+++ b/libcxx/src/thread.cpp
@@ -64,8 +64,29 @@ void thread::detach() {
     std::__throw_system_error(ec, "thread::detach failed");
 }
 
-// Defined here only for backwards compatibility.
-unsigned thread::hardware_concurrency() noexcept { return std::__thread_hardware_concurrency(); }
+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)
+}
 
 namespace this_thread {
 
@@ -150,29 +171,5 @@ 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
diff --git a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.static/tmp.hardware_concurrency_func.pass.cpp b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.static/tmp.hardware_concurrency_func.pass.cpp
new file mode 100644
index 0000000000000..e380b4470ecc3
--- /dev/null
+++ b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.static/tmp.hardware_concurrency_func.pass.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// UNSUPPORTED: no-threads
+
+// <thread>
+
+// class thread
+
+// unsigned hardware_concurrency();
+
+#include <thread>
+#include <__thread/hardware_concurrency.h>
+#include <cassert>
+
+#include "test_macros.h"
+
+int main(int, char**) {
+  assert(std::thread::hardware_concurrency() == std::__thread_hardware_concurrency());
+
+  return 0;
+}

>From 900da96428da3dabd92878de35dae484740d6adc Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Thu, 22 Oct 2026 11:54:35 +0100
Subject: [PATCH 2/4] clang-format

---
 libcxx/include/__thread/hardware_concurrency.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/__thread/hardware_concurrency.h b/libcxx/include/__thread/hardware_concurrency.h
index 043e3883bec6f..c378cba66059a 100644
--- a/libcxx/include/__thread/hardware_concurrency.h
+++ b/libcxx/include/__thread/hardware_concurrency.h
@@ -38,14 +38,15 @@ _LIBCPP_BEGIN_EXPLICIT_ABI_ANNOTATIONS
 #    define _LIBCPP_THREAD_ABI_NAMESPACE_LENGTH___1 3
 #    define _LIBCPP_THREAD_ABI_NAMESPACE_LENGTH___2 3
 #    define _LIBCPP_THREAD_ABI_NAMESPACE_LENGTH___ndk1 6
-#    define _LIBCPP_THREAD_ABI_NAMESPACE_LENGTH _LIBCPP_CONCAT(_LIBCPP_THREAD_ABI_NAMESPACE_LENGTH_, _LIBCPP_ABI_NAMESPACE)
+#    define _LIBCPP_THREAD_ABI_NAMESPACE_LENGTH                                                                        \
+      _LIBCPP_CONCAT(_LIBCPP_THREAD_ABI_NAMESPACE_LENGTH_, _LIBCPP_ABI_NAMESPACE)
 #    if _LIBCPP_THREAD_ABI_NAMESPACE_LENGTH == 0
 #      error "Unknown length of _LIBCPP_ABI_NAMESPACE, add it to <__thread/hardware_concurrency.h>"
 #    endif
 #    define _LIBCPP_THREAD_HARDWARE_CONCURRENCY_SYMBOL                                                                 \
       _LIBCPP_TOSTRING(__USER_LABEL_PREFIX__)                                                                          \
       "_ZNSt" _LIBCPP_TOSTRING(_LIBCPP_THREAD_ABI_NAMESPACE_LENGTH) _LIBCPP_THREAD_ABI_NAMESPACE_STR                   \
-      "6thread20hardware_concurrencyEv"
+          "6thread20hardware_concurrencyEv"
 #  endif
 
 [[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI unsigned __thread_hardware_concurrency() _NOEXCEPT

>From a686d63e07d0d1096121e95b8f0e48b973e1d93b Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Thu, 22 Oct 2026 12:42:46 +0100
Subject: [PATCH 3/4] Guard with C++11+, simplify the logic

---
 libcxx/CMakeLists.txt                         |  2 ++
 libcxx/include/__config_site.in               |  1 +
 .../include/__thread/hardware_concurrency.h   | 21 +++++--------------
 .../tmp.hardware_concurrency_func.pass.cpp    |  1 +
 4 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt
index d163f0f579c39..7dc427dae77b2 100644
--- a/libcxx/CMakeLists.txt
+++ b/libcxx/CMakeLists.txt
@@ -230,6 +230,7 @@ set(LIBCXX_ABI_NAMESPACE "__${LIBCXX_ABI_VERSION}" CACHE STRING "The inline ABI
 if (NOT LIBCXX_ABI_NAMESPACE MATCHES "__.*")
   message(FATAL_ERROR "LIBCXX_ABI_NAMESPACE must be a reserved identifier, got '${LIBCXX_ABI_NAMESPACE}'.")
 endif()
+string(LENGTH "${LIBCXX_ABI_NAMESPACE}" LIBCPP_ABI_NAMESPACE_LEN)
 set(LIBCXX_AVAILABILITY_MINIMUM_HEADER_VERSION "2" CACHE STRING
   "Minimum version of the libc++ headers that are allowed to be used by binaries linked against the libc++ library. This
    version must correspond to the major version of an LLVM release.")
@@ -741,6 +742,7 @@ endfunction()
 # Configuration file flags =====================================================
 config_define(${LIBCXX_ABI_VERSION} _LIBCPP_ABI_VERSION)
 config_define(${LIBCXX_ABI_NAMESPACE} _LIBCPP_ABI_NAMESPACE)
+config_define(${LIBCPP_ABI_NAMESPACE_LEN} _LIBCPP_ABI_NAMESPACE_LEN)
 config_define(${LIBCXX_ABI_FORCE_ITANIUM} _LIBCPP_ABI_FORCE_ITANIUM)
 config_define(${LIBCXX_ABI_FORCE_MICROSOFT} _LIBCPP_ABI_FORCE_MICROSOFT)
 config_define(${LIBCXX_ENABLE_THREADS} _LIBCPP_HAS_THREADS)
diff --git a/libcxx/include/__config_site.in b/libcxx/include/__config_site.in
index e6e33a2eeb2a9..785c1562de7bd 100644
--- a/libcxx/include/__config_site.in
+++ b/libcxx/include/__config_site.in
@@ -11,6 +11,7 @@
 
 #cmakedefine _LIBCPP_ABI_VERSION @_LIBCPP_ABI_VERSION@
 #cmakedefine _LIBCPP_ABI_NAMESPACE @_LIBCPP_ABI_NAMESPACE@
+#cmakedefine _LIBCPP_ABI_NAMESPACE_LEN @_LIBCPP_ABI_NAMESPACE_LEN@
 #cmakedefine01 _LIBCPP_ABI_FORCE_ITANIUM
 #cmakedefine01 _LIBCPP_ABI_FORCE_MICROSOFT
 #cmakedefine01 _LIBCPP_HAS_THREADS
diff --git a/libcxx/include/__thread/hardware_concurrency.h b/libcxx/include/__thread/hardware_concurrency.h
index c378cba66059a..0e90258159a5b 100644
--- a/libcxx/include/__thread/hardware_concurrency.h
+++ b/libcxx/include/__thread/hardware_concurrency.h
@@ -22,37 +22,26 @@ _LIBCPP_PUSH_MACROS
 _LIBCPP_BEGIN_NAMESPACE_STD
 _LIBCPP_BEGIN_EXPLICIT_ABI_ANNOTATIONS
 
-#if _LIBCPP_HAS_THREADS
+#if _LIBCPP_STD_VER >= 11 && _LIBCPP_HAS_THREADS
 
 // __thread_hardware_concurrency() has the same semantics as std::[j]thread::hardware_concurrency(), but allows querying
 // this information without depending on std::thread itself. Rather than adding a new symbol to the built library, it is
 // declared as an alias of std::thread::hardware_concurrency(), which has always been part of the ABI.
 
-#  define _LIBCPP_THREAD_ABI_NAMESPACE_STR _LIBCPP_TOSTRING(_LIBCPP_ABI_NAMESPACE)
-
 #  ifdef _LIBCPP_ABI_MICROSOFT
 #    define _LIBCPP_THREAD_HARDWARE_CONCURRENCY_SYMBOL                                                                 \
-      "?hardware_concurrency at thread@" _LIBCPP_THREAD_ABI_NAMESPACE_STR "@std@@SAIXZ"
+      "?hardware_concurrency at thread@" _LIBCPP_TOSTRING(_LIBCPP_ABI_NAMESPACE) "@std@@SAIXZ"
 #  else
-// The Itanium mangling of a namespace name is prefixed with its length, which can't be computed by the preprocessor.
-#    define _LIBCPP_THREAD_ABI_NAMESPACE_LENGTH___1 3
-#    define _LIBCPP_THREAD_ABI_NAMESPACE_LENGTH___2 3
-#    define _LIBCPP_THREAD_ABI_NAMESPACE_LENGTH___ndk1 6
-#    define _LIBCPP_THREAD_ABI_NAMESPACE_LENGTH                                                                        \
-      _LIBCPP_CONCAT(_LIBCPP_THREAD_ABI_NAMESPACE_LENGTH_, _LIBCPP_ABI_NAMESPACE)
-#    if _LIBCPP_THREAD_ABI_NAMESPACE_LENGTH == 0
-#      error "Unknown length of _LIBCPP_ABI_NAMESPACE, add it to <__thread/hardware_concurrency.h>"
-#    endif
 #    define _LIBCPP_THREAD_HARDWARE_CONCURRENCY_SYMBOL                                                                 \
       _LIBCPP_TOSTRING(__USER_LABEL_PREFIX__)                                                                          \
-      "_ZNSt" _LIBCPP_TOSTRING(_LIBCPP_THREAD_ABI_NAMESPACE_LENGTH) _LIBCPP_THREAD_ABI_NAMESPACE_STR                   \
-          "6thread20hardware_concurrencyEv"
+      "_ZNSt" _LIBCPP_TOSTRING(_LIBCPP_ABI_NAMESPACE_LEN)                                                              \
+          _LIBCPP_TOSTRING(_LIBCPP_ABI_NAMESPACE) "6thread20hardware_concurrencyEv"
 #  endif
 
 [[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI unsigned __thread_hardware_concurrency() _NOEXCEPT
     __asm__(_LIBCPP_THREAD_HARDWARE_CONCURRENCY_SYMBOL);
 
-#endif // _LIBCPP_HAS_THREADS
+#endif // _LIBCPP_STD_VER >= 11 && _LIBCPP_HAS_THREADS
 
 _LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.static/tmp.hardware_concurrency_func.pass.cpp b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.static/tmp.hardware_concurrency_func.pass.cpp
index e380b4470ecc3..0b4ad0b69aaf3 100644
--- a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.static/tmp.hardware_concurrency_func.pass.cpp
+++ b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.static/tmp.hardware_concurrency_func.pass.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 //
 // UNSUPPORTED: no-threads
+// UNSUPPORTED: c++03
 
 // <thread>
 

>From fcff7eb71eb6c3571fb882ab5f9d4112fc50e8bf Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Sat, 24 Oct 2026 10:49:17 +0100
Subject: [PATCH 4/4] Removed the temporary added test

---
 .../include/__thread/hardware_concurrency.h   |  4 +--
 .../tmp.hardware_concurrency_func.pass.cpp    | 28 -------------------
 2 files changed, 2 insertions(+), 30 deletions(-)
 delete mode 100644 libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.static/tmp.hardware_concurrency_func.pass.cpp

diff --git a/libcxx/include/__thread/hardware_concurrency.h b/libcxx/include/__thread/hardware_concurrency.h
index 0e90258159a5b..9fba8a30fba0c 100644
--- a/libcxx/include/__thread/hardware_concurrency.h
+++ b/libcxx/include/__thread/hardware_concurrency.h
@@ -25,8 +25,8 @@ _LIBCPP_BEGIN_EXPLICIT_ABI_ANNOTATIONS
 #if _LIBCPP_STD_VER >= 11 && _LIBCPP_HAS_THREADS
 
 // __thread_hardware_concurrency() has the same semantics as std::[j]thread::hardware_concurrency(), but allows querying
-// this information without depending on std::thread itself. Rather than adding a new symbol to the built library, it is
-// declared as an alias of std::thread::hardware_concurrency(), which has always been part of the ABI.
+// this information without depending on std::thread itself. This function is an alias to
+// std::thread::hardware_concurrency(), which is a part of the ABI.
 
 #  ifdef _LIBCPP_ABI_MICROSOFT
 #    define _LIBCPP_THREAD_HARDWARE_CONCURRENCY_SYMBOL                                                                 \
diff --git a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.static/tmp.hardware_concurrency_func.pass.cpp b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.static/tmp.hardware_concurrency_func.pass.cpp
deleted file mode 100644
index 0b4ad0b69aaf3..0000000000000
--- a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.static/tmp.hardware_concurrency_func.pass.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-//
-// UNSUPPORTED: no-threads
-// UNSUPPORTED: c++03
-
-// <thread>
-
-// class thread
-
-// unsigned hardware_concurrency();
-
-#include <thread>
-#include <__thread/hardware_concurrency.h>
-#include <cassert>
-
-#include "test_macros.h"
-
-int main(int, char**) {
-  assert(std::thread::hardware_concurrency() == std::__thread_hardware_concurrency());
-
-  return 0;
-}



More information about the libcxx-commits mailing list