Browse Source

Fix pthread_cond_timedwait from sleeping for about 52 years

pthread_cond_timedwait gives a timestamp as the timeout, but libctru
expects a duration. After converting the timestamp to nanoseconds since
epoch, we were telling libctru to sleep for over 52 years!

This commit changes our impl to convert the timestamp to a duration.

Additionally, CondVar_WaitTimeout returns a boolean indicating if it
timed out or not. But pthread_cond_timedwait expects a libc-style error
code. This conversion is added as well.
pull/6/head
AzureMarker 3 years ago
parent
commit
a7ff3bc394
No known key found for this signature in database
GPG Key ID: 47A133F3BF9D03D3
  1. 37
      src/lib.rs

37
src/lib.rs

@ -131,9 +131,40 @@ pub unsafe extern "C" fn pthread_cond_timedwait( @@ -131,9 +131,40 @@ pub unsafe extern "C" fn pthread_cond_timedwait(
lock: *mut libc::pthread_mutex_t,
abstime: *const libc::timespec,
) -> libc::c_int {
let nsec: i64 = ((*abstime).tv_sec as i64 * 1_000_000_000) + (*abstime).tv_nsec as i64;
CondVar_WaitTimeout(cond as _, lock as _, nsec)
// libctru expects a duration, but we have an absolute timestamp.
// Convert to a duration before calling libctru.
// Get the current time so we can make a duration
let mut now = libc::timeval {
tv_sec: 0,
tv_usec: 0,
};
let r = libc::gettimeofday(&mut now, ptr::null_mut());
if r != 0 {
return r;
}
// Calculate the duration
let duration_nsec = (*abstime)
.tv_sec
// Get the difference in seconds
.saturating_sub(now.tv_sec)
// Convert to nanoseconds
.saturating_mul(1_000_000_000)
// Add the difference in nanoseconds
.saturating_add((*abstime).tv_nsec as i64)
.saturating_sub(now.tv_usec as i64 * 1_000)
// Don't go negative
.max(0);
let r = CondVar_WaitTimeout(cond as _, lock as _, duration_nsec);
// CondVar_WaitTimeout returns a boolean which is true (nonzero) if it timed out
if r == 0 {
0
} else {
libc::ETIMEDOUT
}
}
#[no_mangle]

Loading…
Cancel
Save