Add needed functions for acid to link.
This commit is contained in:
+54
-18
@@ -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 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_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 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]
|
||||
|
||||
+10
-24
@@ -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::*;
|
||||
|
||||
+96
-38
@@ -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
|
||||
}
|
||||
|
||||
|
||||
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_getprioceiling(attr: *const pthread_mutexattr_t, prioceiling: *mut c_int) -> c_int {
|
||||
prioceiling.write((*attr).prioceiling);
|
||||
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_getprotocol(attr: *const pthread_mutexattr_t, protocol: *mut c_int) -> c_int {
|
||||
protocol.write((*attr).protocol);
|
||||
0
|
||||
}
|
||||
|
||||
pub extern "C" fn pthread_mutexattr_getrobust(attr: *const pthread_mutexattr_t, robust: *mut c_int) -> c_int {
|
||||
todo!();
|
||||
}
|
||||
pub extern "C" fn pthread_mutexattr_gettype(attr: *const pthread_mutexattr_t, ty: *mut c_int) -> c_int {
|
||||
todo!();
|
||||
}
|
||||
pub extern "C" fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> 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_setprioceiling(attr: *mut pthread_mutexattr_t, prioceiling: 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
|
||||
}
|
||||
#[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
|
||||
}
|
||||
#[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_setprotocol(attr: *mut pthread_mutexattr_t, protocol: 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_setpshared(attr: *mut pthread_mutexattr_t, pshared: 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_setrobust(attr: *mut pthread_mutexattr_t, robust: 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_settype(attr: *mut pthread_mutexattr_t, ty: 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
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, ty: c_int) -> c_int {
|
||||
(*attr).ty = ty;
|
||||
0
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
+4
-2
@@ -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);
|
||||
|
||||
+21
-18
@@ -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:
|
||||
|
||||
+1
-1
@@ -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> {}
|
||||
|
||||
Reference in New Issue
Block a user