From c395897fbe98be0386423102353ed33c71bd1690 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Wed, 15 Apr 2026 08:57:02 +0300 Subject: [PATCH] Fixed scePthreadSemTimedwait absolute timespec (#4238) * The usec parameter is a relative timeout, but posix_sem_timedwait expects an absolute timespec * posix_sem_post , concurrent fix --- .../libraries/kernel/threads/semaphore.cpp | 21 ++++++++++++------- src/core/libraries/kernel/time.h | 1 + 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/core/libraries/kernel/threads/semaphore.cpp b/src/core/libraries/kernel/threads/semaphore.cpp index 721b2c21a..a8ca84251 100644 --- a/src/core/libraries/kernel/threads/semaphore.cpp +++ b/src/core/libraries/kernel/threads/semaphore.cpp @@ -306,11 +306,14 @@ s32 PS4_SYSV_ABI posix_sem_post(PthreadSem** sem) { *__Error() = POSIX_EINVAL; return -1; } - if ((*sem)->value == ORBIS_KERNEL_SEM_VALUE_MAX) { - *__Error() = POSIX_EOVERFLOW; - return -1; - } - ++(*sem)->value; + // Atomically check for overflow and increment in one step. + s32 current = (*sem)->value.load(); + do { + if (current == ORBIS_KERNEL_SEM_VALUE_MAX) { + *__Error() = POSIX_EOVERFLOW; + return -1; + } + } while (!(*sem)->value.compare_exchange_weak(current, current + 1)); (*sem)->semaphore.release(); return 0; } @@ -367,9 +370,13 @@ s32 PS4_SYSV_ABI scePthreadSemTrywait(PthreadSem** sem) { } s32 PS4_SYSV_ABI scePthreadSemTimedwait(PthreadSem** sem, u32 usec) { + OrbisKernelTimespec now{}; + posix_clock_gettime(ORBIS_CLOCK_REALTIME, &now); + const u64 total_nsec = now.tv_nsec + (usec % 1000000) * 1000ULL; + OrbisKernelTimespec time{}; - time.tv_sec = usec / 1000000; - time.tv_nsec = (usec % 1000000) * 1000; + time.tv_sec = now.tv_sec + usec / 1000000 + total_nsec / 1000000000; + time.tv_nsec = total_nsec % 1000000000; s32 ret = posix_sem_timedwait(sem, &time); if (ret != 0) { diff --git a/src/core/libraries/kernel/time.h b/src/core/libraries/kernel/time.h index 583d138b8..d876fe7bb 100644 --- a/src/core/libraries/kernel/time.h +++ b/src/core/libraries/kernel/time.h @@ -83,6 +83,7 @@ s32 PS4_SYSV_ABI sceKernelConvertLocaltimeToUtc(time_t param_1, int64_t param_2, s32 PS4_SYSV_ABI sceKernelConvertUtcToLocaltime(time_t time, time_t* local_time, OrbisTimesec* st, u64* dst_sec); s32 PS4_SYSV_ABI sceKernelUsleep(u32 microseconds); +s32 PS4_SYSV_ABI posix_clock_gettime(u32 clock_id, OrbisKernelTimespec* ts); s32 PS4_SYSV_ABI posix_clock_settime(s32 clock_id, OrbisKernelTimespec* tp); s32 PS4_SYSV_ABI posix_settimeofday(OrbisKernelTimeval* _tv, OrbisKernelTimezone* _tz); s32 PS4_SYSV_ABI sceKernelSettimeofday(OrbisKernelTimeval* _tv, OrbisKernelTimezone* _tz);