Add and fix pthread rwlock timeout tests

This commit is contained in:
Wildan M
2026-03-29 11:31:08 +07:00
parent 928a446f12
commit f5dd08dc49
3 changed files with 51 additions and 31 deletions
+25 -25
View File
@@ -2,7 +2,7 @@ use super::*;
use crate::header::errno::{EBUSY, EINVAL};
use crate::{error::ResultExt, header::time::CLOCK_REALTIME, pthread::Pshared};
use crate::{header::time::CLOCK_REALTIME, pthread::Pshared};
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_rwlock_init(
@@ -23,10 +23,10 @@ pub unsafe extern "C" fn pthread_rwlock_init(
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_rwlock_rdlock(rwlock: *mut pthread_rwlock_t) -> c_int {
unsafe { get(rwlock) }
.acquire_read_lock(None)
.map(|_| 0)
.or_minus_one_errno()
match unsafe { get(rwlock) }.acquire_read_lock(None) {
Ok(()) => 0,
Err(e) => e.0,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_rwlock_clockrdlock(
@@ -34,20 +34,20 @@ pub unsafe extern "C" fn pthread_rwlock_clockrdlock(
clock_id: clockid_t,
abstime: *const timespec,
) -> c_int {
unsafe { get(rwlock) }
.acquire_read_lock(Some((unsafe { &*abstime }, clock_id)))
.map(|_| 0)
.or_minus_one_errno()
match unsafe { get(rwlock) }.acquire_read_lock(Some((unsafe { &*abstime }, clock_id))) {
Ok(()) => 0,
Err(e) => e.0,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_rwlock_timedrdlock(
rwlock: *mut pthread_rwlock_t,
abstime: *const timespec,
) -> c_int {
unsafe { get(rwlock) }
.acquire_read_lock(Some((unsafe { &*abstime }, CLOCK_REALTIME)))
.map(|_| 0)
.or_minus_one_errno()
match unsafe { get(rwlock) }.acquire_read_lock(Some((unsafe { &*abstime }, CLOCK_REALTIME))) {
Ok(()) => 0,
Err(e) => e.0,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_rwlock_clockwrlock(
@@ -55,20 +55,20 @@ pub unsafe extern "C" fn pthread_rwlock_clockwrlock(
clock_id: clockid_t,
abstime: *const timespec,
) -> c_int {
unsafe { get(rwlock) }
.acquire_write_lock(Some((unsafe { &*abstime }, clock_id)))
.map(|_| 0)
.or_minus_one_errno()
match unsafe { get(rwlock) }.acquire_write_lock(Some((unsafe { &*abstime }, clock_id))) {
Ok(()) => 0,
Err(e) => e.0,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_rwlock_timedwrlock(
rwlock: *mut pthread_rwlock_t,
abstime: *const timespec,
) -> c_int {
unsafe { get(rwlock) }
.acquire_write_lock(Some((unsafe { &*abstime }, CLOCK_REALTIME)))
.map(|_| 0)
.or_minus_one_errno()
match unsafe { get(rwlock) }.acquire_write_lock(Some((unsafe { &*abstime }, CLOCK_REALTIME))) {
Ok(()) => 0,
Err(e) => e.0,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_rwlock_tryrdlock(rwlock: *mut pthread_rwlock_t) -> c_int {
@@ -92,10 +92,10 @@ pub unsafe extern "C" fn pthread_rwlock_unlock(rwlock: *mut pthread_rwlock_t) ->
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_rwlock_wrlock(rwlock: *mut pthread_rwlock_t) -> c_int {
unsafe { get(rwlock) }
.acquire_write_lock(None)
.map(|_| 0)
.or_minus_one_errno()
match unsafe { get(rwlock) }.acquire_write_lock(None) {
Ok(()) => 0,
Err(e) => e.0,
}
}
#[unsafe(no_mangle)]
+9 -4
View File
@@ -8,7 +8,7 @@ use crate::{
error::{Errno, Result},
header::{
bits_time::timespec,
errno::EINVAL,
errno::{EINVAL, ETIMEDOUT},
time::{CLOCK_MONOTONIC, CLOCK_REALTIME, timespec_realtime_to_monotonic},
},
platform::types::clockid_t,
@@ -77,7 +77,10 @@ impl InnerRwLock {
waiting_wr = expected & WAITING_WR;
if actual & COUNT_MASK > 0 {
let _ = crate::sync::futex_wait(&self.state, expected, relative.as_ref());
match crate::sync::futex_wait(&self.state, expected, relative.as_ref()) {
super::FutexWaitResult::TimedOut => return Err(Errno(ETIMEDOUT)),
_ => {}
}
} else {
// We must avoid blocking indefinitely in our `futex_wait()`, in this case
// where it's possible that `self.state == expected` but our futex might
@@ -93,9 +96,11 @@ impl InnerRwLock {
}
pub fn acquire_read_lock(&self, deadline: Option<(&timespec, clockid_t)>) -> Result<(), Errno> {
let relative = Self::translate_timeout(deadline)?;
// TODO: timeout
while let Err(old) = self.try_acquire_read_lock() {
crate::sync::futex_wait(&self.state, old, relative.as_ref());
match crate::sync::futex_wait(&self.state, old, relative.as_ref()) {
super::FutexWaitResult::TimedOut => return Err(Errno(ETIMEDOUT)),
_ => {}
}
}
Ok(())
+17 -2
View File
@@ -4,8 +4,9 @@
#include <assert.h>
#include <pthread.h>
#include <errno.h>
#include <time.h>
// Same test logic as test_rwlock_try_write in rustc/library/std/sync/rwlock/tests.rs
// Adapted from test_rwlock_try_write in rustc/library/std/sync/rwlock/tests.rs
int main(void) {
int status;
@@ -31,11 +32,25 @@ int main(void) {
ERROR_IF(pthread_rwlock_rdlock, status, != 0);
status = pthread_rwlock_trywrlock(&rwlock);
assert(status == EBUSY);
UNEXP_IF(pthread_rwlock_trywrlock, status, != EBUSY);
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_nsec += 200 * 1000000;
status = pthread_rwlock_timedwrlock(&rwlock, &ts);
UNEXP_IF(pthread_rwlock_timedwrlock, status, != ETIMEDOUT);
status = pthread_rwlock_unlock(&rwlock);
ERROR_IF(pthread_rwlock_unlock, status, != 0);
status = pthread_rwlock_trywrlock(&rwlock);
ERROR_IF(pthread_rwlock_rdlock, status, != 0);
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_nsec += 200 * 1000000;
status = pthread_rwlock_timedrdlock(&rwlock, &ts);
UNEXP_IF(pthread_rwlock_timedrdlock, status, != ETIMEDOUT);
status = pthread_rwlock_destroy(&rwlock);
ERROR_IF(pthread_rwlock_destroy, status, != 0);