diff --git a/core/libs/prx/libkernel/Pthread/src/Thread.cpp b/core/libs/prx/libkernel/Pthread/src/Thread.cpp index ee0f309c5..60f902c82 100644 --- a/core/libs/prx/libkernel/Pthread/src/Thread.cpp +++ b/core/libs/prx/libkernel/Pthread/src/Thread.cpp @@ -29,6 +29,7 @@ static constexpr int SCE_OK = 0; static constexpr std::size_t DEFAULT_STACK_SIZE = 1u << 20; +static constexpr std::size_t HOST_STACK_MARGIN = 1u << 20; static constexpr int DETACH_DETACHED = 1; static constexpr std::size_t THREAD_NAME_CAPACITY = 32; @@ -481,9 +482,9 @@ int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, Pthread #ifdef _WIN32 SYSTEM_INFO system{}; GetSystemInfo(&system); - const std::size_t nativeStack = (p->stackSize + system.dwPageSize - 1) / system.dwPageSize * system.dwPageSize; - if (p->stackSize < 16384 || nativeStack > std::numeric_limits::max()) + if (p->stackSize < 16384 || p->stackSize > std::numeric_limits::max() - HOST_STACK_MARGIN - system.dwPageSize) throw std::runtime_error("scePthreadCreate: invalid Windows stack size"); + const std::size_t nativeStack = (p->stackSize + HOST_STACK_MARGIN + system.dwPageSize - 1) / system.dwPageSize * system.dwPageSize; auto native = std::make_unique(NativeThreadArgs{std::move(args), start.get_future(), {}}); auto initialized = native->initialized.get_future(); const auto handle = _beginthreadex(nullptr, static_cast(nativeStack), StartNativeThread, native.get(), 0, nullptr); @@ -507,9 +508,9 @@ int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, Pthread #else const auto reserve = HostStackReserve(); const auto page = static_cast(sysconf(_SC_PAGESIZE)); - if (p->stackSize < 16384 || p->stackSize > std::numeric_limits::max() - reserve - page) + if (p->stackSize < 16384 || p->stackSize > std::numeric_limits::max() - reserve - HOST_STACK_MARGIN - page) throw std::runtime_error("scePthreadCreate: invalid stack size"); - const std::size_t nativeStack = (p->stackSize + reserve + page - 1) / page * page; + const std::size_t nativeStack = (p->stackSize + reserve + HOST_STACK_MARGIN + page - 1) / page * page; auto native = std::make_unique(NativeThreadArgs{std::move(args), start.get_future(), {}}); auto initialized = native->initialized.get_future(); pthread_attr_t nativeAttr; diff --git a/core/libs/tests/GuestPthreadStack.cpp b/core/libs/tests/GuestPthreadStack.cpp index 1a0f7bb62..21045925e 100644 --- a/core/libs/tests/GuestPthreadStack.cpp +++ b/core/libs/tests/GuestPthreadStack.cpp @@ -17,6 +17,7 @@ Pthread APS5_VABI scePthreadSelf(); static constexpr int SCE_OK = 0; static constexpr std::size_t FRAME_SIZE = 4096; static constexpr std::size_t FRAME_MARGIN = 2 * FRAME_SIZE; +static constexpr std::size_t HOST_CALL_STACK = 256 * 1024; static constexpr std::size_t STACK_SIZES[] = {16384, 65536, 1u << 20, 16u << 20}; thread_local unsigned char threadLocalBlock[512 * 1024]; @@ -56,6 +57,8 @@ static void* APS5_VABI Worker(void* arg) { Require(local - begin + FRAME_SIZE >= requested); const auto deepest = Descend(begin); Require(deepest >= begin && deepest < begin + FRAME_MARGIN); + const auto hostDeepest = descend(begin - HOST_CALL_STACK); + Require(hostDeepest < begin - HOST_CALL_STACK + FRAME_MARGIN); Require(threadLocalBlock[0] == 1 && threadLocalBlock[sizeof(threadLocalBlock) - 1] == 2); return arg;