Merge pull request #4004 from zmeizy/claude/mutex-timedlock-try-first

fix(libkernel): try the lock before checking the pthread_mutex_timedl…
This commit is contained in:
Dean 2026-10-13 02:34:16 +13:00 committed by GitHub
commit ddc713fbcf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 28 additions and 7 deletions

View File

@ -6,14 +6,13 @@
#include "../include/Mutex.hpp"
#include "Common.hpp"
#include <atomic>
#include <chrono>
#include <limits>
#include <stdexcept>
#include <string>
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<std::chrono::microseconds>(deadline - now).count();
const auto usec = remaining <= 0 ? 0 : remaining >= std::numeric_limits<KernelUseconds>::max() ? std::numeric_limits<KernelUseconds>::max() : static_cast<KernelUseconds>(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));
}

View File

@ -1,4 +1,5 @@
#include "SceTypes.hpp"
#include <cstdint>
#include <cstdlib>
#include <stdexcept>
@ -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<PthreadMutex*>(arg);
return reinterpret_cast<void*>(static_cast<std::intptr_t>(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<std::intptr_t>(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;