diff --git a/src/header/pthread/cond.rs b/src/header/pthread/cond.rs index 4ec2018bc73ae5fb0f32feadafdc6cb09cc3a8d8..45aaf13f73be803ab456f882bbec4243d03e115f 100644 --- a/src/header/pthread/cond.rs +++ b/src/header/pthread/cond.rs @@ -1,5 +1,9 @@ +// Used design from https://www.remlab.net/op/futex-condvar.shtml + use super::*; +use core::sync::atomic::{AtomicI32 as AtomicInt, Ordering}; + // PTHREAD_COND_INITIALIZER #[repr(C)] @@ -10,36 +14,68 @@ pub struct CondAttr { #[repr(C)] pub struct Cond { + cur: AtomicInt, + prev: AtomicInt, } -// #[no_mangle] -pub extern "C" fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> c_int { - todo!() +#[no_mangle] +pub unsafe extern "C" fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> c_int { + wake(cond, i32::MAX) } -// #[no_mangle] -pub extern "C" fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> c_int { - todo!() +unsafe fn wake(cond: *mut pthread_cond_t, n: i32) -> c_int { + let cond: &pthread_cond_t = &*cond; + + // This is formally correct as long as we don't have more than u32::MAX threads. + let prev = cond.prev.load(Ordering::SeqCst); + cond.cur.store(prev.wrapping_add(1), Ordering::SeqCst); + + crate::sync::futex_wake(&cond.cur, n); + + 0 } -// #[no_mangle] -pub extern "C" fn pthread_cond_init(cond: *mut pthread_cond_t, attr: *const pthread_condattr_t) -> c_int { - todo!() +#[no_mangle] +pub unsafe extern "C" fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> c_int { + let _cond: &pthread_cond_t = &*cond; + 0 } -// #[no_mangle] -pub extern "C" fn pthread_cond_signal(cond: *mut pthread_cond_t) -> c_int { - todo!() +#[no_mangle] +pub unsafe extern "C" fn pthread_cond_init(cond: *mut pthread_cond_t, _attr: *const pthread_condattr_t) -> c_int { + cond.write(Cond { + cur: AtomicInt::new(0), + prev: AtomicInt::new(0), + }); + 0 } -// #[no_mangle] -pub extern "C" fn pthread_cond_timedwait(cond: *mut pthread_cond_t, mutex: *const pthread_mutex_t, timeout: *const timespec) -> c_int { - todo!() +#[no_mangle] +pub unsafe extern "C" fn pthread_cond_signal(cond: *mut pthread_cond_t) -> c_int { + wake(cond, 1) +} + +#[no_mangle] +pub unsafe extern "C" fn pthread_cond_timedwait(cond: *mut pthread_cond_t, mutex_ptr: *const 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 mutex: &pthread_mutex_t = &*mutex_ptr; + let timeout: Option<×pec> = timeout.as_ref(); + + let current = cond.cur.load(Ordering::Relaxed); + cond.prev.store(current, Ordering::SeqCst); + + mutex.inner.manual_unlock(); + crate::sync::futex_wait(&cond.cur, current, timeout); + mutex.inner.manual_lock(); + + 0 } -// #[no_mangle] -pub extern "C" fn pthread_cond_wait(cond: *mut pthread_cond_t, mutex: *const pthread_mutex_t) -> c_int { - todo!() +#[no_mangle] +pub unsafe extern "C" fn pthread_cond_wait(cond: *mut pthread_cond_t, mutex: *const pthread_mutex_t) -> c_int { + pthread_cond_timedwait(cond, mutex, core::ptr::null()) } #[no_mangle] diff --git a/src/header/pthread/mod.rs b/src/header/pthread/mod.rs index 5b7425f997d4af5caf15a0af50b6fc5fd36ad574..db215d811b023006cfe53ee7a999f8ff4ed87773 100644 --- a/src/header/pthread/mod.rs +++ b/src/header/pthread/mod.rs @@ -9,9 +9,9 @@ use crate::pthread; pub const PTHREAD_BARRIER_SERIAL_THREAD: c_int = 1; pub const PTHREAD_CANCEL_ASYNCHRONOUS: c_int = 0; -pub const PTHREAD_CANCEL_ENABLE: c_int = 0; -pub const PTHREAD_CANCEL_DEFERRED: c_int = 0; -pub const PTHREAD_CANCEL_DISABLE: c_int = 0; +pub const PTHREAD_CANCEL_ENABLE: c_int = 1; +pub const PTHREAD_CANCEL_DEFERRED: c_int = 2; +pub const PTHREAD_CANCEL_DISABLE: c_int = 3; pub const PTHREAD_CANCELED: *mut c_void = core::ptr::null_mut(); pub const PTHREAD_CREATE_DETACHED: c_int = 0; @@ -21,11 +21,12 @@ pub const PTHREAD_EXPLICIT_SCHED: c_int = 0; pub const PTHREAD_INHERIT_SCHED: c_int = 1; pub const PTHREAD_MUTEX_DEFAULT: c_int = 0; -pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 0; -pub const PTHREAD_MUTEX_NORMAL: c_int = 0; -pub const PTHREAD_MUTEX_RECURSIVE: c_int = 0; +pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 1; +pub const PTHREAD_MUTEX_NORMAL: c_int = 2; +pub const PTHREAD_MUTEX_RECURSIVE: c_int = 3; + pub const PTHREAD_MUTEX_ROBUST: c_int = 0; -pub const PTHREAD_MUTEX_STALLED: c_int = 0; +pub const PTHREAD_MUTEX_STALLED: c_int = 1; pub const PTHREAD_PRIO_INHERIT: c_int = 0; @@ -102,10 +103,8 @@ pub extern "C" fn pthread_getschedparam(thread: pthread_t, policy: *mut clockid_ todo!() } -// #[no_mangle] -pub extern "C" fn pthread_getspecific(key: pthread_key_t) -> *mut c_void { - todo!() -} +pub mod tls; +pub use tls::*; #[no_mangle] pub unsafe extern "C" fn pthread_join(thread: pthread_t, retval: *mut *mut c_void) -> c_int { @@ -118,16 +117,6 @@ pub unsafe extern "C" fn pthread_join(thread: pthread_t, retval: *mut *mut c_voi } } -// #[no_mangle] -pub extern "C" fn pthread_key_create(key: *mut pthread_key_t, destructor: extern "C" fn(value: *mut c_void)) -> c_int { - todo!() -} - -// #[no_mangle] -pub extern "C" fn pthread_key_delete(key: pthread_key_t) -> c_int { - todo!() -} - pub mod mutex; pub use self::mutex::*; @@ -157,9 +146,6 @@ pub extern "C" fn pthread_setschedparam(thread: pthread_t, policy: c_int, param: pub extern "C" fn pthread_setschedprio(thread: pthread_t, prio: c_int) -> c_int { todo!(); } -pub extern "C" fn pthread_setspecific(key: pthread_key_t, value: *const c_void) -> c_int { - todo!(); -} pub mod spin; pub use self::spin::*; diff --git a/src/header/pthread/mutex.rs b/src/header/pthread/mutex.rs index eec8d5bdf835d067660bac082c8747164f102f92..be8d40bf3b79694cd2ade1fe8855a6e093cbe1b9 100644 --- a/src/header/pthread/mutex.rs +++ b/src/header/pthread/mutex.rs @@ -1,88 +1,146 @@ use super::*; +use crate::header::errno::EBUSY; + // PTHREAD_MUTEX_INITIALIZER #[repr(C)] pub struct Mutex { + pub(crate) inner: crate::sync::Mutex<()>, } #[repr(C)] pub struct MutexAttr { + prioceiling: c_int, + protocol: c_int, + pshared: c_int, + robust: c_int, + ty: c_int, } +// #[no_mangle] pub extern "C" fn pthread_mutex_consistent(mutex: *mut pthread_mutex_t) -> c_int { todo!(); } -pub extern "C" fn pthread_mutex_destroy(mutex: *mut pthread_mutex_t) -> c_int { - todo!(); +#[no_mangle] +pub unsafe extern "C" fn pthread_mutex_destroy(mutex: *mut pthread_mutex_t) -> c_int { + let _mutex: &pthread_mutex_t = &*mutex; + 0 } +// #[no_mangle] pub extern "C" fn pthread_mutex_getprioceiling(mutex: *const pthread_mutex_t, prioceiling: *mut c_int) -> c_int { todo!(); } -pub extern "C" fn pthread_mutex_init(mutex: *mut pthread_mutex_t, attr: *const pthread_mutexattr_t) -> c_int { - todo!(); +#[no_mangle] +pub unsafe extern "C" fn pthread_mutex_init(mutex: *mut pthread_mutex_t, _attr: *const pthread_mutexattr_t) -> c_int { + // TODO: attr + mutex.write(Mutex { + inner: crate::sync::Mutex::new(()), + }); + 0 } -pub extern "C" fn pthread_mutex_lock(mutex: *mut pthread_mutex_t) -> c_int { - todo!(); +#[no_mangle] +pub unsafe extern "C" fn pthread_mutex_lock(mutex: *mut pthread_mutex_t) -> c_int { + (&*mutex).inner.manual_lock(); + + 0 } +// #[no_mangle] pub extern "C" fn pthread_mutex_setprioceiling(mutex: *mut pthread_mutex_t, prioceiling: c_int, old_prioceiling: *mut c_int) -> c_int { todo!(); } +// #[no_mangle] pub extern "C" fn pthread_mutex_timedlock(mutex: *mut pthread_mutex_t, timespec: *const timespec) -> c_int { todo!(); } -pub extern "C" fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> c_int { - todo!(); +#[no_mangle] +pub unsafe extern "C" fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> c_int { + match (&*mutex).inner.manual_try_lock() { + Ok(_) => 0, + Err(_) => EBUSY, + } } -pub extern "C" fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> c_int { - todo!(); -} -pub extern "C" fn pthread_mutexattr_destroy(attr: *mut pthread_mutexattr_t) -> c_int { - todo!(); +#[no_mangle] +pub unsafe extern "C" fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> c_int { + (&*mutex).inner.manual_unlock(); + 0 } -pub extern "C" fn pthread_mutexattr_getprioceiling(attr: *const pthread_mutexattr_t, prioceiling: *mut c_int) -> c_int { - todo!(); +#[no_mangle] +pub extern "C" fn pthread_mutexattr_destroy(_attr: *mut pthread_mutexattr_t) -> c_int { + 0 } +#[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); + 0 +} -pub extern "C" fn pthread_mutexattr_getprotocol(attr: *const pthread_mutexattr_t, protocol: *mut c_int) -> c_int { - todo!(); +#[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); + 0 } -pub extern "C" fn pthread_mutexattr_getpshared(attr: *const pthread_mutexattr_t, pshared: *mut c_int) -> c_int { - todo!(); +#[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); + 0 } -pub extern "C" fn pthread_mutexattr_getrobust(attr: *const pthread_mutexattr_t, robust: *mut c_int) -> c_int { - todo!(); +#[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); + 0 } -pub extern "C" fn pthread_mutexattr_gettype(attr: *const pthread_mutexattr_t, ty: *mut c_int) -> c_int { - todo!(); +#[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); + 0 } -pub extern "C" fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> c_int { - todo!(); +#[no_mangle] +pub unsafe extern "C" fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> c_int { + attr.write(MutexAttr { + robust: PTHREAD_MUTEX_STALLED, + pshared: PTHREAD_PROCESS_PRIVATE, + protocol: PTHREAD_PRIO_NONE, + // TODO + prioceiling: 0, + ty: PTHREAD_MUTEX_DEFAULT, + }); + 0 } -pub extern "C" fn pthread_mutexattr_setprioceiling(attr: *mut pthread_mutexattr_t, prioceiling: c_int) -> c_int { - todo!(); +#[no_mangle] +pub unsafe extern "C" fn pthread_mutexattr_setprioceiling(attr: *mut pthread_mutexattr_t, prioceiling: c_int) -> c_int { + (*attr).prioceiling = prioceiling; + 0 } -pub extern "C" fn pthread_mutexattr_setprotocol(attr: *mut pthread_mutexattr_t, protocol: c_int) -> c_int { - todo!(); +#[no_mangle] +pub unsafe extern "C" fn pthread_mutexattr_setprotocol(attr: *mut pthread_mutexattr_t, protocol: c_int) -> c_int { + (*attr).protocol = protocol; + 0 } -pub extern "C" fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, pshared: c_int) -> c_int { - todo!(); +#[no_mangle] +pub unsafe extern "C" fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, pshared: c_int) -> c_int { + (*attr).pshared = pshared; + 0 } -pub extern "C" fn pthread_mutexattr_setrobust(attr: *mut pthread_mutexattr_t, robust: c_int) -> c_int { - todo!(); +#[no_mangle] +pub unsafe extern "C" fn pthread_mutexattr_setrobust(attr: *mut pthread_mutexattr_t, robust: c_int) -> c_int { + (*attr).robust = robust; + 0 } -pub extern "C" fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, ty: c_int) -> c_int { - todo!(); +#[no_mangle] +pub unsafe extern "C" fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, ty: c_int) -> c_int { + (*attr).ty = ty; + 0 } diff --git a/src/header/pthread/rwlock.rs b/src/header/pthread/rwlock.rs index fbc20c0232fa31ff671933358ac353b33e35a46f..375a40828cec898f6e505e9ae4a9e08a95022473 100644 --- a/src/header/pthread/rwlock.rs +++ b/src/header/pthread/rwlock.rs @@ -46,7 +46,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 timeout = NonNull::new(timeout as *mut _).map(|n| n.as_ref()); + let timeout = timeout.as_ref(); loop { if pthread_rwlock_tryrdlock(rwlock as *const _ as *mut _) == EBUSY { @@ -58,7 +58,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 timeout = NonNull::new(timeout as *mut _).map(|n| n.as_ref()); + let timeout = timeout.as_ref(); loop { if pthread_rwlock_trywrlock(rwlock as *const _ as *mut _) == EBUSY { diff --git a/src/header/pthread/tls.rs b/src/header/pthread/tls.rs new file mode 100644 index 0000000000000000000000000000000000000000..19d614342d7f5d25dc68f8928b941cf25c3a16b9 --- /dev/null +++ b/src/header/pthread/tls.rs @@ -0,0 +1,73 @@ +use super::*; + +// TODO: Hashmap? +use alloc::collections::BTreeMap; + +use core::cell::{Cell, RefCell}; + +use crate::header::errno::EINVAL; + +// TODO: What should this limit be? +pub const PTHREAD_KEYS_MAX: u32 = 4096 * 32; + +#[no_mangle] +pub unsafe extern "C" fn pthread_getspecific(key: pthread_key_t) -> *mut c_void { + let Some(&Record { data, .. }) = DICT.borrow_mut().get(&key) else { + return core::ptr::null_mut(); + }; + + data +} +#[no_mangle] +pub unsafe extern "C" fn pthread_key_create(key_ptr: *mut pthread_key_t, destructor: extern "C" fn(value: *mut c_void)) -> c_int { + let key = NEXTKEY.get(); + NEXTKEY.set(key + 1); + + // TODO + //if key >= PTHREAD_KEYS_MAX { + //} + + DICT.borrow_mut().insert(key, Record { + data: core::ptr::null_mut(), + destructor, + }); + + key_ptr.write(key); + + 0 +} + +#[no_mangle] +pub unsafe extern "C" fn pthread_key_delete(key: pthread_key_t) -> c_int { + if DICT.borrow_mut().remove(&key).is_none() { + // We don't have to return anything, but it's not less expensive to ignore it. + return EINVAL; + } + + 0 +} + + #[no_mangle] +pub unsafe extern "C" fn pthread_setspecific(key: pthread_key_t, value: *const c_void) -> c_int { + let mut guard = DICT.borrow_mut(); + + let Some(Record { data, .. }) = guard.get_mut(&key) else { + // We don't have to return anything, but it's not less expensive to ignore it. + return EINVAL; + }; + + *data = value as *mut c_void; + + 0 +} + +#[thread_local] +static DICT: RefCell<BTreeMap<u32, Record>> = RefCell::new(BTreeMap::new()); + +struct Record { + data: *mut c_void, + destructor: extern "C" fn(value: *mut c_void), +} + +#[thread_local] +static NEXTKEY: Cell<u32> = Cell::new(1); diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 5ab129d5c3d112e98f8b8ecfba474b64367d67c1..9885a939b14ceeb26cd460b047ed854177dea861 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -219,8 +219,8 @@ impl Pal for Sys { e(unsafe { syscall!(FTRUNCATE, fildes, length) }) as c_int } - fn futex(addr: *mut c_int, op: c_int, val: c_int, val2: usize) -> c_int { - unsafe { syscall!(FUTEX, addr, op, val, val2, 0, 0) as c_int } + fn futex(addr: *mut c_int, op: c_int, val: c_int, val2: usize) -> Result<c_long, crate::pthread::Errno> { + e_raw(unsafe { syscall!(FUTEX, addr, op, val, val2, 0, 0)}).map(|r| r as c_long).map_err(|e| Errno(e as c_int)) } fn futimens(fd: c_int, times: *const timespec) -> c_int { diff --git a/src/platform/pal/mod.rs b/src/platform/pal/mod.rs index 37d1b34aba34623a3c6ac33742cb4842546eed38..1dfdd2c7e1670e5f25da0b634e0c915f7c80a0ca 100644 --- a/src/platform/pal/mod.rs +++ b/src/platform/pal/mod.rs @@ -73,7 +73,7 @@ pub trait Pal { fn ftruncate(fildes: c_int, length: off_t) -> c_int; - fn futex(addr: *mut c_int, op: c_int, val: c_int, val2: usize) -> c_int; + fn futex(addr: *mut c_int, op: c_int, val: c_int, val2: usize) -> Result<c_long, crate::pthread::Errno>; fn futimens(fd: c_int, times: *const timespec) -> c_int; diff --git a/src/platform/pte.rs b/src/platform/pte.rs index e8796dba173de51abdd7567470b6ee947e500893..34000b6343eb295a3007151a9ea1c15413a347bd 100644 --- a/src/platform/pte.rs +++ b/src/platform/pte.rs @@ -51,10 +51,6 @@ static LOCALS: UnsafeCell<BTreeMap<c_uint, *mut c_void>> = UnsafeCell::new(BTree static NEXT_KEY: AtomicU32 = AtomicU32::new(0); -unsafe fn locals<'a>() -> &'a mut BTreeMap<c_uint, *mut c_void> { - &mut *LOCALS.get() -} - #[no_mangle] pub unsafe extern "C" fn pte_osThreadStart(handle: pte_osThreadHandle) -> pte_osResult { let mut ret = PTE_OS_GENERAL_FAILURE; @@ -250,64 +246,3 @@ pub unsafe extern "C" fn pte_osSemaphorePend( Err(()) => PTE_OS_TIMEOUT, } } - -#[no_mangle] -pub unsafe extern "C" fn pte_osSemaphoreCancellablePend( - handle: pte_osSemaphoreHandle, - pTimeout: *mut c_uint, -) -> pte_osResult { - //TODO: thread cancel - pte_osSemaphorePend(handle, pTimeout) -} - -#[no_mangle] -pub unsafe extern "C" fn pte_osAtomicExchange(ptarg: *mut c_int, val: c_int) -> c_int { - intrinsics::atomic_xchg_seqcst(ptarg, val) -} - -#[no_mangle] -pub unsafe extern "C" fn pte_osAtomicCompareExchange( - pdest: *mut c_int, - exchange: c_int, - comp: c_int, -) -> c_int { - intrinsics::atomic_cxchg_seqcst_seqcst(pdest, comp, exchange).0 -} - -#[no_mangle] -pub unsafe extern "C" fn pte_osAtomicExchangeAdd(pAppend: *mut c_int, value: c_int) -> c_int { - intrinsics::atomic_xadd_seqcst(pAppend, value) -} - -#[no_mangle] -pub unsafe extern "C" fn pte_osAtomicDecrement(pdest: *mut c_int) -> c_int { - intrinsics::atomic_xadd_seqcst(pdest, -1) - 1 -} - -#[no_mangle] -pub unsafe extern "C" fn pte_osAtomicIncrement(pdest: *mut c_int) -> c_int { - intrinsics::atomic_xadd_seqcst(pdest, 1) + 1 -} - -#[no_mangle] -pub unsafe extern "C" fn pte_osTlsSetValue(index: c_uint, value: *mut c_void) -> pte_osResult { - locals().insert(index, value); - PTE_OS_OK -} - -#[no_mangle] -pub unsafe extern "C" fn pte_osTlsGetValue(index: c_uint) -> *mut c_void { - locals().get_mut(&index).copied().unwrap_or(ptr::null_mut()) -} - -#[no_mangle] -pub unsafe extern "C" fn pte_osTlsAlloc(pKey: *mut c_uint) -> pte_osResult { - *pKey = NEXT_KEY.fetch_add(1, Ordering::Relaxed); - PTE_OS_OK -} - -#[no_mangle] -pub unsafe extern "C" fn pte_osTlsFree(index: c_uint) -> pte_osResult { - // XXX free keys - PTE_OS_OK -} diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index b4b423d9ab4f87cf369b96c6c96da6e7e9c252be..e1d87f937ea256c762dae01de0daea638b2a10a3 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -333,7 +333,7 @@ impl Pal for Sys { e(syscall::ftruncate(fd as usize, len as usize)) as c_int } - fn futex(addr: *mut c_int, op: c_int, val: c_int, val2: usize) -> c_int { + fn futex(addr: *mut c_int, op: c_int, val: c_int, val2: usize) -> Result<c_long, crate::pthread::Errno> { match unsafe { syscall::futex( addr as *mut i32, @@ -343,8 +343,8 @@ impl Pal for Sys { ptr::null_mut(), ) } { - Ok(success) => success as c_int, - Err(err) => -(err.errno as c_int), + Ok(success) => Ok(success as c_long), + Err(err) => Err(crate::pthread::Errno(err.errno)), } } diff --git a/src/platform/types.rs b/src/platform/types.rs index 50440b17c07abc5401a984f724b7356c92acc968..037ba2d6a4d135575b35830c061fe14d44b51a60 100644 --- a/src/platform/types.rs +++ b/src/platform/types.rs @@ -82,7 +82,7 @@ pub type pthread_barrier_t = crate::header::pthread::barrier::Barrier; pub type pthread_barrierattr_t = crate::header::pthread::barrier::BarrierAttr; pub type pthread_cond_t = crate::header::pthread::cond::Cond; pub type pthread_condattr_t = crate::header::pthread::cond::CondAttr; -pub type pthread_key_t = *mut c_void; +pub type pthread_key_t = u32; pub type pthread_mutex_t = crate::header::pthread::mutex::Mutex; pub type pthread_mutexattr_t = crate::header::pthread::mutex::MutexAttr; pub type pthread_once_t = crate::header::pthread::once::Once; diff --git a/src/pthread/mod.rs b/src/pthread/mod.rs index df6c023873e800c0f51a03c29bada21190c09822..1110895b550efdc6bfcc94b7ab1211607fe7cf50 100644 --- a/src/pthread/mod.rs +++ b/src/pthread/mod.rs @@ -48,7 +48,8 @@ unsafe impl Sync for Pthread {} use crate::header::pthread::attr::Attr; /// Positive error codes (EINVAL, not -EINVAL). -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq)] +// TODO: Move to a more generic place. pub struct Errno(pub c_int); #[derive(Clone, Copy)] @@ -134,7 +135,8 @@ pub unsafe fn create(attrs: Option<&pthread_attr_t>, start_routine: extern "C" f return Err(Errno(EAGAIN)); }; - let _ = (&mut *synchronization_mutex).lock(); + let _ = (&*synchronization_mutex).lock(); + OS_TID_TO_PTHREAD.lock().insert(os_tid, ForceSendSync(ptr.cast())); core::mem::forget(stack_raii); diff --git a/src/sync/mod.rs b/src/sync/mod.rs index 853831d830239b08a1aab850790fbc82a2705830..8e1e1649fdfcb6eff7d3f2adce38c528ad004136 100644 --- a/src/sync/mod.rs +++ b/src/sync/mod.rs @@ -28,6 +28,21 @@ pub enum AttemptStatus { Other, } +pub unsafe fn futex_wake_ptr(ptr: *mut i32, n: i32) -> usize { + // TODO: unwrap_unchecked? + Sys::futex(ptr, FUTEX_WAKE, n, 0).unwrap() as usize +} +pub unsafe fn futex_wait_ptr(ptr: *mut i32, value: i32, timeout_opt: Option<×pec>) -> bool { + // TODO: unwrap_unchecked? + Sys::futex(ptr, FUTEX_WAIT, value, timeout_opt.map_or(0, |t| t as *const _ as usize)) == Ok(0) +} +pub fn futex_wake(atomic: &AtomicInt, n: i32) -> usize { + unsafe { futex_wake_ptr(atomic.as_mut_ptr(), n) } +} +pub fn futex_wait(atomic: &AtomicInt, value: i32, timeout_opt: Option<×pec>) -> bool { + unsafe { futex_wait_ptr(atomic.as_mut_ptr(), value, timeout_opt) } +} + /// Convenient wrapper around the "futex" system call for /// synchronization implementations #[repr(C)] @@ -41,28 +56,16 @@ impl AtomicLock { } } pub fn notify_one(&self) { - Sys::futex( - self.atomic.as_mut_ptr(), - FUTEX_WAKE, - 1, - 0, - ); + futex_wake(&self.atomic, 1); } pub fn notify_all(&self) { - Sys::futex( - self.atomic.as_mut_ptr(), - FUTEX_WAKE, - c_int::max_value(), - 0, - ); + futex_wake(&self.atomic, i32::MAX); } pub fn wait_if(&self, value: c_int, timeout_opt: Option<×pec>) { - Sys::futex( - self.atomic.as_mut_ptr(), - FUTEX_WAIT, - value, - timeout_opt.map_or(0, |timeout| timeout as *const timespec as usize), - ); + self.wait_if_raw(value, timeout_opt); + } + pub fn wait_if_raw(&self, value: c_int, timeout_opt: Option<×pec>) -> bool { + futex_wait(&self.atomic, value, timeout_opt) } /// A general way to efficiently wait for what might be a long time, using two closures: diff --git a/src/sync/mutex.rs b/src/sync/mutex.rs index 127c78ca84108301b313179a33c81482d73f1ba9..b286a90a73c9c7719011a3788fba5ad5bf121142 100644 --- a/src/sync/mutex.rs +++ b/src/sync/mutex.rs @@ -11,7 +11,7 @@ const LOCKED: c_int = 1; const WAITING: c_int = 2; pub struct Mutex<T> { - lock: AtomicLock, + pub(crate) lock: AtomicLock, content: UnsafeCell<T>, } unsafe impl<T: Send> Send for Mutex<T> {}