mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-18 23:07:07 -05:00
fix(libkernel): clamp POSIX deadlines beyond the clock range instead of overflowing
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
This commit is contained in:
2 files changed
+27
-4
No files matched your search
@@ -24,10 +24,18 @@ inline bool RelativeMicroseconds(int clockId, const KernelTimespec* abstime, Ker
|
||||
if (!abstime || abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) return false;
|
||||
KernelTimespec now{};
|
||||
clock_gettime_nid_postfix(clockId, &now);
|
||||
const auto deadline = std::chrono::seconds(abstime->tv_sec) + std::chrono::nanoseconds(abstime->tv_nsec);
|
||||
const auto current = std::chrono::seconds(now.tv_sec) + std::chrono::nanoseconds(now.tv_nsec);
|
||||
const auto remaining = std::chrono::duration_cast<std::chrono::microseconds>(deadline - current).count();
|
||||
*usec = remaining <= 0 ? 0 : remaining >= std::numeric_limits<KernelUseconds>::max() ? std::numeric_limits<KernelUseconds>::max() : static_cast<KernelUseconds>(remaining);
|
||||
constexpr auto maximum = std::numeric_limits<KernelUseconds>::max();
|
||||
if (abstime->tv_sec < now.tv_sec - 1) {
|
||||
*usec = 0;
|
||||
return true;
|
||||
}
|
||||
const std::int64_t seconds = abstime->tv_sec - now.tv_sec;
|
||||
if (seconds > static_cast<std::int64_t>(maximum / 1000000) + 1) {
|
||||
*usec = maximum;
|
||||
return true;
|
||||
}
|
||||
const std::int64_t remaining = (seconds * 1000000000 + abstime->tv_nsec - now.tv_nsec) / 1000;
|
||||
*usec = remaining <= 0 ? 0 : remaining >= maximum ? maximum : static_cast<KernelUseconds>(remaining);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -190,8 +190,23 @@ static void CheckFailedLockAttempts() {
|
||||
Require(rwlock == nullptr);
|
||||
}
|
||||
|
||||
static void CheckDeadlinesBeyondTheClockRange() {
|
||||
PthreadRwlock rwlock = nullptr;
|
||||
Holder reader{&rwlock, false};
|
||||
Start(reader);
|
||||
const KernelTimespec farPast{INT64_MIN, 0};
|
||||
Require(pthread_rwlock_timedwrlock_nid_postfix(&rwlock, &farPast) == GUEST_ETIMEDOUT);
|
||||
reader.release.store(true);
|
||||
const KernelTimespec farFuture{INT64_MAX, 0};
|
||||
Require(pthread_rwlock_timedwrlock_nid_postfix(&rwlock, &farFuture) == 0);
|
||||
Require(pthread_rwlock_unlock_nid_postfix(&rwlock) == 0);
|
||||
Require(scePthreadJoin(reader.thread, nullptr) == SCE_OK);
|
||||
Require(pthread_rwlock_destroy_nid_postfix(&rwlock) == 0);
|
||||
}
|
||||
|
||||
int main() {
|
||||
CheckConcurrentFirstWrlockExcludes();
|
||||
CheckDeadlinesBeyondTheClockRange();
|
||||
const KernelTimespec invalid{0, NANOS_PER_SECOND};
|
||||
PthreadRwlock fresh[4] = {};
|
||||
Require(pthread_rwlock_tryrdlock_nid_postfix(&fresh[0]) == 0);
|
||||
|
||||
Reference in new issue
Block a user