Make pthread types opaque, and check against libc.
This commit is contained in:
Generated
+1
-2
@@ -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
@@ -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" }
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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
@@ -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,
|
||||
}
|
||||
|
||||
|
||||
@@ -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<()>;
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user