From bd6cc20a755f88daeaffd04f24d1e6b9b8acb46d Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sun, 9 Apr 2023 16:53:04 +0200 Subject: [PATCH] Make pthread types opaque, and check against libc. --- Cargo.lock | 3 +- Cargo.toml | 7 +- src/header/bits_pthread/mod.rs | 126 ++++++++++++++++++++------------- src/header/bits_sched/mod.rs | 6 -- src/header/pthread/attr.rs | 45 ++++++------ src/header/pthread/barrier.rs | 23 ++++-- src/header/pthread/cond.rs | 35 ++++++--- src/header/pthread/mod.rs | 14 +++- src/header/pthread/mutex.rs | 51 +++++++++---- src/header/pthread/once.rs | 8 ++- src/header/pthread/rwlock.rs | 34 ++++++--- src/header/pthread/spin.rs | 29 ++++++-- src/header/sched/mod.rs | 9 ++- src/pthread/mod.rs | 2 +- 14 files changed, 260 insertions(+), 132 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1a00975c5..72bbd7cf3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -228,8 +228,6 @@ version = "0.1.0" [[package]] name = "libc" version = "0.2.141" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" [[package]] name = "linux-raw-sys" @@ -407,6 +405,7 @@ dependencies = [ "core_io", "goblin", "lazy_static", + "libc", "memchr", "memoffset", "plain", diff --git a/Cargo.toml b/Cargo.toml index 856da184c..41e0ddbfb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ rand = { version = "0.5.5", default-features = false } memchr = { version = "2.2.0", default-features = false } plain = "0.2" unicode-width = "0.1" +libc = { version = "0.2", optional = true } [dependencies.goblin] version = "0.0.21" @@ -48,11 +49,15 @@ spin = "0.9.0" redox-exec = { path = "src/platform/redox/redox-exec" } [features] -default = [] +default = ["check_against_libc_crate"] trace = [] +check_against_libc_crate = ["libc"] [profile.dev] panic = "abort" [profile.release] panic = "abort" + +[patch.crates-io] +libc = { path = "/home/me/Projects/libc" } diff --git a/src/header/bits_pthread/mod.rs b/src/header/bits_pthread/mod.rs index 1f8729942..e3dc67bf2 100644 --- a/src/header/bits_pthread/mod.rs +++ b/src/header/bits_pthread/mod.rs @@ -7,75 +7,105 @@ use crate::header::sched::sched_param; use crate::sync::AtomicLock; use core::sync::atomic::{AtomicU32 as AtomicUint, AtomicI32 as AtomicInt}; +// XXX: https://github.com/eqrion/cbindgen/issues/685 +// +// We need to write the opaque types ourselves, and apparently cbindgen doesn't even support +// expanding macros! Instead, we rely on checking that the lengths are correct, when these headers +// are parsed in the regular compilation phase. + #[repr(C)] -#[derive(Clone, Copy)] -pub struct pthread_attr_t { - pub detachstate: c_uchar, - pub inheritsched: c_uchar, - pub schedpolicy: c_uchar, - pub scope: c_uchar, - pub guardsize: size_t, - pub stacksize: size_t, - pub stack: size_t, - pub param: sched_param, +pub union pthread_attr_t { + __relibc_internal_size: [c_uchar; 32], + __relibc_internal_align: c_long, } - #[repr(C)] -pub struct pthread_rwlockattr_t { - pub pshared: c_int, +pub union pthread_rwlockattr_t { + __relibc_internal_size: [c_uchar; 4], + __relibc_internal_align: c_int, } - #[repr(C)] -pub struct pthread_rwlock_t { - pub state: AtomicInt, +pub union pthread_rwlock_t { + __relibc_internal_size: [c_uchar; 4], + __relibc_internal_align: c_int, } - #[repr(C)] -pub struct pthread_barrier_t { - pub count: AtomicUint, - pub original_count: c_uint, - pub epoch: AtomicInt, +pub union pthread_barrier_t { + __relibc_internal_size: [c_uchar; 12], + __relibc_internal_align: c_int, } - #[repr(C)] -pub struct pthread_barrierattr_t { - pub pshared: c_int, +pub union pthread_barrierattr_t { + __relibc_internal_size: [c_uchar; 4], + __relibc_internal_align: c_int, } - #[repr(C)] -pub struct pthread_mutex_t { - pub inner: AtomicInt, +pub union pthread_mutex_t { + __relibc_internal_size: [c_uchar; 4], + __relibc_internal_align: c_int, } - #[repr(C)] -pub struct pthread_mutexattr_t { - pub prioceiling: c_int, - pub protocol: c_int, - pub pshared: c_int, - pub robust: c_int, - pub ty: c_int, +pub union pthread_mutexattr_t { + __relibc_internal_size: [c_uchar; 20], + __relibc_internal_align: c_int, } - #[repr(C)] -pub struct pthread_condattr_t { - pub clock: clockid_t, - pub pshared: c_int, +pub union pthread_cond_t { + __relibc_internal_size: [c_uchar; 8], + __relibc_internal_align: c_int, } - #[repr(C)] -pub struct pthread_cond_t { - pub cur: AtomicInt, - pub prev: AtomicInt, +pub union pthread_condattr_t { + __relibc_internal_size: [c_uchar; 8], + __relibc_internal_align: c_int, } #[repr(C)] -pub struct pthread_spinlock_t { - pub inner: AtomicInt, +pub union pthread_spinlock_t { + __relibc_internal_size: [c_uchar; 4], + __relibc_internal_align: c_int, } - #[repr(C)] -pub struct pthread_once_t { - pub inner: AtomicInt, +pub union pthread_once_t { + __relibc_internal_size: [c_uchar; 4], + __relibc_internal_align: c_int, } -pub type pthread_t = *mut (); +macro_rules! assert_equal_size( + ($export:ident, $wrapped:ident) => { + const _: () = unsafe { + type Wrapped = crate::header::pthread::$wrapped; + + // Fail at compile-time if sizes differ. + + // TODO: Is this UB? + let export = $export { __relibc_internal_align: 0 }; + let _: Wrapped = core::mem::transmute(export.__relibc_internal_size); + + // Fail at compile-time if alignments differ. + let a = [0_u8; core::mem::align_of::<$export>()]; + let b: [u8; core::mem::align_of::<Wrapped>()] = core::mem::transmute(a); + }; + #[cfg(feature = "check_against_libc_crate")] + const _: () = unsafe { + let export = $export { __relibc_internal_align: 0 }; + let _: libc::$export = core::mem::transmute(export.__relibc_internal_size); + + let a = [0_u8; core::mem::align_of::<$export>()]; + let b: [u8; core::mem::align_of::<libc::$export>()] = core::mem::transmute(a); + + }; + } +); +assert_equal_size!(pthread_attr_t, RlctAttr); +assert_equal_size!(pthread_rwlock_t, RlctRwlock); +assert_equal_size!(pthread_rwlock_t, RlctRwlockAttr); +assert_equal_size!(pthread_barrier_t, RlctBarrier); +assert_equal_size!(pthread_barrierattr_t, RlctBarrierAttr); +assert_equal_size!(pthread_mutex_t, RlctMutex); +assert_equal_size!(pthread_mutexattr_t, RlctMutexAttr); +assert_equal_size!(pthread_cond_t, RlctCond); +assert_equal_size!(pthread_condattr_t, RlctCondAttr); +assert_equal_size!(pthread_spinlock_t, RlctSpinlock); +assert_equal_size!(pthread_once_t, RlctOnce); + +pub type pthread_t = *mut c_void; pub type pthread_key_t = c_ulong; diff --git a/src/header/bits_sched/mod.rs b/src/header/bits_sched/mod.rs index b092dbdd7..149fc8eb0 100644 --- a/src/header/bits_sched/mod.rs +++ b/src/header/bits_sched/mod.rs @@ -1,9 +1,3 @@ #![allow(non_camel_case_types)] use crate::platform::types::*; - -#[repr(C)] -#[derive(Clone, Copy, Debug)] -pub struct sched_param { - pub sched_priority: c_int, -} diff --git a/src/header/pthread/attr.rs b/src/header/pthread/attr.rs index a13dac614..b9f727945 100644 --- a/src/header/pthread/attr.rs +++ b/src/header/pthread/attr.rs @@ -2,7 +2,7 @@ use super::*; use crate::header::bits_pthread::pthread_attr_t; -impl Default for pthread_attr_t { +impl Default for RlctAttr { fn default() -> Self { Self { // Default according to POSIX. @@ -28,110 +28,113 @@ impl Default for pthread_attr_t { } #[no_mangle] -pub unsafe extern "C" fn pthread_attr_destroy(_attr: *mut pthread_attr_t) -> c_int { +pub unsafe extern "C" fn pthread_attr_destroy(attr: *mut pthread_attr_t) -> c_int { + let _attr = &mut *attr.cast::<RlctAttr>(); + + // No-op 0 } #[no_mangle] pub unsafe extern "C" fn pthread_attr_getdetachstate(attr: *const pthread_attr_t, detachstate: *mut c_int) -> c_int { - core::ptr::write(detachstate, (*attr).detachstate as _); + core::ptr::write(detachstate, (*attr.cast::<RlctAttr>()).detachstate as _); 0 } #[no_mangle] pub unsafe extern "C" fn pthread_attr_getguardsize(attr: *const pthread_attr_t, size: *mut size_t) -> c_int { - core::ptr::write(size, (*attr).guardsize); + core::ptr::write(size, (*attr.cast::<RlctAttr>()).guardsize); 0 } #[no_mangle] pub unsafe extern "C" fn pthread_attr_getinheritsched(attr: *const pthread_attr_t, inheritsched: *mut c_int) -> c_int { - core::ptr::write(inheritsched, (*attr).inheritsched as _); + core::ptr::write(inheritsched, (*attr.cast::<RlctAttr>()).inheritsched as _); 0 } #[no_mangle] pub unsafe extern "C" fn pthread_attr_getschedparam(attr: *const pthread_attr_t, param: *mut sched_param) -> c_int { - core::ptr::write(param, (*attr).param); + param.write((*attr.cast::<RlctAttr>()).param); 0 } #[no_mangle] pub unsafe extern "C" fn pthread_attr_getschedpolicy(attr: *const pthread_attr_t, policy: *mut c_int) -> c_int { - core::ptr::write(policy, (*attr).schedpolicy as _); + core::ptr::write(policy, (*attr.cast::<RlctAttr>()).schedpolicy as _); 0 } #[no_mangle] pub unsafe extern "C" fn pthread_attr_getscope(attr: *const pthread_attr_t, scope: *mut c_int) -> c_int { - core::ptr::write(scope, (*attr).scope as _); + core::ptr::write(scope, (*attr.cast::<RlctAttr>()).scope as _); 0 } #[no_mangle] pub unsafe extern "C" fn pthread_attr_getstack(attr: *const pthread_attr_t, stackaddr: *mut *mut c_void, stacksize: *mut size_t) -> c_int { - core::ptr::write(stackaddr, (*attr).stack as _); - core::ptr::write(stacksize, (*attr).stacksize as _); + core::ptr::write(stackaddr, (*attr.cast::<RlctAttr>()).stack as _); + core::ptr::write(stacksize, (*attr.cast::<RlctAttr>()).stacksize as _); 0 } #[no_mangle] pub unsafe extern "C" fn pthread_attr_getstacksize(attr: *const pthread_attr_t, stacksize: *mut c_int) -> c_int { - core::ptr::write(stacksize, (*attr).stacksize as _); + core::ptr::write(stacksize, (*attr.cast::<RlctAttr>()).stacksize as _); 0 } #[no_mangle] pub unsafe extern "C" fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int { - core::ptr::write(attr, pthread_attr_t::default()); + core::ptr::write(attr.cast::<RlctAttr>(), RlctAttr::default()); 0 } #[no_mangle] pub unsafe extern "C" fn pthread_attr_setdetachstate(attr: *mut pthread_attr_t, detachstate: c_int) -> c_int { - (*attr).detachstate = detachstate as _; + (*attr.cast::<RlctAttr>()).detachstate = detachstate as _; 0 } #[no_mangle] pub unsafe extern "C" fn pthread_attr_setguardsize(attr: *mut pthread_attr_t, guardsize: c_int) -> c_int { - (*attr).guardsize = guardsize as _; + (*attr.cast::<RlctAttr>()).guardsize = guardsize as _; 0 } #[no_mangle] pub unsafe extern "C" fn pthread_attr_setinheritsched(attr: *mut pthread_attr_t, inheritsched: c_int) -> c_int { - (*attr).inheritsched = inheritsched as _; + (*attr.cast::<RlctAttr>()).inheritsched = inheritsched as _; 0 } #[no_mangle] pub unsafe extern "C" fn pthread_attr_setschedparam(attr: *mut pthread_attr_t, param: *const sched_param) -> c_int { - (*attr).param = core::ptr::read(param); + (*attr.cast::<RlctAttr>()).param = param.read(); 0 } #[no_mangle] pub unsafe extern "C" fn pthread_attr_setschedpolicy(attr: *mut pthread_attr_t, policy: c_int) -> c_int { - (*attr).schedpolicy = policy as u8; + (*attr.cast::<RlctAttr>()).schedpolicy = policy as u8; 0 } #[no_mangle] pub unsafe extern "C" fn pthread_attr_setscope(attr: *mut pthread_attr_t, scope: c_int) -> c_int { - (*attr).scope = scope as u8; + (*attr.cast::<RlctAttr>()).scope = scope as u8; 0 } #[no_mangle] pub unsafe extern "C" fn pthread_attr_setstack(attr: *mut pthread_attr_t, stackaddr: *mut c_void, stacksize: size_t) -> c_int { - (*attr).stack = stackaddr as usize; - (*attr).stacksize = stacksize; + (*attr.cast::<RlctAttr>()).stack = stackaddr as usize; + (*attr.cast::<RlctAttr>()).stacksize = stacksize; 0 } #[no_mangle] pub unsafe extern "C" fn pthread_attr_setstacksize(attr: *mut pthread_attr_t, stacksize: size_t) -> c_int { - (*attr).stacksize = stacksize; + (*attr.cast::<RlctAttr>()).stacksize = stacksize; 0 } diff --git a/src/header/pthread/barrier.rs b/src/header/pthread/barrier.rs index 3e32ca4ab..630d9b4d5 100644 --- a/src/header/pthread/barrier.rs +++ b/src/header/pthread/barrier.rs @@ -1,9 +1,18 @@ use crate::header::errno::*; -use core::sync::atomic::{AtomicU32, AtomicI32 as AtomicInt, Ordering}; +use core::sync::atomic::{AtomicU32 as AtomicUint, AtomicI32 as AtomicInt, Ordering}; use super::*; +pub(crate) struct RlctBarrier { + pub count: AtomicUint, + pub original_count: c_uint, + pub epoch: AtomicInt, +} +pub(crate) struct RlctBarrierAttr { + pub pshared: c_int, +} + #[no_mangle] pub unsafe extern "C" fn pthread_barrier_destroy(barrier: *mut pthread_barrier_t) -> c_int { // Behavior is undefined if any thread is currently waiting. @@ -12,12 +21,14 @@ pub unsafe extern "C" fn pthread_barrier_destroy(barrier: *mut pthread_barrier_t #[no_mangle] pub unsafe extern "C" fn pthread_barrier_init(barrier: *mut pthread_barrier_t, attr: *const pthread_barrierattr_t, count: c_uint) -> c_int { + let attr = attr.cast::<RlctBarrierAttr>().as_ref(); + if count == 0 { return EINVAL; } - core::ptr::write(barrier, pthread_barrier_t { - count: AtomicU32::new(0), + barrier.cast::<RlctBarrier>().write(RlctBarrier { + count: AtomicUint::new(0), original_count: count, epoch: AtomicInt::new(0), }); @@ -26,7 +37,7 @@ pub unsafe extern "C" fn pthread_barrier_init(barrier: *mut pthread_barrier_t, a #[no_mangle] pub unsafe extern "C" fn pthread_barrier_wait(barrier: *mut pthread_barrier_t) -> c_int { - let barrier: &pthread_barrier_t = &*barrier; + let barrier = &*barrier.cast::<RlctBarrier>(); // TODO: Orderings let mut cached = barrier.count.load(Ordering::SeqCst); @@ -60,13 +71,13 @@ pub unsafe extern "C" fn pthread_barrier_wait(barrier: *mut pthread_barrier_t) - #[no_mangle] pub unsafe extern "C" fn pthread_barrierattr_init(attr: *mut pthread_barrierattr_t) -> c_int { // PTHREAD_PROCESS_PRIVATE is default according to POSIX. - core::ptr::write(attr, pthread_barrierattr_t { pshared: PTHREAD_PROCESS_PRIVATE }); + core::ptr::write(attr.cast::<RlctBarrierAttr>(), RlctBarrierAttr { pshared: PTHREAD_PROCESS_PRIVATE }); 0 } #[no_mangle] pub unsafe extern "C" fn pthread_barrierattr_setpshared(attr: *mut pthread_barrierattr_t, pshared: c_int) -> c_int { - (*attr).pshared = pshared; + (*attr.cast::<RlctBarrierAttr>()).pshared = pshared; 0 } diff --git a/src/header/pthread/cond.rs b/src/header/pthread/cond.rs index 545d918a4..25d2faf5a 100644 --- a/src/header/pthread/cond.rs +++ b/src/header/pthread/cond.rs @@ -12,7 +12,7 @@ pub unsafe extern "C" fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> c_ } unsafe fn wake(cond: *mut pthread_cond_t, n: i32) -> c_int { - let cond: &pthread_cond_t = &*cond; + let cond = &*cond.cast::<RlctCond>(); // This is formally correct as long as we don't have more than u32::MAX threads. let prev = cond.prev.load(Ordering::SeqCst); @@ -25,13 +25,15 @@ unsafe fn wake(cond: *mut pthread_cond_t, n: i32) -> c_int { #[no_mangle] pub unsafe extern "C" fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> c_int { - let _cond: &pthread_cond_t = &*cond; + let _cond = &mut cond.cast::<RlctCond>(); + + // No-op 0 } #[no_mangle] pub unsafe extern "C" fn pthread_cond_init(cond: *mut pthread_cond_t, _attr: *const pthread_condattr_t) -> c_int { - cond.write(pthread_cond_t { + cond.cast::<RlctCond>().write(RlctCond { cur: AtomicInt::new(0), prev: AtomicInt::new(0), }); @@ -47,11 +49,11 @@ pub unsafe extern "C" fn pthread_cond_signal(cond: *mut pthread_cond_t) -> c_int pub unsafe extern "C" fn pthread_cond_timedwait(cond: *mut pthread_cond_t, mutex_ptr: *mut pthread_mutex_t, timeout: *const timespec) -> c_int { // TODO: Error checking for certain types (i.e. robust and errorcheck) of mutexes, e.g. if the // mutex is not locked. - let cond: &pthread_cond_t = &*cond; + let cond = &*cond.cast::<RlctCond>(); let timeout: Option<×pec> = timeout.as_ref(); let current = cond.cur.load(Ordering::Relaxed); - cond.prev.store(current, Ordering::SeqCst); + cond.prev.store(current, Ordering::SeqCst); // TODO: ordering? pthread_mutex_unlock(mutex_ptr); crate::sync::futex_wait(&cond.cur, current, timeout); @@ -67,41 +69,54 @@ pub unsafe extern "C" fn pthread_cond_wait(cond: *mut pthread_cond_t, mutex: *mu #[no_mangle] pub unsafe extern "C" fn pthread_condattr_destroy(condattr: *mut pthread_condattr_t) -> c_int { + let _condattr = &mut *condattr.cast::<RlctCondAttr>(); + + // No-op 0 } #[no_mangle] pub unsafe extern "C" fn pthread_condattr_getclock(condattr: *const pthread_condattr_t, clock: *mut clockid_t) -> c_int { - core::ptr::write(clock, (*condattr).clock); + core::ptr::write(clock, (*condattr.cast::<RlctCondAttr>()).clock); 0 } #[no_mangle] pub unsafe extern "C" fn pthread_condattr_getpshared(condattr: *const pthread_condattr_t, pshared: *mut c_int) -> c_int { - core::ptr::write(pshared, (*condattr).pshared); + core::ptr::write(pshared, (*condattr.cast::<RlctCondAttr>()).pshared); 0 } #[no_mangle] pub unsafe extern "C" fn pthread_condattr_init(condattr: *mut pthread_condattr_t) -> c_int { - core::ptr::write(condattr, pthread_condattr_t { + condattr.cast::<RlctCondAttr>().write(RlctCondAttr { // FIXME: system clock clock: 0, // Default pshared: PTHREAD_PROCESS_PRIVATE, }); + 0 } #[no_mangle] pub unsafe extern "C" fn pthread_condattr_setclock(condattr: *mut pthread_condattr_t, clock: clockid_t) -> c_int { - (*condattr).clock = clock; + (*condattr.cast::<RlctCondAttr>()).clock = clock; 0 } #[no_mangle] pub unsafe extern "C" fn pthread_condattr_setpshared(condattr: *mut pthread_condattr_t, pshared: c_int) -> c_int { - (*condattr).pshared = pshared; + (*condattr.cast::<RlctCondAttr>()).pshared = pshared; 0 } +pub(crate) struct RlctCondAttr { + pub clock: clockid_t, + pub pshared: c_int, +} + +pub(crate) struct RlctCond { + pub cur: AtomicInt, + pub prev: AtomicInt, +} diff --git a/src/header/pthread/mod.rs b/src/header/pthread/mod.rs index 7bdf7de4d..ea6d3f150 100644 --- a/src/header/pthread/mod.rs +++ b/src/header/pthread/mod.rs @@ -6,6 +6,18 @@ use crate::platform::{self, Pal, Sys, types::*}; use crate::header::{sched::*, time::timespec}; use crate::pthread; +#[derive(Clone, Copy)] +pub(crate) struct RlctAttr { + pub detachstate: c_uchar, + pub inheritsched: c_uchar, + pub schedpolicy: c_uchar, + pub scope: c_uchar, + pub guardsize: size_t, + pub stacksize: size_t, + pub stack: size_t, + pub param: sched_param, +} + pub const PTHREAD_BARRIER_SERIAL_THREAD: c_int = 1; pub const PTHREAD_CANCEL_ASYNCHRONOUS: c_int = 0; @@ -59,7 +71,7 @@ pub use self::cond::*; #[no_mangle] pub unsafe extern "C" fn pthread_create(pthread: *mut pthread_t, attr: *const pthread_attr_t, start_routine: extern "C" fn(arg: *mut c_void) -> *mut c_void, arg: *mut c_void) -> c_int { - let attr = NonNull::new(attr as *mut _).map(|n| n.as_ref()); + let attr = attr.cast::<RlctAttr>().as_ref(); match pthread::create(attr, start_routine, arg) { Ok(ptr) => { diff --git a/src/header/pthread/mutex.rs b/src/header/pthread/mutex.rs index 3ea242e74..c5490cdbc 100644 --- a/src/header/pthread/mutex.rs +++ b/src/header/pthread/mutex.rs @@ -2,6 +2,8 @@ use super::*; use crate::header::errno::EBUSY; +use core::sync::atomic::AtomicI32 as AtomicInt; + // PTHREAD_MUTEX_INITIALIZER // #[no_mangle] @@ -20,15 +22,19 @@ pub extern "C" fn pthread_mutex_getprioceiling(mutex: *const pthread_mutex_t, pr } #[no_mangle] -pub unsafe extern "C" fn pthread_mutex_init(mutex: *mut pthread_mutex_t, _attr: *const pthread_mutexattr_t) -> c_int { +pub unsafe extern "C" fn pthread_mutex_init(mutex: *mut pthread_mutex_t, attr: *const pthread_mutexattr_t) -> c_int { + let attr = attr.cast::<RlctMutexAttr>().as_ref(); + // TODO: attr - mutex.write(pthread_mutex_t { + mutex.cast::<RlctMutex>().write(RlctMutex { inner: crate::sync::mutex::UNLOCKED.into(), }); 0 } #[no_mangle] pub unsafe extern "C" fn pthread_mutex_lock(mutex: *mut pthread_mutex_t) -> c_int { + let mutex = &*mutex.cast::<RlctMutex>(); + crate::sync::mutex::manual_lock_generic(&(&*mutex).inner); 0 @@ -45,6 +51,8 @@ pub extern "C" fn pthread_mutex_timedlock(mutex: *mut pthread_mutex_t, timespec: } #[no_mangle] pub unsafe extern "C" fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> c_int { + let mutex = &*mutex.cast::<RlctMutex>(); + if crate::sync::mutex::manual_try_lock_generic(&(&*mutex).inner) { 0 } else { @@ -53,6 +61,8 @@ pub unsafe extern "C" fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> c } #[no_mangle] pub unsafe extern "C" fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> c_int { + let mutex = &*mutex.cast::<RlctMutex>(); + crate::sync::mutex::manual_unlock_generic(&(&*mutex).inner); 0 } @@ -64,35 +74,35 @@ pub extern "C" fn pthread_mutexattr_destroy(_attr: *mut pthread_mutexattr_t) -> #[no_mangle] pub unsafe extern "C" fn pthread_mutexattr_getprioceiling(attr: *const pthread_mutexattr_t, prioceiling: *mut c_int) -> c_int { - prioceiling.write((*attr).prioceiling); + prioceiling.write((*attr.cast::<RlctMutexAttr>()).prioceiling); 0 } #[no_mangle] pub unsafe extern "C" fn pthread_mutexattr_getprotocol(attr: *const pthread_mutexattr_t, protocol: *mut c_int) -> c_int { - protocol.write((*attr).protocol); + protocol.write((*attr.cast::<RlctMutexAttr>()).protocol); 0 } #[no_mangle] pub unsafe extern "C" fn pthread_mutexattr_getpshared(attr: *const pthread_mutexattr_t, pshared: *mut c_int) -> c_int { - pshared.write((*attr).pshared); + pshared.write((*attr.cast::<RlctMutexAttr>()).pshared); 0 } #[no_mangle] pub unsafe extern "C" fn pthread_mutexattr_getrobust(attr: *const pthread_mutexattr_t, robust: *mut c_int) -> c_int { - robust.write((*attr).robust); + robust.write((*attr.cast::<RlctMutexAttr>()).robust); 0 } #[no_mangle] pub unsafe extern "C" fn pthread_mutexattr_gettype(attr: *const pthread_mutexattr_t, ty: *mut c_int) -> c_int { - ty.write((*attr).ty); + ty.write((*attr.cast::<RlctMutexAttr>()).ty); 0 } #[no_mangle] pub unsafe extern "C" fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> c_int { - attr.write(pthread_mutexattr_t { + attr.cast::<RlctMutexAttr>().write(RlctMutexAttr { robust: PTHREAD_MUTEX_STALLED, pshared: PTHREAD_PROCESS_PRIVATE, protocol: PTHREAD_PRIO_NONE, @@ -105,29 +115,44 @@ pub unsafe extern "C" fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) #[no_mangle] pub unsafe extern "C" fn pthread_mutexattr_setprioceiling(attr: *mut pthread_mutexattr_t, prioceiling: c_int) -> c_int { - (*attr).prioceiling = prioceiling; + (*attr.cast::<RlctMutexAttr>()).prioceiling = prioceiling; 0 } #[no_mangle] pub unsafe extern "C" fn pthread_mutexattr_setprotocol(attr: *mut pthread_mutexattr_t, protocol: c_int) -> c_int { - (*attr).protocol = protocol; + (*attr.cast::<RlctMutexAttr>()).protocol = protocol; 0 } #[no_mangle] pub unsafe extern "C" fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, pshared: c_int) -> c_int { - (*attr).pshared = pshared; + (*attr.cast::<RlctMutexAttr>()).pshared = pshared; 0 } #[no_mangle] pub unsafe extern "C" fn pthread_mutexattr_setrobust(attr: *mut pthread_mutexattr_t, robust: c_int) -> c_int { - (*attr).robust = robust; + (*attr.cast::<RlctMutexAttr>()).robust = robust; 0 } #[no_mangle] pub unsafe extern "C" fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, ty: c_int) -> c_int { - (*attr).ty = ty; + (*attr.cast::<RlctMutexAttr>()).ty = ty; 0 } + +#[repr(C)] +pub(crate) struct RlctMutex { + pub inner: AtomicInt, +} + +#[repr(C)] +pub(crate) struct RlctMutexAttr { + pub prioceiling: c_int, + pub protocol: c_int, + pub pshared: c_int, + pub robust: c_int, + pub ty: c_int, +} + diff --git a/src/header/pthread/once.rs b/src/header/pthread/once.rs index 9bb96616f..28400ae6c 100644 --- a/src/header/pthread/once.rs +++ b/src/header/pthread/once.rs @@ -4,10 +4,14 @@ use super::*; #[no_mangle] pub unsafe extern "C" fn pthread_once(once: *mut pthread_once_t, constructor: extern "C" fn()) -> c_int { - let once: &pthread_once_t = &*once; + let once = &*once.cast::<RlctOnce>(); // TODO: Cancellation points - crate::sync::once::call_once_generic(&once.inner, || constructor()); + + once.call_once(|| constructor()); + + //crate::sync::once::call_once_generic(&once.inner, || constructor()); 0 } +pub(crate) type RlctOnce = crate::sync::Once<()>; diff --git a/src/header/pthread/rwlock.rs b/src/header/pthread/rwlock.rs index be2fbf274..6303e3eab 100644 --- a/src/header/pthread/rwlock.rs +++ b/src/header/pthread/rwlock.rs @@ -21,8 +21,10 @@ pub unsafe extern "C" fn pthread_rwlock_destroy(rwlock: *mut pthread_rwlock_t) - 0 } #[no_mangle] -pub unsafe extern "C" fn pthread_rwlock_init(rwlock: *mut pthread_rwlock_t, _attr: *const pthread_rwlockattr_t) -> c_int { - core::ptr::write(rwlock, pthread_rwlock_t { +pub unsafe extern "C" fn pthread_rwlock_init(rwlock: *mut pthread_rwlock_t, attr: *const pthread_rwlockattr_t) -> c_int { + let attr = attr.cast::<RlctRwlockAttr>().as_ref(); + + rwlock.cast::<RlctRwlock>().write(RlctRwlock { state: AtomicInt::new(0), }); @@ -34,7 +36,7 @@ pub unsafe extern "C" fn pthread_rwlock_rdlock(rwlock: *mut pthread_rwlock_t) -> } #[no_mangle] pub unsafe extern "C" fn pthread_rwlock_timedrdlock(rwlock: *mut pthread_rwlock_t, timeout: *const timespec) -> c_int { - let rwlock: &pthread_rwlock_t = &*rwlock; + let rwlock = &*rwlock.cast::<RlctRwlock>(); let timeout = timeout.as_ref(); loop { @@ -46,7 +48,7 @@ pub unsafe extern "C" fn pthread_rwlock_timedrdlock(rwlock: *mut pthread_rwlock_ } #[no_mangle] pub unsafe extern "C" fn pthread_rwlock_timedwrlock(rwlock: *mut pthread_rwlock_t, timeout: *const timespec) -> c_int { - let rwlock: &pthread_rwlock_t = &*rwlock; + let rwlock = &*rwlock.cast::<RlctRwlock>(); let timeout = timeout.as_ref(); /*loop { @@ -67,7 +69,7 @@ pub unsafe extern "C" fn pthread_rwlock_timedwrlock(rwlock: *mut pthread_rwlock_ } #[no_mangle] pub unsafe extern "C" fn pthread_rwlock_tryrdlock(rwlock: *mut pthread_rwlock_t) -> c_int { - let rwlock: &pthread_rwlock_t = &*rwlock; + let rwlock = &*rwlock.cast::<RlctRwlock>(); let mut cached = rwlock.state.load(Ordering::Acquire) as u32; @@ -89,7 +91,7 @@ pub unsafe extern "C" fn pthread_rwlock_tryrdlock(rwlock: *mut pthread_rwlock_t) } #[no_mangle] pub unsafe extern "C" fn pthread_rwlock_trywrlock(rwlock: *mut pthread_rwlock_t) -> c_int { - let rwlock: &pthread_rwlock_t = &*rwlock; + let rwlock = &*rwlock.cast::<RlctRwlock>(); match rwlock.state.compare_exchange(0, EXCLUSIVE as i32, Ordering::Acquire, Ordering::Relaxed) { Ok(_) => 0, @@ -98,7 +100,7 @@ pub unsafe extern "C" fn pthread_rwlock_trywrlock(rwlock: *mut pthread_rwlock_t) } #[no_mangle] pub unsafe extern "C" fn pthread_rwlock_unlock(rwlock: *const pthread_rwlock_t) -> c_int { - let rwlock: &pthread_rwlock_t = &*rwlock; + let rwlock = &*rwlock.cast::<RlctRwlock>(); let old = rwlock.state.swap(0, Ordering::Release) as u32; @@ -114,20 +116,23 @@ pub unsafe extern "C" fn pthread_rwlock_wrlock(rwlock: *mut pthread_rwlock_t) -> } #[no_mangle] -pub unsafe extern "C" fn pthread_rwlockattr_destroy(_attr: *mut pthread_rwlockattr_t) -> c_int { +pub unsafe extern "C" fn pthread_rwlockattr_destroy(attr: *mut pthread_rwlockattr_t) -> c_int { + let _attr = &mut *attr.cast::<RlctRwlockAttr>(); + + // No-op 0 } #[no_mangle] pub unsafe extern "C" fn pthread_rwlockattr_getpshared(attr: *const pthread_rwlockattr_t, pshared: *mut c_int) -> c_int { - core::ptr::write(pshared, (*attr).pshared); + core::ptr::write(pshared, (*attr.cast::<RlctRwlockAttr>()).pshared); 0 } #[no_mangle] pub unsafe extern "C" fn pthread_rwlockattr_init(attr: *mut pthread_rwlockattr_t) -> c_int { - core::ptr::write(attr, pthread_rwlockattr_t { + attr.cast::<RlctRwlockAttr>().write(RlctRwlockAttr { // Default according to POSIX. pshared: PTHREAD_PROCESS_PRIVATE, }); @@ -137,6 +142,13 @@ pub unsafe extern "C" fn pthread_rwlockattr_init(attr: *mut pthread_rwlockattr_t #[no_mangle] pub unsafe extern "C" fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, pshared: c_int) -> c_int { - (*attr).pshared = pshared; + (*attr.cast::<RlctRwlockAttr>()).pshared = pshared; 0 } + +pub(crate) struct RlctRwlockAttr { + pub pshared: c_int, +} +pub(crate) struct RlctRwlock { + pub state: AtomicInt, +} diff --git a/src/header/pthread/spin.rs b/src/header/pthread/spin.rs index 9e957a638..c847ee340 100644 --- a/src/header/pthread/spin.rs +++ b/src/header/pthread/spin.rs @@ -7,39 +7,54 @@ use super::*; pub const UNLOCKED: c_int = 0; pub const LOCKED: c_int = 1; +#[no_mangle] pub unsafe extern "C" fn pthread_spin_destroy(spinlock: *mut pthread_spinlock_t) -> c_int { + let _spinlock = &mut *spinlock.cast::<RlctSpinlock>(); + + // No-op 0 } +#[no_mangle] pub unsafe extern "C" fn pthread_spin_init(spinlock: *mut pthread_spinlock_t, _pshared: c_int) -> c_int { // TODO: pshared doesn't matter in most situations, as memory is just memory, but this may be // different on some architectures... - core::ptr::write(spinlock, pthread_spinlock_t { inner: AtomicInt::new(UNLOCKED) }); + spinlock.cast::<RlctSpinlock>().write(RlctSpinlock { inner: AtomicInt::new(UNLOCKED) }); 0 } +#[no_mangle] pub unsafe extern "C" fn pthread_spin_lock(spinlock: *mut pthread_spinlock_t) -> c_int { - let spinlock: &pthread_spinlock_t = &*spinlock; + let spinlock = &*spinlock.cast::<RlctSpinlock>(); loop { match spinlock.inner.compare_exchange_weak(UNLOCKED, LOCKED, Ordering::Acquire, Ordering::Relaxed) { - Ok(_) => return 0, + Ok(_) => break, Err(_) => core::hint::spin_loop(), } } + + 0 } +#[no_mangle] pub unsafe extern "C" fn pthread_spin_trylock(spinlock: *mut pthread_spinlock_t) -> c_int { - let spinlock: &pthread_spinlock_t = &*spinlock; + let spinlock = &*spinlock.cast::<RlctSpinlock>(); match spinlock.inner.compare_exchange(UNLOCKED, LOCKED, Ordering::Acquire, Ordering::Relaxed) { - Ok(_) => 0, - Err(_) => EBUSY, + Ok(_) => (), + Err(_) => return EBUSY, } + + 0 } +#[no_mangle] pub unsafe extern "C" fn pthread_spin_unlock(spinlock: *mut pthread_spinlock_t) -> c_int { - let spinlock: &pthread_spinlock_t = &*spinlock; + let spinlock = &*spinlock.cast::<RlctSpinlock>(); spinlock.inner.store(UNLOCKED, Ordering::Release); 0 } +pub(crate) struct RlctSpinlock { + pub inner: AtomicInt, +} diff --git a/src/header/sched/mod.rs b/src/header/sched/mod.rs index 62512d484..b1c485b36 100644 --- a/src/header/sched/mod.rs +++ b/src/header/sched/mod.rs @@ -3,7 +3,10 @@ use crate::platform::{Pal, Sys, types::*}; use crate::header::time::timespec; -pub use crate::header::bits_sched::sched_param; +#[derive(Clone, Copy, Debug)] +pub struct sched_param { + pub sched_priority: c_int, +} pub const SCHED_FIFO: c_int = 0; pub const SCHED_RR: c_int = 1; @@ -18,7 +21,7 @@ pub extern "C" fn sched_get_priority_min(policy: c_int) -> c_int { todo!() } // #[no_mangle] -pub extern "C" fn sched_getparam(pid: pid_t, param: *mut sched_param) -> c_int { +pub unsafe extern "C" fn sched_getparam(pid: pid_t, param: *mut sched_param) -> c_int { todo!() } // #[no_mangle] @@ -26,7 +29,7 @@ pub extern "C" fn sched_rr_get_interval(pid: pid_t, time: *const timespec) -> c_ todo!() } // #[no_mangle] -pub extern "C" fn sched_setparam(pid: pid_t, param: *const sched_param) -> c_int { +pub unsafe extern "C" fn sched_setparam(pid: pid_t, param: *const sched_param) -> c_int { todo!() } // #[no_mangle] diff --git a/src/pthread/mod.rs b/src/pthread/mod.rs index b3573e18f..1d68d8bb5 100644 --- a/src/pthread/mod.rs +++ b/src/pthread/mod.rs @@ -90,7 +90,7 @@ impl Drop for MmapGuard { } } -pub unsafe fn create(attrs: Option<&pthread_attr_t>, start_routine: extern "C" fn(arg: *mut c_void) -> *mut c_void, arg: *mut c_void) -> Result<pthread_t, Errno> { +pub(crate) unsafe fn create(attrs: Option<&header::RlctAttr>, start_routine: extern "C" fn(arg: *mut c_void) -> *mut c_void, arg: *mut c_void) -> Result<pthread_t, Errno> { let attrs = attrs.copied().unwrap_or_default(); // Create a locked mutex, unlocked by the thread after it has started. -- GitLab