From 3769bce12cf531f07c5859c395893cf437b7f5a4 Mon Sep 17 00:00:00 2001 From: notaxeltv Date: Wed, 14 Oct 2026 23:33:45 +0200 Subject: [PATCH 1/2] feat(libc): export std::thread::hardware_concurrency Absent PPSA34015 import CHrhwd8QSBs; forward to host hardware_concurrency. Co-authored-by: Cursor --- core/libs/prx/libc/CMakeLists.txt | 10 ++++++ core/libs/prx/libc/src/Threads.cpp | 4 +++ .../GuestStdThreadHardwareConcurrency.cpp | 33 +++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 core/libs/tests/GuestStdThreadHardwareConcurrency.cpp diff --git a/core/libs/prx/libc/CMakeLists.txt b/core/libs/prx/libc/CMakeLists.txt index dfbe462ee1..233ff92c44 100644 --- a/core/libs/prx/libc/CMakeLists.txt +++ b/core/libs/prx/libc/CMakeLists.txt @@ -451,6 +451,16 @@ if(BUILD_TESTING) set_tests_properties(guest_libc_threads PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() + add_test_executable(guest_std_thread_hardware_concurrency_tests ${LIBS_INCLUDE_DIR}/tests/GuestStdThreadHardwareConcurrency.cpp) + target_include_directories(guest_std_thread_hardware_concurrency_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_std_thread_hardware_concurrency_tests PRIVATE libc) + configure_windows_unwind(guest_std_thread_hardware_concurrency_tests) + add_test(NAME guest_std_thread_hardware_concurrency COMMAND guest_std_thread_hardware_concurrency_tests) + set_tests_properties(guest_std_thread_hardware_concurrency PROPERTIES TIMEOUT 20) + if(WIN32) + set_tests_properties(guest_std_thread_hardware_concurrency PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() add_test_executable(guest_libc_static_imports_tests ${LIBS_INCLUDE_DIR}/tests/GuestLibcStaticImports.cpp) target_include_directories(guest_libc_static_imports_tests PRIVATE ${LIBS_INCLUDE_DIR}) target_link_libraries(guest_libc_static_imports_tests PRIVATE libc) diff --git a/core/libs/prx/libc/src/Threads.cpp b/core/libs/prx/libc/src/Threads.cpp index 1e7ea35688..4933672426 100644 --- a/core/libs/prx/libc/src/Threads.cpp +++ b/core/libs/prx/libc/src/Threads.cpp @@ -350,6 +350,10 @@ int SignalCondition_nid_no_patch(void** handle) { return threadSuccess; } +unsigned APS5_VABI _ZNSt6thread20hardware_concurrencyEv_nid_postfix() { + return std::thread::hardware_concurrency(); +} + int APS5_VABI _Thrd_sleep_nid_postfix(const Xtime* target, Xtime*) { if (!target) APS5_INVALID_ARG_EX; diff --git a/core/libs/tests/GuestStdThreadHardwareConcurrency.cpp b/core/libs/tests/GuestStdThreadHardwareConcurrency.cpp new file mode 100644 index 0000000000..fe6a695747 --- /dev/null +++ b/core/libs/tests/GuestStdThreadHardwareConcurrency.cpp @@ -0,0 +1,33 @@ +#include "prx/libc/include/general/VabiMacros.hpp" +#include +#include +#ifdef _WIN32 +#include +#else +#include +#endif + +extern "C" unsigned APS5_VABI _ZNSt6thread20hardware_concurrencyEv_nid_postfix(); + +int main() { + unsigned expected = 0; +#ifdef _WIN32 + SYSTEM_INFO info{}; + GetSystemInfo(&info); + expected = info.dwNumberOfProcessors; +#else + const long processors = sysconf(_SC_NPROCESSORS_ONLN); + if (processors > 0) expected = static_cast(processors); +#endif + const unsigned result = _ZNSt6thread20hardware_concurrencyEv_nid_postfix(); + if (expected != 0 && result != expected) { + std::fprintf(stderr, "guest processor hint %u differs from OS count %u\n", result, expected); + return 1; + } + if (result != std::thread::hardware_concurrency()) { + std::fprintf(stderr, "guest processor hint %u differs from std::thread::hardware_concurrency %u\n", + result, std::thread::hardware_concurrency()); + return 1; + } + return 0; +} From b443b9f9f011381019a70b31ca57ee747d819ec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Franch?= Date: Sat, 24 Oct 2026 03:31:05 +0200 Subject: [PATCH 2/2] fix(libc): compare only with std::thread::hardware_concurrency, record host count in debt Co-Authored-By: Claude Sonnet 5.5 --- .../GuestStdThreadHardwareConcurrency.cpp | 18 ------------------ docs/dev/debt/libc.md | 1 + 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/core/libs/tests/GuestStdThreadHardwareConcurrency.cpp b/core/libs/tests/GuestStdThreadHardwareConcurrency.cpp index fe6a695747..6b53d172cf 100644 --- a/core/libs/tests/GuestStdThreadHardwareConcurrency.cpp +++ b/core/libs/tests/GuestStdThreadHardwareConcurrency.cpp @@ -1,29 +1,11 @@ #include "prx/libc/include/general/VabiMacros.hpp" #include #include -#ifdef _WIN32 -#include -#else -#include -#endif extern "C" unsigned APS5_VABI _ZNSt6thread20hardware_concurrencyEv_nid_postfix(); int main() { - unsigned expected = 0; -#ifdef _WIN32 - SYSTEM_INFO info{}; - GetSystemInfo(&info); - expected = info.dwNumberOfProcessors; -#else - const long processors = sysconf(_SC_NPROCESSORS_ONLN); - if (processors > 0) expected = static_cast(processors); -#endif const unsigned result = _ZNSt6thread20hardware_concurrencyEv_nid_postfix(); - if (expected != 0 && result != expected) { - std::fprintf(stderr, "guest processor hint %u differs from OS count %u\n", result, expected); - return 1; - } if (result != std::thread::hardware_concurrency()) { std::fprintf(stderr, "guest processor hint %u differs from std::thread::hardware_concurrency %u\n", result, std::thread::hardware_concurrency()); diff --git a/docs/dev/debt/libc.md b/docs/dev/debt/libc.md index fbc52c5e51..dbec0ee78f 100644 --- a/docs/dev/debt/libc.md +++ b/docs/dev/debt/libc.md @@ -60,6 +60,7 @@ ### Functional - [_Cosh](../../../core/libs/prx/libc/src/Math.cpp) (libc) follows the two-argument Dinkumware CRT helper used by `std::complex`, including a scaled large-finite-input path; the signature, exact result and floating-point exception behavior are not verified against the console. +- [std::thread::hardware_concurrency](../../../core/libs/prx/libc/src/Threads.cpp) (libc, NID `CHrhwd8QSBs`) returns the host's `std::thread::hardware_concurrency()` (which may be 0 when unknown) instead of the console's processor count; no reference implements it and the value a title expects (PPSA34015 imports it) is unverified. - [fmodf](../../../core/libs/prx/libc/src/Math.cpp) (libc) - console `errno`, exception flags and NaN payloads remain unverified. The wrapper preserves `errno` like the existing double `fmod`, following FreeBSD 11.4 [`e_fmodf.c`](https://github.com/freebsd/freebsd-src/blob/release/11.4.0/lib/msun/src/e_fmodf.c); host `std::fmod` still supplies the result and exception flags. - [_FSinh and _FCosh](../../../core/libs/prx/libc/src/Math.cpp) (libc) finite results are not verified bit for bit against the console: the scaled product uses the host's binary64 hyperbolic function before rounding to binary32, rather than the float rational and `_FExp` sequence in PRAGMATA's bundled `libc.prx`. NaN preference and payloads, signed zeros, infinite operands and the range-error thresholds follow that binary's instructions; the system `libSceLibcInternal` implementation and nondefault flush-to-zero modes are unverified.