Make pthread types opaque, and check against libc.

This commit is contained in:
4lDO2
2023-04-09 16:53:04 +02:00
parent f0d8b6fd31
commit bd6cc20a75
14 changed files with 275 additions and 147 deletions
Generated
+1 -2
View File
@@ -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",
+6 -1
View File
@@ -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" }
+93 -63
View File
@@ -7,75 +7,105 @@ use crate::header::sched::sched_param;
use crate::sync::AtomicLock;
use core::sync::atomic::{AtomicU32 as AtomicUint, AtomicI32 as AtomicInt};
#[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,
}
// 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)]
pub struct pthread_rwlockattr_t {
pub pshared: c_int,
}
#[repr(C)]
pub struct pthread_rwlock_t {
pub state: AtomicInt,
}
#[repr(C)]
pub struct pthread_barrier_t {
pub count: AtomicUint,
pub original_count: c_uint,
pub epoch: AtomicInt,
}
#[repr(C)]
pub struct pthread_barrierattr_t {
pub pshared: c_int,
}
#[repr(C)]
pub struct pthread_mutex_t {
pub inner: AtomicInt,
}
#[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,
}
#[repr(C)]
pub struct pthread_condattr_t {
pub clock: clockid_t,
pub pshared: c_int,
}
#[repr(C)]
pub struct pthread_cond_t {
pub cur: AtomicInt,
pub prev: AtomicInt,
pub union pthread_attr_t {
__relibc_internal_size: [c_uchar; 32],
__relibc_internal_align: c_long,
}
#[repr(C)]
pub struct pthread_spinlock_t {
pub inner: AtomicInt,
pub union pthread_rwlockattr_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_rwlock_t {
__relibc_internal_size: [c_uchar; 4],
__relibc_internal_align: c_int,
}
#[repr(C)]
pub union pthread_barrier_t {
__relibc_internal_size: [c_uchar; 12],
__relibc_internal_align: c_int,
}
#[repr(C)]
pub union pthread_barrierattr_t {
__relibc_internal_size: [c_uchar; 4],
__relibc_internal_align: c_int,
}
#[repr(C)]
pub union pthread_mutex_t {
__relibc_internal_size: [c_uchar; 4],
__relibc_internal_align: c_int,
}
#[repr(C)]
pub union pthread_mutexattr_t {
__relibc_internal_size: [c_uchar; 20],
__relibc_internal_align: c_int,
}
#[repr(C)]
pub union pthread_cond_t {
__relibc_internal_size: [c_uchar; 8],
__relibc_internal_align: c_int,
}
#[repr(C)]
pub union pthread_condattr_t {
__relibc_internal_size: [c_uchar; 8],
__relibc_internal_align: c_int,
}
#[repr(C)]
pub union pthread_spinlock_t {
__relibc_internal_size: [c_uchar; 4],
__relibc_internal_align: c_int,
}
#[repr(C)]
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;
-6
View File
@@ -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,
}
+24 -21
View File
@@ -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
}
+17 -6
View File
@@ -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
}
+25 -10
View File
@@ -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<&timespec> = 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,
}
+13 -1
View File
@@ -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) => {
+38 -13
View File
@@ -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,
}
+6 -2
View File
@@ -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<()>;
+23 -11
View File
@@ -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,
}
+22 -7
View File
@@ -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,
}
+6 -3
View File
@@ -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]
+1 -1
View File
@@ -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.