Merge branch 'pthread-spin-doc' into 'master'

add descriptions to pthread spin lock functions

See merge request redox-os/relibc!1502
This commit is contained in:
Mathew John Roberts
2026-06-30 07:26:36 +01:00
5 changed files with 79 additions and 17 deletions
+1
View File
@@ -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"
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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`.
+1 -1
View File
@@ -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,
+74 -13
View File
@@ -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 <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_spin_destroy.html>.
///
/// 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::<RlctSpinlock>() };
pub unsafe extern "C" fn pthread_spin_destroy(lock: *mut pthread_spinlock_t) -> c_int {
let _spinlock = unsafe { &mut *lock.cast::<RlctSpinlock>() };
// No-op
0
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_spin_init.html>.
///
/// 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::<RlctSpinlock>().write(RlctSpinlock {
lock.cast::<RlctSpinlock>().write(RlctSpinlock {
inner: AtomicInt::new(UNLOCKED),
})
};
@@ -33,9 +64,18 @@ pub unsafe extern "C" fn pthread_spin_init(
0
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_spin_lock.html>.
///
/// 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::<RlctSpinlock>() };
pub unsafe extern "C" fn pthread_spin_lock(lock: *mut pthread_spinlock_t) -> c_int {
let spinlock = unsafe { &*lock.cast::<RlctSpinlock>() };
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 <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_spin_trylock.html>.
///
/// 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::<RlctSpinlock>() };
pub unsafe extern "C" fn pthread_spin_trylock(lock: *mut pthread_spinlock_t) -> c_int {
let spinlock = unsafe { &*lock.cast::<RlctSpinlock>() };
match spinlock
.inner
@@ -67,14 +114,28 @@ pub unsafe extern "C" fn pthread_spin_trylock(spinlock: *mut pthread_spinlock_t)
0
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_spin_unlock.html>.
///
/// 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::<RlctSpinlock>() };
pub unsafe extern "C" fn pthread_spin_unlock(lock: *mut pthread_spinlock_t) -> c_int {
let spinlock = unsafe { &*lock.cast::<RlctSpinlock>() };
spinlock.inner.store(UNLOCKED, Ordering::Release);
0
}
pub(crate) struct RlctSpinlock {
pub inner: AtomicInt,
}