fix(pthread_mutex): store prioceiling in u8 to keep 12-byte layout matching libc crate

This commit is contained in:
Red Bear OS
2026-07-08 19:52:29 +03:00
parent 7f42a9fb20
commit 68d43106eb
4 changed files with 35 additions and 16 deletions
+1 -1
View File
@@ -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).
+7 -5
View File
@@ -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::<RlctCond>();
cond_ref.cur = AtomicU32::new(0);
cond_ref.prev = AtomicU32::new(0);
cond_ref.set_clock(attr.clock);
}
unsafe { cond.cast::<RlctCond>().write(RlctCond::new()) };
0
}
+14 -4
View File
@@ -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<T, E = Errno> = core::result::Result<T, E>;
@@ -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: &timespec) -> 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<&timespec>) -> 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);
}
}
+13 -6
View File
@@ -19,7 +19,7 @@ pub struct RlctMutex {
ty: Ty,
robust: bool,
prioceiling_value: Cell<c_int>,
prioceiling_value: Cell<u8>,
}
pub struct RobustMutexNode {
@@ -43,12 +43,16 @@ impl RlctMutex {
pub(crate) fn new(attr: &RlctMutexAttr) -> Result<Self, Errno> {
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<c_int, Errno> {
Ok(self.prioceiling_value.get())
Ok(self.prioceiling_value.get() as c_int)
}
pub fn replace_prioceiling(&self, new_ceiling: c_int) -> Result<c_int, Errno> {
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");