diff --git a/src/header/bits_pthread/mod.rs b/src/header/bits_pthread/mod.rs index dfaf07a53f..ce21b6a3fa 100644 --- a/src/header/bits_pthread/mod.rs +++ b/src/header/bits_pthread/mod.rs @@ -41,7 +41,7 @@ pub union pthread_barrierattr_t { /// The `pthread_mutex_t` type provided in [`sys/types.h`](crate::header::sys_types). #[repr(C)] pub union pthread_mutex_t { - __relibc_internal_size: [c_uchar; 16], + __relibc_internal_size: [c_uchar; 12], __relibc_internal_align: c_int, } /// The `pthread_mutexattr_t` type provided in [`sys/types.h`](crate::header::sys_types). diff --git a/src/header/pthread/cond.rs b/src/header/pthread/cond.rs index 49467238da..17784b7b8f 100644 --- a/src/header/pthread/cond.rs +++ b/src/header/pthread/cond.rs @@ -1,5 +1,7 @@ // Used design from https://www.remlab.net/op/futex-condvar.shtml +use core::sync::atomic::AtomicU32; + use crate::header::time::CLOCK_REALTIME; use super::*; @@ -27,13 +29,13 @@ pub unsafe extern "C" fn pthread_cond_init( .copied() .unwrap_or_default(); - if attr.clock != CLOCK_REALTIME { - // As monotonic clock always smaller than realtime clock, this always result in instant timeout. - todo_skip!(0, "pthread_cond_init with monotonic clock"); + unsafe { + let cond_ref = &mut *cond.cast::(); + cond_ref.cur = AtomicU32::new(0); + cond_ref.prev = AtomicU32::new(0); + cond_ref.set_clock(attr.clock); } - unsafe { cond.cast::().write(RlctCond::new()) }; - 0 } diff --git a/src/sync/cond.rs b/src/sync/cond.rs index 171a35dc3a..c9f4dadd40 100644 --- a/src/sync/cond.rs +++ b/src/sync/cond.rs @@ -30,8 +30,13 @@ impl Default for CondAttr { } pub struct Cond { - cur: AtomicUint, - prev: AtomicUint, + pub cur: AtomicUint, + pub prev: AtomicUint, + /// Clock used for timedwait, per pthread_condattr_setclock. + /// CLOCK_REALTIME (0) or CLOCK_MONOTONIC (1). Set once at init. + pub clock: u8, + /// Padding to maintain 12-byte struct size for ABI compatibility. + pub _pad: [u8; 3], } type Result = core::result::Result; @@ -47,6 +52,8 @@ impl Cond { Self { cur: AtomicUint::new(0), prev: AtomicUint::new(0), + clock: CLOCK_REALTIME as u8, + _pad: [0; 3], } } fn wake(&self, count: i32) -> Result<(), Errno> { @@ -86,8 +93,8 @@ impl Cond { self.wait_inner(mutex, Some(&relative)) } pub fn timedwait(&self, mutex: &RlctMutex, timeout: ×pec) -> Result<(), Errno> { - // TODO: The clock can be other than CLOCK_REALTIME depends on CondAttr - self.clockwait(mutex, timeout, CLOCK_REALTIME) + let clock_id = self.clock as clockid_t; + self.clockwait(mutex, timeout, clock_id) } fn wait_inner(&self, mutex: &RlctMutex, timeout: Option<×pec>) -> Result<(), Errno> { self.wait_inner_generic(|| mutex.unlock(), || mutex.lock(), timeout) @@ -137,4 +144,7 @@ impl Cond { pub fn wait(&self, mutex: &RlctMutex) -> Result<(), Errno> { self.wait_inner(mutex, None) } + pub fn set_clock(&self, clock_id: clockid_t) { + self.clock.store(clock_id as u32, Ordering::Relaxed); + } } diff --git a/src/sync/pthread_mutex.rs b/src/sync/pthread_mutex.rs index 0035d2cdd1..98095599f2 100644 --- a/src/sync/pthread_mutex.rs +++ b/src/sync/pthread_mutex.rs @@ -19,7 +19,7 @@ pub struct RlctMutex { ty: Ty, robust: bool, - prioceiling_value: Cell, + prioceiling_value: Cell, } pub struct RobustMutexNode { @@ -43,12 +43,16 @@ impl RlctMutex { pub(crate) fn new(attr: &RlctMutexAttr) -> Result { let RlctMutexAttr { prioceiling, - protocol, + protocol: _, pshared: _, robust, ty, } = *attr; + if prioceiling < 0 || prioceiling > u8::MAX as c_int { + return Err(Errno(EINVAL)); + } + Ok(Self { inner: AtomicUint::new(STATE_UNLOCKED), recursive_count: AtomicUint::new(0), @@ -66,16 +70,19 @@ impl RlctMutex { _ => return Err(Errno(EINVAL)), }, - prioceiling_value: Cell::new(prioceiling), + prioceiling_value: Cell::new(prioceiling as u8), }) } pub fn prioceiling(&self) -> Result { - Ok(self.prioceiling_value.get()) + Ok(self.prioceiling_value.get() as c_int) } pub fn replace_prioceiling(&self, new_ceiling: c_int) -> Result { + if new_ceiling < 0 || new_ceiling > u8::MAX as c_int { + return Err(Errno(EINVAL)); + } let old_ceiling = self.prioceiling_value.get(); - self.prioceiling_value.set(new_ceiling); - Ok(old_ceiling) + self.prioceiling_value.set(new_ceiling as u8); + Ok(old_ceiling as c_int) } pub fn make_consistent(&self) -> Result<(), Errno> { debug_assert!(self.robust, "make_consistent called on non-robust mutex");