Add needed functions for acid to link.

4lDO2 6a658bc3 2593101e

Changed files
+265 -172
src
header
platform
linux
pal
redox
pthread
sync
+54 -18
src/header/pthread/cond.rs
··· 1 + // Used design from https://www.remlab.net/op/futex-condvar.shtml 2 + 1 3 use super::*; 4 + 5 + use core::sync::atomic::{AtomicI32 as AtomicInt, Ordering}; 2 6 3 7 // PTHREAD_COND_INITIALIZER 4 8 ··· 10 14 11 15 #[repr(C)] 12 16 pub struct Cond { 17 + cur: AtomicInt, 18 + prev: AtomicInt, 13 19 } 14 20 15 - // #[no_mangle] 16 - pub extern "C" fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> c_int { 17 - todo!() 21 + #[no_mangle] 22 + pub unsafe extern "C" fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> c_int { 23 + wake(cond, i32::MAX) 18 24 } 19 25 20 - // #[no_mangle] 21 - pub extern "C" fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> c_int { 22 - todo!() 26 + unsafe fn wake(cond: *mut pthread_cond_t, n: i32) -> c_int { 27 + let cond: &pthread_cond_t = &*cond; 28 + 29 + // This is formally correct as long as we don't have more than u32::MAX threads. 30 + let prev = cond.prev.load(Ordering::SeqCst); 31 + cond.cur.store(prev.wrapping_add(1), Ordering::SeqCst); 32 + 33 + crate::sync::futex_wake(&cond.cur, n); 34 + 35 + 0 23 36 } 24 37 25 - // #[no_mangle] 26 - pub extern "C" fn pthread_cond_init(cond: *mut pthread_cond_t, attr: *const pthread_condattr_t) -> c_int { 27 - todo!() 38 + #[no_mangle] 39 + pub unsafe extern "C" fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> c_int { 40 + let _cond: &pthread_cond_t = &*cond; 41 + 0 28 42 } 29 43 30 - // #[no_mangle] 31 - pub extern "C" fn pthread_cond_signal(cond: *mut pthread_cond_t) -> c_int { 32 - todo!() 44 + #[no_mangle] 45 + pub unsafe extern "C" fn pthread_cond_init(cond: *mut pthread_cond_t, _attr: *const pthread_condattr_t) -> c_int { 46 + cond.write(Cond { 47 + cur: AtomicInt::new(0), 48 + prev: AtomicInt::new(0), 49 + }); 50 + 0 33 51 } 34 52 35 - // #[no_mangle] 36 - pub extern "C" fn pthread_cond_timedwait(cond: *mut pthread_cond_t, mutex: *const pthread_mutex_t, timeout: *const timespec) -> c_int { 37 - todo!() 53 + #[no_mangle] 54 + pub unsafe extern "C" fn pthread_cond_signal(cond: *mut pthread_cond_t) -> c_int { 55 + wake(cond, 1) 38 56 } 39 57 40 - // #[no_mangle] 41 - pub extern "C" fn pthread_cond_wait(cond: *mut pthread_cond_t, mutex: *const pthread_mutex_t) -> c_int { 42 - todo!() 58 + #[no_mangle] 59 + pub unsafe extern "C" fn pthread_cond_timedwait(cond: *mut pthread_cond_t, mutex_ptr: *const pthread_mutex_t, timeout: *const timespec) -> c_int { 60 + // TODO: Error checking for certain types (i.e. robust and errorcheck) of mutexes, e.g. if the 61 + // mutex is not locked. 62 + let cond: &pthread_cond_t = &*cond; 63 + let mutex: &pthread_mutex_t = &*mutex_ptr; 64 + let timeout: Option<&timespec> = timeout.as_ref(); 65 + 66 + let current = cond.cur.load(Ordering::Relaxed); 67 + cond.prev.store(current, Ordering::SeqCst); 68 + 69 + mutex.inner.manual_unlock(); 70 + crate::sync::futex_wait(&cond.cur, current, timeout); 71 + mutex.inner.manual_lock(); 72 + 73 + 0 74 + } 75 + 76 + #[no_mangle] 77 + pub unsafe extern "C" fn pthread_cond_wait(cond: *mut pthread_cond_t, mutex: *const pthread_mutex_t) -> c_int { 78 + pthread_cond_timedwait(cond, mutex, core::ptr::null()) 43 79 } 44 80 45 81 #[no_mangle]
+10 -24
src/header/pthread/mod.rs
··· 9 9 pub const PTHREAD_BARRIER_SERIAL_THREAD: c_int = 1; 10 10 11 11 pub const PTHREAD_CANCEL_ASYNCHRONOUS: c_int = 0; 12 - pub const PTHREAD_CANCEL_ENABLE: c_int = 0; 13 - pub const PTHREAD_CANCEL_DEFERRED: c_int = 0; 14 - pub const PTHREAD_CANCEL_DISABLE: c_int = 0; 12 + pub const PTHREAD_CANCEL_ENABLE: c_int = 1; 13 + pub const PTHREAD_CANCEL_DEFERRED: c_int = 2; 14 + pub const PTHREAD_CANCEL_DISABLE: c_int = 3; 15 15 pub const PTHREAD_CANCELED: *mut c_void = core::ptr::null_mut(); 16 16 17 17 pub const PTHREAD_CREATE_DETACHED: c_int = 0; ··· 21 21 pub const PTHREAD_INHERIT_SCHED: c_int = 1; 22 22 23 23 pub const PTHREAD_MUTEX_DEFAULT: c_int = 0; 24 - pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 0; 25 - pub const PTHREAD_MUTEX_NORMAL: c_int = 0; 26 - pub const PTHREAD_MUTEX_RECURSIVE: c_int = 0; 24 + pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 1; 25 + pub const PTHREAD_MUTEX_NORMAL: c_int = 2; 26 + pub const PTHREAD_MUTEX_RECURSIVE: c_int = 3; 27 + 27 28 pub const PTHREAD_MUTEX_ROBUST: c_int = 0; 28 - pub const PTHREAD_MUTEX_STALLED: c_int = 0; 29 + pub const PTHREAD_MUTEX_STALLED: c_int = 1; 29 30 30 31 pub const PTHREAD_PRIO_INHERIT: c_int = 0; 31 32 ··· 102 103 todo!() 103 104 } 104 105 105 - // #[no_mangle] 106 - pub extern "C" fn pthread_getspecific(key: pthread_key_t) -> *mut c_void { 107 - todo!() 108 - } 106 + pub mod tls; 107 + pub use tls::*; 109 108 110 109 #[no_mangle] 111 110 pub unsafe extern "C" fn pthread_join(thread: pthread_t, retval: *mut *mut c_void) -> c_int { ··· 116 115 } 117 116 Err(pthread::Errno(error)) => error, 118 117 } 119 - } 120 - 121 - // #[no_mangle] 122 - pub extern "C" fn pthread_key_create(key: *mut pthread_key_t, destructor: extern "C" fn(value: *mut c_void)) -> c_int { 123 - todo!() 124 - } 125 - 126 - // #[no_mangle] 127 - pub extern "C" fn pthread_key_delete(key: pthread_key_t) -> c_int { 128 - todo!() 129 118 } 130 119 131 120 pub mod mutex; ··· 155 144 todo!(); 156 145 } 157 146 pub extern "C" fn pthread_setschedprio(thread: pthread_t, prio: c_int) -> c_int { 158 - todo!(); 159 - } 160 - pub extern "C" fn pthread_setspecific(key: pthread_key_t, value: *const c_void) -> c_int { 161 147 todo!(); 162 148 } 163 149
+93 -35
src/header/pthread/mutex.rs
··· 1 1 use super::*; 2 2 3 + use crate::header::errno::EBUSY; 4 + 3 5 // PTHREAD_MUTEX_INITIALIZER 4 6 5 7 #[repr(C)] 6 8 pub struct Mutex { 9 + pub(crate) inner: crate::sync::Mutex<()>, 7 10 } 8 11 9 12 #[repr(C)] 10 13 pub struct MutexAttr { 14 + prioceiling: c_int, 15 + protocol: c_int, 16 + pshared: c_int, 17 + robust: c_int, 18 + ty: c_int, 11 19 } 12 20 21 + // #[no_mangle] 13 22 pub extern "C" fn pthread_mutex_consistent(mutex: *mut pthread_mutex_t) -> c_int { 14 23 todo!(); 15 24 } 16 - pub extern "C" fn pthread_mutex_destroy(mutex: *mut pthread_mutex_t) -> c_int { 17 - todo!(); 25 + #[no_mangle] 26 + pub unsafe extern "C" fn pthread_mutex_destroy(mutex: *mut pthread_mutex_t) -> c_int { 27 + let _mutex: &pthread_mutex_t = &*mutex; 28 + 0 18 29 } 19 30 31 + // #[no_mangle] 20 32 pub extern "C" fn pthread_mutex_getprioceiling(mutex: *const pthread_mutex_t, prioceiling: *mut c_int) -> c_int { 21 33 todo!(); 22 34 } 23 35 24 - pub extern "C" fn pthread_mutex_init(mutex: *mut pthread_mutex_t, attr: *const pthread_mutexattr_t) -> c_int { 25 - todo!(); 36 + #[no_mangle] 37 + pub unsafe extern "C" fn pthread_mutex_init(mutex: *mut pthread_mutex_t, _attr: *const pthread_mutexattr_t) -> c_int { 38 + // TODO: attr 39 + mutex.write(Mutex { 40 + inner: crate::sync::Mutex::new(()), 41 + }); 42 + 0 26 43 } 27 - pub extern "C" fn pthread_mutex_lock(mutex: *mut pthread_mutex_t) -> c_int { 28 - todo!(); 44 + #[no_mangle] 45 + pub unsafe extern "C" fn pthread_mutex_lock(mutex: *mut pthread_mutex_t) -> c_int { 46 + (&*mutex).inner.manual_lock(); 47 + 48 + 0 29 49 } 30 50 51 + // #[no_mangle] 31 52 pub extern "C" fn pthread_mutex_setprioceiling(mutex: *mut pthread_mutex_t, prioceiling: c_int, old_prioceiling: *mut c_int) -> c_int { 32 53 todo!(); 33 54 } 34 55 56 + // #[no_mangle] 35 57 pub extern "C" fn pthread_mutex_timedlock(mutex: *mut pthread_mutex_t, timespec: *const timespec) -> c_int { 36 58 todo!(); 37 59 } 38 - pub extern "C" fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> c_int { 39 - todo!(); 40 - } 41 - pub extern "C" fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> c_int { 42 - todo!(); 60 + #[no_mangle] 61 + pub unsafe extern "C" fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> c_int { 62 + match (&*mutex).inner.manual_try_lock() { 63 + Ok(_) => 0, 64 + Err(_) => EBUSY, 65 + } 43 66 } 44 - pub extern "C" fn pthread_mutexattr_destroy(attr: *mut pthread_mutexattr_t) -> c_int { 45 - todo!(); 67 + #[no_mangle] 68 + pub unsafe extern "C" fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> c_int { 69 + (&*mutex).inner.manual_unlock(); 70 + 0 46 71 } 47 72 48 - pub extern "C" fn pthread_mutexattr_getprioceiling(attr: *const pthread_mutexattr_t, prioceiling: *mut c_int) -> c_int { 49 - todo!(); 73 + #[no_mangle] 74 + pub extern "C" fn pthread_mutexattr_destroy(_attr: *mut pthread_mutexattr_t) -> c_int { 75 + 0 50 76 } 51 77 78 + #[no_mangle] 79 + pub unsafe extern "C" fn pthread_mutexattr_getprioceiling(attr: *const pthread_mutexattr_t, prioceiling: *mut c_int) -> c_int { 80 + prioceiling.write((*attr).prioceiling); 81 + 0 82 + } 52 83 53 - pub extern "C" fn pthread_mutexattr_getprotocol(attr: *const pthread_mutexattr_t, protocol: *mut c_int) -> c_int { 54 - todo!(); 84 + #[no_mangle] 85 + pub unsafe extern "C" fn pthread_mutexattr_getprotocol(attr: *const pthread_mutexattr_t, protocol: *mut c_int) -> c_int { 86 + protocol.write((*attr).protocol); 87 + 0 55 88 } 56 89 57 - pub extern "C" fn pthread_mutexattr_getpshared(attr: *const pthread_mutexattr_t, pshared: *mut c_int) -> c_int { 58 - todo!(); 90 + #[no_mangle] 91 + pub unsafe extern "C" fn pthread_mutexattr_getpshared(attr: *const pthread_mutexattr_t, pshared: *mut c_int) -> c_int { 92 + pshared.write((*attr).pshared); 93 + 0 59 94 } 60 95 61 - pub extern "C" fn pthread_mutexattr_getrobust(attr: *const pthread_mutexattr_t, robust: *mut c_int) -> c_int { 62 - todo!(); 96 + #[no_mangle] 97 + pub unsafe extern "C" fn pthread_mutexattr_getrobust(attr: *const pthread_mutexattr_t, robust: *mut c_int) -> c_int { 98 + robust.write((*attr).robust); 99 + 0 63 100 } 64 - pub extern "C" fn pthread_mutexattr_gettype(attr: *const pthread_mutexattr_t, ty: *mut c_int) -> c_int { 65 - todo!(); 101 + #[no_mangle] 102 + pub unsafe extern "C" fn pthread_mutexattr_gettype(attr: *const pthread_mutexattr_t, ty: *mut c_int) -> c_int { 103 + ty.write((*attr).ty); 104 + 0 66 105 } 67 - pub extern "C" fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> c_int { 68 - todo!(); 106 + #[no_mangle] 107 + pub unsafe extern "C" fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> c_int { 108 + attr.write(MutexAttr { 109 + robust: PTHREAD_MUTEX_STALLED, 110 + pshared: PTHREAD_PROCESS_PRIVATE, 111 + protocol: PTHREAD_PRIO_NONE, 112 + // TODO 113 + prioceiling: 0, 114 + ty: PTHREAD_MUTEX_DEFAULT, 115 + }); 116 + 0 69 117 } 70 118 71 - pub extern "C" fn pthread_mutexattr_setprioceiling(attr: *mut pthread_mutexattr_t, prioceiling: c_int) -> c_int { 72 - todo!(); 119 + #[no_mangle] 120 + pub unsafe extern "C" fn pthread_mutexattr_setprioceiling(attr: *mut pthread_mutexattr_t, prioceiling: c_int) -> c_int { 121 + (*attr).prioceiling = prioceiling; 122 + 0 73 123 } 74 124 75 - pub extern "C" fn pthread_mutexattr_setprotocol(attr: *mut pthread_mutexattr_t, protocol: c_int) -> c_int { 76 - todo!(); 125 + #[no_mangle] 126 + pub unsafe extern "C" fn pthread_mutexattr_setprotocol(attr: *mut pthread_mutexattr_t, protocol: c_int) -> c_int { 127 + (*attr).protocol = protocol; 128 + 0 77 129 } 78 130 79 - pub extern "C" fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, pshared: c_int) -> c_int { 80 - todo!(); 131 + #[no_mangle] 132 + pub unsafe extern "C" fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, pshared: c_int) -> c_int { 133 + (*attr).pshared = pshared; 134 + 0 81 135 } 82 136 83 - pub extern "C" fn pthread_mutexattr_setrobust(attr: *mut pthread_mutexattr_t, robust: c_int) -> c_int { 84 - todo!(); 137 + #[no_mangle] 138 + pub unsafe extern "C" fn pthread_mutexattr_setrobust(attr: *mut pthread_mutexattr_t, robust: c_int) -> c_int { 139 + (*attr).robust = robust; 140 + 0 85 141 } 86 - pub extern "C" fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, ty: c_int) -> c_int { 87 - todo!(); 142 + #[no_mangle] 143 + pub unsafe extern "C" fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, ty: c_int) -> c_int { 144 + (*attr).ty = ty; 145 + 0 88 146 }
+2 -2
src/header/pthread/rwlock.rs
··· 46 46 #[no_mangle] 47 47 pub unsafe extern "C" fn pthread_rwlock_timedrdlock(rwlock: *mut pthread_rwlock_t, timeout: *const timespec) -> c_int { 48 48 let rwlock: &pthread_rwlock_t = &*rwlock; 49 - let timeout = NonNull::new(timeout as *mut _).map(|n| n.as_ref()); 49 + let timeout = timeout.as_ref(); 50 50 51 51 loop { 52 52 if pthread_rwlock_tryrdlock(rwlock as *const _ as *mut _) == EBUSY { ··· 58 58 #[no_mangle] 59 59 pub unsafe extern "C" fn pthread_rwlock_timedwrlock(rwlock: *mut pthread_rwlock_t, timeout: *const timespec) -> c_int { 60 60 let rwlock: &pthread_rwlock_t = &*rwlock; 61 - let timeout = NonNull::new(timeout as *mut _).map(|n| n.as_ref()); 61 + let timeout = timeout.as_ref(); 62 62 63 63 loop { 64 64 if pthread_rwlock_trywrlock(rwlock as *const _ as *mut _) == EBUSY {
+73
src/header/pthread/tls.rs
··· 1 + use super::*; 2 + 3 + // TODO: Hashmap? 4 + use alloc::collections::BTreeMap; 5 + 6 + use core::cell::{Cell, RefCell}; 7 + 8 + use crate::header::errno::EINVAL; 9 + 10 + // TODO: What should this limit be? 11 + pub const PTHREAD_KEYS_MAX: u32 = 4096 * 32; 12 + 13 + #[no_mangle] 14 + pub unsafe extern "C" fn pthread_getspecific(key: pthread_key_t) -> *mut c_void { 15 + let Some(&Record { data, .. }) = DICT.borrow_mut().get(&key) else { 16 + return core::ptr::null_mut(); 17 + }; 18 + 19 + data 20 + } 21 + #[no_mangle] 22 + pub unsafe extern "C" fn pthread_key_create(key_ptr: *mut pthread_key_t, destructor: extern "C" fn(value: *mut c_void)) -> c_int { 23 + let key = NEXTKEY.get(); 24 + NEXTKEY.set(key + 1); 25 + 26 + // TODO 27 + //if key >= PTHREAD_KEYS_MAX { 28 + //} 29 + 30 + DICT.borrow_mut().insert(key, Record { 31 + data: core::ptr::null_mut(), 32 + destructor, 33 + }); 34 + 35 + key_ptr.write(key); 36 + 37 + 0 38 + } 39 + 40 + #[no_mangle] 41 + pub unsafe extern "C" fn pthread_key_delete(key: pthread_key_t) -> c_int { 42 + if DICT.borrow_mut().remove(&key).is_none() { 43 + // We don't have to return anything, but it's not less expensive to ignore it. 44 + return EINVAL; 45 + } 46 + 47 + 0 48 + } 49 + 50 + #[no_mangle] 51 + pub unsafe extern "C" fn pthread_setspecific(key: pthread_key_t, value: *const c_void) -> c_int { 52 + let mut guard = DICT.borrow_mut(); 53 + 54 + let Some(Record { data, .. }) = guard.get_mut(&key) else { 55 + // We don't have to return anything, but it's not less expensive to ignore it. 56 + return EINVAL; 57 + }; 58 + 59 + *data = value as *mut c_void; 60 + 61 + 0 62 + } 63 + 64 + #[thread_local] 65 + static DICT: RefCell<BTreeMap<u32, Record>> = RefCell::new(BTreeMap::new()); 66 + 67 + struct Record { 68 + data: *mut c_void, 69 + destructor: extern "C" fn(value: *mut c_void), 70 + } 71 + 72 + #[thread_local] 73 + static NEXTKEY: Cell<u32> = Cell::new(1);
+2 -2
src/platform/linux/mod.rs
··· 219 219 e(unsafe { syscall!(FTRUNCATE, fildes, length) }) as c_int 220 220 } 221 221 222 - fn futex(addr: *mut c_int, op: c_int, val: c_int, val2: usize) -> c_int { 223 - unsafe { syscall!(FUTEX, addr, op, val, val2, 0, 0) as c_int } 222 + fn futex(addr: *mut c_int, op: c_int, val: c_int, val2: usize) -> Result<c_long, crate::pthread::Errno> { 223 + 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)) 224 224 } 225 225 226 226 fn futimens(fd: c_int, times: *const timespec) -> c_int {
+1 -1
src/platform/pal/mod.rs
··· 73 73 74 74 fn ftruncate(fildes: c_int, length: off_t) -> c_int; 75 75 76 - fn futex(addr: *mut c_int, op: c_int, val: c_int, val2: usize) -> c_int; 76 + fn futex(addr: *mut c_int, op: c_int, val: c_int, val2: usize) -> Result<c_long, crate::pthread::Errno>; 77 77 78 78 fn futimens(fd: c_int, times: *const timespec) -> c_int; 79 79
-65
src/platform/pte.rs
··· 51 51 52 52 static NEXT_KEY: AtomicU32 = AtomicU32::new(0); 53 53 54 - unsafe fn locals<'a>() -> &'a mut BTreeMap<c_uint, *mut c_void> { 55 - &mut *LOCALS.get() 56 - } 57 - 58 54 #[no_mangle] 59 55 pub unsafe extern "C" fn pte_osThreadStart(handle: pte_osThreadHandle) -> pte_osResult { 60 56 let mut ret = PTE_OS_GENERAL_FAILURE; ··· 250 246 Err(()) => PTE_OS_TIMEOUT, 251 247 } 252 248 } 253 - 254 - #[no_mangle] 255 - pub unsafe extern "C" fn pte_osSemaphoreCancellablePend( 256 - handle: pte_osSemaphoreHandle, 257 - pTimeout: *mut c_uint, 258 - ) -> pte_osResult { 259 - //TODO: thread cancel 260 - pte_osSemaphorePend(handle, pTimeout) 261 - } 262 - 263 - #[no_mangle] 264 - pub unsafe extern "C" fn pte_osAtomicExchange(ptarg: *mut c_int, val: c_int) -> c_int { 265 - intrinsics::atomic_xchg_seqcst(ptarg, val) 266 - } 267 - 268 - #[no_mangle] 269 - pub unsafe extern "C" fn pte_osAtomicCompareExchange( 270 - pdest: *mut c_int, 271 - exchange: c_int, 272 - comp: c_int, 273 - ) -> c_int { 274 - intrinsics::atomic_cxchg_seqcst_seqcst(pdest, comp, exchange).0 275 - } 276 - 277 - #[no_mangle] 278 - pub unsafe extern "C" fn pte_osAtomicExchangeAdd(pAppend: *mut c_int, value: c_int) -> c_int { 279 - intrinsics::atomic_xadd_seqcst(pAppend, value) 280 - } 281 - 282 - #[no_mangle] 283 - pub unsafe extern "C" fn pte_osAtomicDecrement(pdest: *mut c_int) -> c_int { 284 - intrinsics::atomic_xadd_seqcst(pdest, -1) - 1 285 - } 286 - 287 - #[no_mangle] 288 - pub unsafe extern "C" fn pte_osAtomicIncrement(pdest: *mut c_int) -> c_int { 289 - intrinsics::atomic_xadd_seqcst(pdest, 1) + 1 290 - } 291 - 292 - #[no_mangle] 293 - pub unsafe extern "C" fn pte_osTlsSetValue(index: c_uint, value: *mut c_void) -> pte_osResult { 294 - locals().insert(index, value); 295 - PTE_OS_OK 296 - } 297 - 298 - #[no_mangle] 299 - pub unsafe extern "C" fn pte_osTlsGetValue(index: c_uint) -> *mut c_void { 300 - locals().get_mut(&index).copied().unwrap_or(ptr::null_mut()) 301 - } 302 - 303 - #[no_mangle] 304 - pub unsafe extern "C" fn pte_osTlsAlloc(pKey: *mut c_uint) -> pte_osResult { 305 - *pKey = NEXT_KEY.fetch_add(1, Ordering::Relaxed); 306 - PTE_OS_OK 307 - } 308 - 309 - #[no_mangle] 310 - pub unsafe extern "C" fn pte_osTlsFree(index: c_uint) -> pte_osResult { 311 - // XXX free keys 312 - PTE_OS_OK 313 - }
+3 -3
src/platform/redox/mod.rs
··· 333 333 e(syscall::ftruncate(fd as usize, len as usize)) as c_int 334 334 } 335 335 336 - fn futex(addr: *mut c_int, op: c_int, val: c_int, val2: usize) -> c_int { 336 + fn futex(addr: *mut c_int, op: c_int, val: c_int, val2: usize) -> Result<c_long, crate::pthread::Errno> { 337 337 match unsafe { 338 338 syscall::futex( 339 339 addr as *mut i32, ··· 343 343 ptr::null_mut(), 344 344 ) 345 345 } { 346 - Ok(success) => success as c_int, 347 - Err(err) => -(err.errno as c_int), 346 + Ok(success) => Ok(success as c_long), 347 + Err(err) => Err(crate::pthread::Errno(err.errno)), 348 348 } 349 349 } 350 350
+1 -1
src/platform/types.rs
··· 82 82 pub type pthread_barrierattr_t = crate::header::pthread::barrier::BarrierAttr; 83 83 pub type pthread_cond_t = crate::header::pthread::cond::Cond; 84 84 pub type pthread_condattr_t = crate::header::pthread::cond::CondAttr; 85 - pub type pthread_key_t = *mut c_void; 85 + pub type pthread_key_t = u32; 86 86 pub type pthread_mutex_t = crate::header::pthread::mutex::Mutex; 87 87 pub type pthread_mutexattr_t = crate::header::pthread::mutex::MutexAttr; 88 88 pub type pthread_once_t = crate::header::pthread::once::Once;
+4 -2
src/pthread/mod.rs
··· 48 48 use crate::header::pthread::attr::Attr; 49 49 50 50 /// Positive error codes (EINVAL, not -EINVAL). 51 - #[derive(Debug)] 51 + #[derive(Debug, Eq, PartialEq)] 52 + // TODO: Move to a more generic place. 52 53 pub struct Errno(pub c_int); 53 54 54 55 #[derive(Clone, Copy)] ··· 134 135 return Err(Errno(EAGAIN)); 135 136 }; 136 137 137 - let _ = (&mut *synchronization_mutex).lock(); 138 + let _ = (&*synchronization_mutex).lock(); 139 + 138 140 OS_TID_TO_PTHREAD.lock().insert(os_tid, ForceSendSync(ptr.cast())); 139 141 140 142 core::mem::forget(stack_raii);
+21 -18
src/sync/mod.rs
··· 28 28 Other, 29 29 } 30 30 31 + pub unsafe fn futex_wake_ptr(ptr: *mut i32, n: i32) -> usize { 32 + // TODO: unwrap_unchecked? 33 + Sys::futex(ptr, FUTEX_WAKE, n, 0).unwrap() as usize 34 + } 35 + pub unsafe fn futex_wait_ptr(ptr: *mut i32, value: i32, timeout_opt: Option<&timespec>) -> bool { 36 + // TODO: unwrap_unchecked? 37 + Sys::futex(ptr, FUTEX_WAIT, value, timeout_opt.map_or(0, |t| t as *const _ as usize)) == Ok(0) 38 + } 39 + pub fn futex_wake(atomic: &AtomicInt, n: i32) -> usize { 40 + unsafe { futex_wake_ptr(atomic.as_mut_ptr(), n) } 41 + } 42 + pub fn futex_wait(atomic: &AtomicInt, value: i32, timeout_opt: Option<&timespec>) -> bool { 43 + unsafe { futex_wait_ptr(atomic.as_mut_ptr(), value, timeout_opt) } 44 + } 45 + 31 46 /// Convenient wrapper around the "futex" system call for 32 47 /// synchronization implementations 33 48 #[repr(C)] ··· 41 56 } 42 57 } 43 58 pub fn notify_one(&self) { 44 - Sys::futex( 45 - self.atomic.as_mut_ptr(), 46 - FUTEX_WAKE, 47 - 1, 48 - 0, 49 - ); 59 + futex_wake(&self.atomic, 1); 50 60 } 51 61 pub fn notify_all(&self) { 52 - Sys::futex( 53 - self.atomic.as_mut_ptr(), 54 - FUTEX_WAKE, 55 - c_int::max_value(), 56 - 0, 57 - ); 62 + futex_wake(&self.atomic, i32::MAX); 58 63 } 59 64 pub fn wait_if(&self, value: c_int, timeout_opt: Option<&timespec>) { 60 - Sys::futex( 61 - self.atomic.as_mut_ptr(), 62 - FUTEX_WAIT, 63 - value, 64 - timeout_opt.map_or(0, |timeout| timeout as *const timespec as usize), 65 - ); 65 + self.wait_if_raw(value, timeout_opt); 66 + } 67 + pub fn wait_if_raw(&self, value: c_int, timeout_opt: Option<&timespec>) -> bool { 68 + futex_wait(&self.atomic, value, timeout_opt) 66 69 } 67 70 68 71 /// A general way to efficiently wait for what might be a long time, using two closures:
+1 -1
src/sync/mutex.rs
··· 11 11 const WAITING: c_int = 2; 12 12 13 13 pub struct Mutex<T> { 14 - lock: AtomicLock, 14 + pub(crate) lock: AtomicLock, 15 15 content: UnsafeCell<T>, 16 16 } 17 17 unsafe impl<T: Send> Send for Mutex<T> {}