diff --git a/core/libs/prx/libc/CMakeLists.txt b/core/libs/prx/libc/CMakeLists.txt index 30aaf71ba88..ad4b063782e 100644 --- a/core/libs/prx/libc/CMakeLists.txt +++ b/core/libs/prx/libc/CMakeLists.txt @@ -46,6 +46,16 @@ if(WIN32) endif() if(BUILD_TESTING) + add_test_executable(guest_hardware_concurrency_tests ${LIBS_INCLUDE_DIR}/tests/GuestHardwareConcurrency.cpp) + target_include_directories(guest_hardware_concurrency_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(guest_hardware_concurrency_tests PRIVATE libc) + configure_windows_unwind(guest_hardware_concurrency_tests) + add_test(NAME guest_hardware_concurrency COMMAND guest_hardware_concurrency_tests) + set_tests_properties(guest_hardware_concurrency PROPERTIES TIMEOUT 30) + if(WIN32) + set_tests_properties(guest_hardware_concurrency PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() add_test_executable(guest_time_conversion_tests ${LIBS_INCLUDE_DIR}/tests/GuestTimeConversion.cpp) target_include_directories(guest_time_conversion_tests PRIVATE ${LIBS_INCLUDE_DIR}) target_link_libraries(guest_time_conversion_tests PRIVATE libc) diff --git a/core/libs/prx/libc/src/CxxAbiSupport.cpp b/core/libs/prx/libc/src/CxxAbiSupport.cpp index c8e7e0801cc..a39b5c6c723 100644 --- a/core/libs/prx/libc/src/CxxAbiSupport.cpp +++ b/core/libs/prx/libc/src/CxxAbiSupport.cpp @@ -19,12 +19,17 @@ #include #include #include +#include #include "prx/libc/include/General.hpp" #include "prx/libc/include/ApplicationHeap.hpp" extern "C" { +unsigned int APS5_VABI _ZNSt8__sce_v226_Thrd_hardware_concurrencyEv_nid_postfix() noexcept { + return std::thread::hardware_concurrency(); +} + void* APS5_VABI __cxa_demangle_nid_postfix(const char* mangled, char* buf, std::size_t* len, int* status) { if (mangled == nullptr || (buf != nullptr && len == nullptr)) { if (status != nullptr) *status = -3; diff --git a/core/libs/tests/GuestHardwareConcurrency.cpp b/core/libs/tests/GuestHardwareConcurrency.cpp new file mode 100644 index 00000000000..ccf2d00ec8f --- /dev/null +++ b/core/libs/tests/GuestHardwareConcurrency.cpp @@ -0,0 +1,38 @@ +#include "prx/libc/include/general/VabiMacros.hpp" +#include +#include +#include +#include + +extern "C" unsigned int APS5_VABI _ZNSt8__sce_v226_Thrd_hardware_concurrencyEv_nid_postfix() noexcept; + +static_assert(sizeof(unsigned int) == 4); +static_assert(std::is_same_v); +static_assert(noexcept(_ZNSt8__sce_v226_Thrd_hardware_concurrencyEv_nid_postfix())); + +int main() { + const unsigned int expected = std::thread::hardware_concurrency(); + const auto query = _ZNSt8__sce_v226_Thrd_hardware_concurrencyEv_nid_postfix; + const unsigned int mainResult = query(); + if (mainResult != expected) { + std::fprintf(stderr, "guest processor hint %u differs from host hint %u\n", mainResult, expected); + return 1; + } + std::array results{}; + std::array consistent{true, true}; + std::array workers; + for (std::size_t index = 0; index < workers.size(); ++index) + workers[index] = std::thread([&, index] { + for (unsigned int iteration = 0; iteration < 128; ++iteration) { + results[index] = query(); + if (results[index] != std::thread::hardware_concurrency()) consistent[index] = false; + } + }); + for (auto& worker : workers) worker.join(); + for (std::size_t index = 0; index < results.size(); ++index) { + if (!consistent[index] || results[index] != mainResult) { + std::fprintf(stderr, "guest processor hint differs across threads\n"); + return 1; + } + } +}