diff --git a/core/libs/prx/libkernel/Pthread/Posix/Mutex.cpp b/core/libs/prx/libkernel/Pthread/Posix/Mutex.cpp index ee0695d43..7ab97118f 100644 --- a/core/libs/prx/libkernel/Pthread/Posix/Mutex.cpp +++ b/core/libs/prx/libkernel/Pthread/Posix/Mutex.cpp @@ -6,14 +6,13 @@ #include "../include/Mutex.hpp" #include "Common.hpp" #include -#include -#include #include #include namespace { constexpr int POSIX_EINVAL = 22; +constexpr int GUEST_REALTIME_CLOCK = 0; constexpr int POSIX_PRIO_PROTECT = 2; constexpr int POSIX_SCHED_RR = 3; constexpr std::uintptr_t POSIX_ADAPTIVE_MUTEX_INITIALIZER = 1; @@ -62,12 +61,10 @@ int APS5_VABI pthread_mutex_lock_nid_postfix(PthreadMutex* mutex) { int APS5_VABI pthread_mutex_timedlock_nid_postfix(PthreadMutex* mutex, const KernelTimespec* abstime) { if (!abstime) throw std::runtime_error("pthread_mutex_timedlock: null abstime"); - if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) return POSIX_EINVAL; _initializeStatic(mutex, __func__); - const auto deadline = std::chrono::seconds(abstime->tv_sec) + std::chrono::nanoseconds(abstime->tv_nsec); - const auto now = std::chrono::system_clock::now().time_since_epoch(); - const auto remaining = std::chrono::duration_cast(deadline - now).count(); - const auto usec = remaining <= 0 ? 0 : remaining >= std::numeric_limits::max() ? std::numeric_limits::max() : static_cast(remaining); + if (scePthreadMutexTrylock(mutex) == 0) return 0; + KernelUseconds usec = 0; + if (!PosixThread::RelativeMicroseconds(GUEST_REALTIME_CLOCK, abstime, &usec)) return POSIX_EINVAL; return PosixThread::ToErrno(scePthreadMutexTimedlock(mutex, usec)); } diff --git a/core/libs/tests/GuestPthreadMutexattr.cpp b/core/libs/tests/GuestPthreadMutexattr.cpp index 410fb354e..410aa02ba 100644 --- a/core/libs/tests/GuestPthreadMutexattr.cpp +++ b/core/libs/tests/GuestPthreadMutexattr.cpp @@ -1,4 +1,5 @@ #include "SceTypes.hpp" +#include #include #include @@ -14,6 +15,9 @@ int APS5_VABI pthread_mutex_init_nid_postfix(PthreadMutex* mutex, const PthreadM int APS5_VABI pthread_mutex_lock_nid_postfix(PthreadMutex* mutex); int APS5_VABI pthread_mutex_unlock_nid_postfix(PthreadMutex* mutex); int APS5_VABI pthread_mutex_destroy_nid_postfix(PthreadMutex* mutex); +int APS5_VABI pthread_mutex_timedlock_nid_postfix(PthreadMutex* mutex, const KernelTimespec* abstime); +int APS5_VABI scePthreadCreate(Pthread* thread, const PthreadAttr* attr, PthreadEntry entry, void* arg, const char* name); +int APS5_VABI scePthreadJoin(Pthread thread, void** retval); int APS5_VABI sched_get_priority_max_nid_postfix(int policy); } @@ -35,6 +39,25 @@ static bool Throws(Call call) { return false; } +static constexpr KernelTimespec INVALID_DEADLINE{0, 1000000000}; + +static void* APS5_VABI TimedlockInvalidDeadline(void* arg) { + auto* mutex = static_cast(arg); + return reinterpret_cast(static_cast(pthread_mutex_timedlock_nid_postfix(mutex, &INVALID_DEADLINE))); +} + +static void CheckTimedlockInvalidDeadline() { + PthreadMutex mutex = nullptr; + Require(pthread_mutex_init_nid_postfix(&mutex, nullptr) == 0); + Require(pthread_mutex_timedlock_nid_postfix(&mutex, &INVALID_DEADLINE) == 0); + Pthread thread{}; + void* result = nullptr; + Require(scePthreadCreate(&thread, nullptr, TimedlockInvalidDeadline, &mutex, nullptr) == 0); + Require(scePthreadJoin(thread, &result) == 0 && reinterpret_cast(result) == GUEST_EINVAL); + Require(pthread_mutex_unlock_nid_postfix(&mutex) == 0); + Require(pthread_mutex_destroy_nid_postfix(&mutex) == 0); +} + static void CheckType() { PthreadMutexattr attr = nullptr; Require(pthread_mutexattr_init_nid_postfix(&attr) == 0); @@ -55,6 +78,7 @@ static void CheckType() { int main() { CheckType(); + CheckTimedlockInvalidDeadline(); PthreadMutexattr attr = nullptr; Require(pthread_mutexattr_init_nid_postfix(&attr) == 0); int ceiling = -1;