diff --git a/core/libs/prx/libkernel/Time/Time.cpp b/core/libs/prx/libkernel/Time/Time.cpp index 581e81bb5..0f86dbf4d 100644 --- a/core/libs/prx/libkernel/Time/Time.cpp +++ b/core/libs/prx/libkernel/Time/Time.cpp @@ -473,8 +473,7 @@ int APS5_VABI gettimeofday_nid_postfix(KernelTimeval* tv, KernelTimezone* tz) { } int APS5_VABI clock_getres_nid_postfix(int clockId, KernelTimespec* res) { - KernelTimespec ignoredResolution{}; - if (res == nullptr) res = &ignoredResolution; + if (res == nullptr) return 0; if (IsCpuClock(clockId)) return clock_getres_nid_postfix(GUEST_CLOCK_THREAD_CPUTIME_ID, res); if (clockId == 1 || clockId == 2) { diff --git a/core/libs/tests/GuestFreebsdClocks.cpp b/core/libs/tests/GuestFreebsdClocks.cpp index be5f30434..d75ca2ec4 100644 --- a/core/libs/tests/GuestFreebsdClocks.cpp +++ b/core/libs/tests/GuestFreebsdClocks.cpp @@ -1,13 +1,17 @@ #include "SceTypes.hpp" #include +#include #include +#include #include +#include extern "C" { int APS5_VABI clock_gettime_nid_postfix(int clockId, KernelTimespec* tp); int APS5_VABI clock_getres_nid_postfix(int clockId, KernelTimespec* res); int APS5_VABI sceKernelClockGettime(KernelClockid clockId, KernelTimespec* tp); int APS5_VABI sceKernelClockGetres(KernelClockid clockId, KernelTimespec* tp); +int* APS5_VABI __error_nid_postfix(); int APS5_VABI sceKernelUsleep_nid_postfix(KernelUseconds microseconds); int APS5_VABI gettimeofday_nid_postfix(KernelTimeval* tv, KernelTimezone* tz); std::int64_t APS5_VABI _Xtime_get_ticks_nid_postfix(); @@ -32,6 +36,34 @@ static constexpr std::int64_t GIVE_UP_NANOS = 10 * NANOS_PER_SECOND; static void Require(bool value) { if (!value) std::abort(); } +static bool OmittedResolutionSucceeds() { + constexpr int clocks[] = {0, 1, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 3, 6, 9999, -1, INT_MIN, INT_MAX}; + for (const int clock : clocks) { + *__error_nid_postfix() = 77; + try { + if (clock_getres_nid_postfix(clock, nullptr) == SCE_OK && *__error_nid_postfix() == 77) continue; + } catch (const std::runtime_error&) { + } + std::fprintf(stderr, "clock_getres(%d, nullptr) must succeed without changing errno\n", clock); + return false; + } + return true; +} + +static void UnsupportedResolutionStillThrows() { + KernelTimespec resolution{-1, -1}; + bool rejected = false; + try { + clock_getres_nid_postfix(3, &resolution); + } catch (const std::runtime_error&) { + rejected = true; + } + Require(rejected && resolution.tv_sec == -1 && resolution.tv_nsec == -1); + constexpr int fault = static_cast(0x8002000eu); + Require(sceKernelClockGetres(GUEST_CLOCK_REALTIME, nullptr) == fault); + Require(sceKernelClockGetres(3, nullptr) == fault); +} + static KernelTimespec Read(int clockId) { KernelTimespec time{-1, -1}; Require(clock_gettime_nid_postfix(clockId, &time) == SCE_OK); @@ -168,6 +200,8 @@ static void CalendarConversionsInitializeTheirState() { } int main() { + if (!OmittedResolutionSucceeds()) return 1; + UnsupportedResolutionStillThrows(); CalendarConversionsInitializeTheirState(); SecondClockReportsWholeSeconds(); KernelTimezone zone{-1, -1};