Files
AnyPS5/core/libs/tests/GuestNanosleepLongRequest.cpp
T
xXPBSXxandClaude Sonnet 5.5 62e6ba7481 fix(libkernel): clamp long nanosleep requests like FreeBSD instead of wrapping them
kern_clock_nanosleep limits the sleep to INT32_MAX / 2 seconds and sleeps
for that long (sys/kern/kern_time.c:543-547). The guest multiplied tv_sec
by 1e9 in 64 bits, so a request of 18446744074 seconds or more wrapped to a
short sleep: nanosleep with tv_sec = INT64_MAX returned after about 0.1 s.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-20 21:24:54 +02:00

59 lines
1.9 KiB
C++

#include "SceTypes.hpp"
#include "prx/libkernel/Pthread/include/Pthread.hpp"
#include <atomic>
#include <chrono>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <source_location>
#include <thread>
extern "C" {
int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name);
int APS5_VABI nanosleep_nid_postfix(const KernelTimespec* rqtp, KernelTimespec* rmtp);
int APS5_VABI sceKernelNanosleep(const KernelTimespec* rqtp, KernelTimespec* rmtp);
}
static void Require(bool value, std::source_location location = std::source_location::current()) {
if (value) return;
std::fprintf(stderr, "%s:%u: requirement failed\n", location.file_name(), location.line());
std::abort();
}
static constexpr auto ObservationTime = std::chrono::milliseconds(1500);
static std::atomic<bool> started{false};
static std::atomic<bool> returned{false};
static std::int64_t requestedSeconds = 0;
static bool posix = true;
static void* APS5_VABI Sleeper(void*) {
const KernelTimespec request{requestedSeconds, 0};
started.store(true);
if (posix) nanosleep_nid_postfix(&request, nullptr);
else sceKernelNanosleep(&request, nullptr);
returned.store(true);
return nullptr;
}
static void SleepsPastTheObservation(std::int64_t seconds, bool usePosix) {
started.store(false);
returned.store(false);
requestedSeconds = seconds;
posix = usePosix;
Pthread thread = nullptr;
Require(scePthreadCreate(&thread, nullptr, Sleeper, nullptr, nullptr) == 0);
while (!started.load()) std::this_thread::yield();
std::this_thread::sleep_for(ObservationTime);
Require(!returned.load());
}
int main() {
for (const bool usePosix : {true, false}) {
SleepsPastTheObservation(INT64_MAX, usePosix);
SleepsPastTheObservation(18446744074LL, usePosix);
SleepsPastTheObservation(std::int64_t{1} << 40, usePosix);
}
std::fflush(nullptr);
std::_Exit(0);
}