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
This commit is contained in:
georgemoralis 2026-04-15 08:57:02 +03:00 committed by GitHub
parent c1e496efcd
commit c395897fbe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 15 additions and 7 deletions

View File

@ -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) {

View File

@ -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);