diff --git a/src/header/bits_key-t/cbindgen.toml b/src/header/bits_key-t/cbindgen.toml index 113e852959..3307c870b6 100644 --- a/src/header/bits_key-t/cbindgen.toml +++ b/src/header/bits_key-t/cbindgen.toml @@ -4,6 +4,7 @@ # # POSIX headers that require key_t: # - sys/ipc.h +# - sys/shm.h # - sys/types (where it should be defined) include_guard = "_RELIBC_BITS_KEY_T_H" language = "C" diff --git a/src/header/bits_mode-t/cbindgen.toml b/src/header/bits_mode-t/cbindgen.toml index aa7e4194c3..9c560cbd8f 100644 --- a/src/header/bits_mode-t/cbindgen.toml +++ b/src/header/bits_mode-t/cbindgen.toml @@ -5,7 +5,7 @@ # POSIX headers that require mode_t: # - fcntl.h # - ndbm.h (TODO not present in relibc) -# - spawn.h (TODO not present in relibc) +# - spawn.h # - sys/ipc.h # - sys/mman.h # - sys/stat.h diff --git a/src/header/fcntl/mod.rs b/src/header/fcntl/mod.rs index 387bd71b06..4abdb6baf0 100644 --- a/src/header/fcntl/mod.rs +++ b/src/header/fcntl/mod.rs @@ -96,7 +96,7 @@ pub struct flock { /// - `F_GETFD`: Value of flags. The return value shall not be negative. /// - `F_SETFD`: Value other than `-1`. /// - `F_GETFL`: Value of file status flags and access modes. The return value -/// shall not be negative. +/// shall not be negative. /// - `F_SETFL`: Value other than `-1`. /// - `F_GETLK`: Value other than `-1`. /// - `F_SETLK`: Value other than `-1`. @@ -105,7 +105,7 @@ pub struct flock { /// - `F_OFD_SETLK`: Value other than `-1`. /// - `F_OFD_SETLKW`: Value other than `-1`. /// - `F_GETOWN`: Value of the socket owner process or process group; this -/// shall not be `-1`. +/// shall not be `-1`. /// - `F_SETOWN`: Value other than `-1`. /// - `F_GETOWN_EX`: Value other than `-1`. /// - `F_SETOWN_EX`: Value other than `-1`. diff --git a/src/header/pthread/mod.rs b/src/header/pthread/mod.rs index eba7e347f2..7cd55d6fd9 100644 --- a/src/header/pthread/mod.rs +++ b/src/header/pthread/mod.rs @@ -14,7 +14,7 @@ use crate::{ c_int, c_uchar, c_uint, c_void, clockid_t, pthread_attr_t, pthread_barrier_t, pthread_barrierattr_t, pthread_cond_t, pthread_condattr_t, pthread_key_t, pthread_mutex_t, pthread_mutexattr_t, pthread_once_t, pthread_rwlock_t, - pthread_rwlockattr_t, pthread_spinlock_t, pthread_t, size_t, + pthread_rwlockattr_t, pthread_t, size_t, }, }, pthread, diff --git a/src/header/pthread/spin.rs b/src/header/pthread/spin.rs index 6000d6093f..6f8572841b 100644 --- a/src/header/pthread/spin.rs +++ b/src/header/pthread/spin.rs @@ -1,31 +1,62 @@ use core::sync::atomic::{AtomicI32 as AtomicInt, Ordering}; -use crate::header::errno::EBUSY; - -use super::*; +use crate::{ + header::errno::EBUSY, + platform::types::{c_int, pthread_spinlock_t}, +}; +/// The spin lock is in an unlocked state. const UNLOCKED: c_int = 0; +/// The spin lock is in a locked state. const LOCKED: c_int = 1; /// See . +/// +/// Destroys the spin lock referenced by `lock` and releases any resources used +/// by the lock. +/// +/// Upon success, returns `0`. Upon failure, an error number is returned. +/// +/// # Implementation +/// Cannot fail on the Rust side so no error number is ever returned. +/// +/// # Safety +/// It is undefined behaviour for any of the following: +/// - Subsequent use of `lock` after calling this function unless it is +/// reinitialized with `pthread_spin_init()`. +/// - This function is called when a thread holds the lock. +/// - `lock` is uninitialized when this function is called. #[unsafe(no_mangle)] -pub unsafe extern "C" fn pthread_spin_destroy(spinlock: *mut pthread_spinlock_t) -> c_int { - let _spinlock = unsafe { &mut *spinlock.cast::() }; +pub unsafe extern "C" fn pthread_spin_destroy(lock: *mut pthread_spinlock_t) -> c_int { + let _spinlock = unsafe { &mut *lock.cast::() }; // No-op 0 } /// See . +/// +/// Allocates any resources required to use the spin lock referenced to by +/// `lock` and initializes the lock to an unlocked state. +/// +/// Upon success, returns `0`. Upon failure, an error number is returned. +/// +/// # Implementation +/// Cannot fail on the Rust side so no error number is ever returned. +/// +/// # Safety +/// It is undefined behaviour for any of the following: +/// - `lock` has already been initialized. +/// - `lock` has been used before being initialized by this function. #[unsafe(no_mangle)] pub unsafe extern "C" fn pthread_spin_init( - spinlock: *mut pthread_spinlock_t, + lock: *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... unsafe { - spinlock.cast::().write(RlctSpinlock { + lock.cast::().write(RlctSpinlock { inner: AtomicInt::new(UNLOCKED), }) }; @@ -33,9 +64,18 @@ pub unsafe extern "C" fn pthread_spin_init( 0 } /// See . +/// +/// Locks the spin lock referenced by `lock`. +/// +/// Upon success, returns `0`. Upon failure, an error number is returned. +/// +/// # Safety +/// It is undefined behaviour for any of the following: +/// - `lock` is uninitialized. +/// - The calling thread holds `lock` at the time the call is made. #[unsafe(no_mangle)] -pub unsafe extern "C" fn pthread_spin_lock(spinlock: *mut pthread_spinlock_t) -> c_int { - let spinlock = unsafe { &*spinlock.cast::() }; +pub unsafe extern "C" fn pthread_spin_lock(lock: *mut pthread_spinlock_t) -> c_int { + let spinlock = unsafe { &*lock.cast::() }; loop { match spinlock.inner.compare_exchange_weak( @@ -52,9 +92,16 @@ pub unsafe extern "C" fn pthread_spin_lock(spinlock: *mut pthread_spinlock_t) -> 0 } /// See . +/// +/// Locks the spin lock referenced by `lock` if it is not held by any thread. +/// +/// Upon success, returns `0`. Upon failure, an error number is returned. +/// +/// # Safety +/// It is undefined behaviour if `lock` is uninitialized. #[unsafe(no_mangle)] -pub unsafe extern "C" fn pthread_spin_trylock(spinlock: *mut pthread_spinlock_t) -> c_int { - let spinlock = unsafe { &*spinlock.cast::() }; +pub unsafe extern "C" fn pthread_spin_trylock(lock: *mut pthread_spinlock_t) -> c_int { + let spinlock = unsafe { &*lock.cast::() }; match spinlock .inner @@ -67,14 +114,28 @@ pub unsafe extern "C" fn pthread_spin_trylock(spinlock: *mut pthread_spinlock_t) 0 } /// See . +/// +/// Releases the spin lock referenced by `lock` which was locked via the +/// `pthread_spin_lock()` or `pthread_spin_trylock()` functions. +/// +/// Upon success, returns `0`. Upon failure, an error number is returned. +/// +/// # Implementation +/// Cannot fail on the Rust side so no error number is ever returned. +/// +/// # Safety +/// It is undefined behaviour for any of the following: +/// - `lock` is uninitialized. +/// - `lock` is not held by the calling thread. #[unsafe(no_mangle)] -pub unsafe extern "C" fn pthread_spin_unlock(spinlock: *mut pthread_spinlock_t) -> c_int { - let spinlock = unsafe { &*spinlock.cast::() }; +pub unsafe extern "C" fn pthread_spin_unlock(lock: *mut pthread_spinlock_t) -> c_int { + let spinlock = unsafe { &*lock.cast::() }; spinlock.inner.store(UNLOCKED, Ordering::Release); 0 } + pub(crate) struct RlctSpinlock { pub inner: AtomicInt, }