Merge branch 'pthread-attr-docs' into 'master'

document pthread attr functions

See merge request redox-os/relibc!1509
This commit is contained in:
Jeremy Soller
2026-07-02 08:30:00 -06:00
2 changed files with 303 additions and 45 deletions
+291 -37
View File
@@ -1,9 +1,19 @@
use core::{ptr, sync::atomic::Ordering};
use super::*;
use crate::{
header::bits_pthread::{pthread_attr_t, pthread_t},
header::{
bits_pthread::{pthread_attr_t, pthread_t},
limits::PTHREAD_STACK_MIN,
pthread::{
PTHREAD_CREATE_DETACHED, PTHREAD_CREATE_JOINABLE, PTHREAD_EXPLICIT_SCHED,
PTHREAD_INHERIT_SCHED, PTHREAD_SCOPE_PROCESS, PTHREAD_SCOPE_SYSTEM, RlctAttr,
},
sched::{SCHED_FIFO, SCHED_OTHER, SCHED_RR, sched_param},
},
platform::{
Pal, Sys,
types::{c_int, c_long, c_void, size_t},
},
pthread::{Pthread, PthreadFlags},
};
@@ -35,6 +45,19 @@ impl Default for RlctAttr {
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_attr_destroy.html>.
///
/// Destroys a thread attributes object.
///
/// Upon success, returns `0`. Upon failure, returns an error number to
/// indicate the error.
///
/// # Implementation
/// Always succeeds, so will never return an error number.
///
/// # Safety
/// It is undefined behaviour for the following:
/// - `attr` is not already initialized when calling this function
/// - `attr` is used after calling this function without reinitializing
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_attr_destroy(attr: *mut pthread_attr_t) -> c_int {
unsafe { ptr::drop_in_place(attr) };
@@ -42,6 +65,17 @@ pub unsafe extern "C" fn pthread_attr_destroy(attr: *mut pthread_attr_t) -> c_in
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_attr_getdetachstate.html>.
///
/// Gets the destachstate attribute in the `attr` object.
///
/// Upon success, returns `0` and stores the detachstate attribute in
/// `detachstate`. Upon failure, returns an error number to indicate the error.
///
/// # Implementation
/// Always succeeds, so will never return an error number.
///
/// # Safety
/// It is undefined behaviour if `attr` is not initialized.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_attr_getdetachstate(
attr: *const pthread_attr_t,
@@ -52,16 +86,40 @@ pub unsafe extern "C" fn pthread_attr_getdetachstate(
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_attr_getguardsize.html>.
///
/// Gets the guardsize attribute in the `attr` object.
///
/// Upon success, returns `0` and stores the guardsize attribute in the
/// `guardsize` parameter. Upon failure, an error number is returned to
/// indicate the error.
///
/// # Implementation
/// Always succeeds, so will never return an error number.
///
/// # Safety
/// It is undefined behaviour if `attr` is not initialized.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_attr_getguardsize(
attr: *const pthread_attr_t,
size: *mut size_t,
guardsize: *mut size_t,
) -> c_int {
unsafe { ptr::write(size, (*attr.cast::<RlctAttr>()).guardsize) };
unsafe { ptr::write(guardsize, (*attr.cast::<RlctAttr>()).guardsize) };
0
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_attr_getinheritsched.html>.
///
/// Gets the inheritsched attribute in the `attr` object.
///
/// Upon success, returns `0` and stores the inheritsched attribute in the
/// `inheritsched` parameter. Upon failure, an error number is returned to
/// indicate the error.
///
/// # Implementation
/// Always succeeds, so will never return an error number.
///
/// # Safety
/// It is undefined behaviour if `attr` is not initialized.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_attr_getinheritsched(
attr: *const pthread_attr_t,
@@ -72,6 +130,18 @@ pub unsafe extern "C" fn pthread_attr_getinheritsched(
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_attr_getschedparam.html>.
///
/// Gets the scheduling parameter attributes in the `attr` object.
///
/// Upon success, returns `0` and stores the scheduling parameter attributes
/// in the `param` parameter. Upon failure, an error number is returned to
/// indicate the error.
///
/// # Implementation
/// Always succeeds, so will never return an error number.
///
/// # Safety
/// It is undefined behaviour if `attr` is not initialized.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_attr_getschedparam(
attr: *const pthread_attr_t,
@@ -82,6 +152,18 @@ pub unsafe extern "C" fn pthread_attr_getschedparam(
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_attr_getschedpolicy.html>.
///
/// Gets the schedpolicy attribute in the `attr` object.
///
/// Upon success, returns `0` and stores the schedpolicy attributes in the
/// `policy` parameter. Upon failure, an error number is returned to indicate
/// the error.
///
/// # Implementation
/// Always succeeds, so will never return an error number.
///
/// # Safety
/// It is undefined behaviour if `attr` is not initialized.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_attr_getschedpolicy(
attr: *const pthread_attr_t,
@@ -92,16 +174,41 @@ pub unsafe extern "C" fn pthread_attr_getschedpolicy(
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_attr_getscope.html>.
///
/// Gets the contentionscope attribute in the `attr` object.
///
/// Upon success, returns `0` and stores the contentionscope attribute in the
/// `contentionscope` parameter. Upon failure, an error number is returned to
/// indicate the error.
///
/// # Implementation
/// Always succeeds, so will never return an error number.
///
/// # Safety
/// It is undefined behaviour if `attr` is not initialized.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_attr_getscope(
attr: *const pthread_attr_t,
scope: *mut c_int,
contentionscope: *mut c_int,
) -> c_int {
unsafe { ptr::write(scope, (*attr.cast::<RlctAttr>()).scope.into()) };
unsafe { ptr::write(contentionscope, (*attr.cast::<RlctAttr>()).scope.into()) };
0
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_attr_getstack.html>.
///
/// Gets the thread creation stack attributes stackaddr and stacksize in the
/// `attr` object.
///
/// Upon success, returns `0` and stores the stackaddr attribute in the
/// `stackaddr` parameter and the stacksize attribute in the `stacksize`
/// parameter. Upon failure, an error number is returned to indicate the error.
///
/// # Implementation
/// Always succeeds, so will never return an error number.
///
/// # Safety
/// It is undefined behaviour if `attr` is not initialized.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_attr_getstack(
attr: *const pthread_attr_t,
@@ -109,21 +216,42 @@ pub unsafe extern "C" fn pthread_attr_getstack(
stacksize: *mut size_t,
) -> c_int {
unsafe { ptr::write(stackaddr, (*attr.cast::<RlctAttr>()).stack as _) };
unsafe { ptr::write(stacksize, (*attr.cast::<RlctAttr>()).stacksize as _) };
unsafe { ptr::write(stacksize, (*attr.cast::<RlctAttr>()).stacksize) };
0
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_attr_getstacksize.html>.
///
/// Gets the thread creation stacksize attribute in the `attr` object.
///
/// Upon success, returns `0` and stores the stacksize attribute in the
/// `stacksize` parameter. Upon failure, an error number is returned to
/// indicate the error.
///
/// # Implementation
/// Always succeeds, so will never return an error number.
///
/// # Safety
/// It is undefined behaviour if `attr` is not initialized.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_attr_getstacksize(
attr: *const pthread_attr_t,
stacksize: *mut size_t,
) -> c_int {
unsafe { ptr::write(stacksize, (*attr.cast::<RlctAttr>()).stacksize as _) };
unsafe { ptr::write(stacksize, (*attr.cast::<RlctAttr>()).stacksize) };
0
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_attr_init.html>.
///
/// Initializes a thread attributes object `attr` with the default value for
/// all of the individual attributes used by a given implementation.
///
/// Upon success, returns `0`. Upon failure, returns an error number to
/// indicate the error.
///
/// # Implementation
/// Always succeeds, so will never return an error number.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int {
unsafe { ptr::write(attr.cast::<RlctAttr>(), RlctAttr::default()) };
@@ -131,18 +259,46 @@ pub unsafe extern "C" fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int {
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_attr_setdetachstate.html>.
///
/// Sets the detachstate attribute in the `attr` object.
///
/// Upon success, returns `0`. Upon failure, returns an error number to
/// indicate the error.
///
/// # Safety
/// It is undefined behaviour if `attr` is not initialized.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_attr_setdetachstate(
attr: *mut pthread_attr_t,
detachstate: c_int,
) -> c_int {
unsafe {
(*attr.cast::<RlctAttr>()).detachstate = detachstate as _;
match detachstate {
PTHREAD_CREATE_DETACHED | PTHREAD_CREATE_JOINABLE => {
// infallible, value of constants fit into `c_uchar`
if let Ok(ds) = detachstate.try_into() {
// SAFTEY: guaranteed to fit
unsafe {
(*attr.cast::<RlctAttr>()).detachstate = ds;
}
}
0
}
_ => crate::header::errno::EINVAL,
}
0
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_attr_setguardsize.html>.
///
/// Sets the guardsize attribute in the `attr` object.
///
/// Upon success, returns `0`. Upon failure, returns an error number to
/// indicate the error.
///
/// # Implementation
/// Always succeeds, so will never return an error number.
///
/// # Safety
/// It is undefined behaviour if `attr` is not initialized.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_attr_setguardsize(
attr: *mut pthread_attr_t,
@@ -155,18 +311,46 @@ pub unsafe extern "C" fn pthread_attr_setguardsize(
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_attr_setinheritsched.html>.
///
/// Sets the inheritsched attribute in the `attr` object.
///
/// Upon success, returns `0`. Upon failure, returns an error number to
/// indicate the error.
///
/// # Safety
/// It is undefined behaviour if `attr` is not initialized.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_attr_setinheritsched(
attr: *mut pthread_attr_t,
inheritsched: c_int,
) -> c_int {
unsafe {
(*attr.cast::<RlctAttr>()).inheritsched = inheritsched as _;
match inheritsched {
PTHREAD_INHERIT_SCHED | PTHREAD_EXPLICIT_SCHED => {
// infallible, value of constants fit into `c_uchar`
if let Ok(insch) = inheritsched.try_into() {
// SAFTEY: guaranteed to fit
unsafe {
(*attr.cast::<RlctAttr>()).inheritsched = insch;
}
}
0
}
_ => crate::header::errno::ENOTSUP,
}
0
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_attr_setschedparam.html>.
///
/// Sets the scheduling parameter attributes in the `attr` object.
///
/// Upon success, returns `0`. Upon failure, returns an error number to
/// indicate the error.
///
/// # Implementation
/// Always succeeds, so will never return an error number.
///
/// # Safety
/// It is undefined behaviour if `attr` is not initialized.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_attr_setschedparam(
attr: *mut pthread_attr_t,
@@ -179,61 +363,131 @@ pub unsafe extern "C" fn pthread_attr_setschedparam(
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_attr_setschedpolicy.html>.
///
/// Sets the schedpolicy attribute in the `attr` object.
///
/// Upon success, returns `0`. Upon failure, returns an error number to
/// indicate the error.
///
/// # Safety
/// It is undefined behaviour if `attr` is not initialized.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_attr_setschedpolicy(
attr: *mut pthread_attr_t,
policy: c_int,
) -> c_int {
unsafe {
(*attr.cast::<RlctAttr>()).schedpolicy = policy as u8;
match policy {
SCHED_FIFO | SCHED_OTHER | SCHED_RR => {
// infallible, value of constants fit into `c_uchar`
if let Ok(pol) = policy.try_into() {
// SAFTEY: guaranteed to fit
unsafe {
(*attr.cast::<RlctAttr>()).schedpolicy = pol;
}
}
0
}
_ => crate::header::errno::ENOTSUP,
}
0
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_attr_setscope.html>.
///
/// Sets the contentionscope attribute in the `attr` object.
///
/// Upon success, returns `0`. Upon failure, returns an error number to
/// indicate the error.
///
/// # Safety
/// It is undefined behaviour if `attr` is not initialized.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_attr_setscope(attr: *mut pthread_attr_t, scope: c_int) -> c_int {
unsafe {
(*attr.cast::<RlctAttr>()).scope = scope as u8;
pub unsafe extern "C" fn pthread_attr_setscope(
attr: *mut pthread_attr_t,
contentionscope: c_int,
) -> c_int {
match contentionscope {
PTHREAD_SCOPE_SYSTEM | PTHREAD_SCOPE_PROCESS => {
// infallible, value of constants fit into `c_uchar`
if let Ok(ctnscope) = contentionscope.try_into() {
// SAFTEY: guaranteed to fit
unsafe {
(*attr.cast::<RlctAttr>()).scope = ctnscope;
}
}
0
}
_ => crate::header::errno::ENOTSUP,
}
0
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_attr_setstack.html>.
///
/// Sets the thread creation stack attributes stackaddr and stacksize in the
/// `attr` object.
///
/// Upon success, returns `0`. Upon failure, returns an error number to
/// indicate the error.
///
/// # Safety
/// It is undefined behaviour if `attr` is not initialized.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_attr_setstack(
attr: *mut pthread_attr_t,
stackaddr: *mut c_void,
stacksize: size_t,
) -> c_int {
unsafe {
(*attr.cast::<RlctAttr>()).stack = stackaddr as usize;
if stacksize as c_long >= PTHREAD_STACK_MIN {
unsafe {
(*attr.cast::<RlctAttr>()).stack = stackaddr as usize;
}
unsafe {
(*attr.cast::<RlctAttr>()).stacksize = stacksize;
}
0
} else {
crate::header::errno::EINVAL
}
unsafe {
(*attr.cast::<RlctAttr>()).stacksize = stacksize;
}
0
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_attr_setstacksize.html>.
///
/// Sets the thread creation stacksize attribute in the `attr` object.
///
/// Upon success, returns `0`. Upon failure, returns an error number to
/// indicate the error.
///
/// # Safety
/// It is undefined behaviour if `attr` is not initialized.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_attr_setstacksize(
attr: *mut pthread_attr_t,
stacksize: size_t,
) -> c_int {
unsafe {
(*attr.cast::<RlctAttr>()).stacksize = stacksize;
if stacksize as c_long >= PTHREAD_STACK_MIN {
unsafe {
(*attr.cast::<RlctAttr>()).stacksize = stacksize;
}
0
} else {
crate::header::errno::EINVAL
}
0
}
// TODO should be guarded by _GNU_SOURCE
/// Non-POSIX, see <https://www.man7.org/linux/man-pages/man3/pthread_getattr_np.3.html>.
///
/// Initializes the thread attributes object referenced to by `attr` so that it
/// contains actual attribute values describing the running thread `thread`.
///
/// Upon success, returns `0`. Upon failure, returns an error number to
/// indicate the error.
///
/// # Implementation
/// Always succeeds, so will never return an error number.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pthread_getattr_np(
thread_ptr: pthread_t,
attr_ptr: *mut pthread_attr_t,
) -> c_int {
let thread = unsafe { &*thread_ptr.cast::<Pthread>() };
let attr_ptr = attr_ptr.cast::<RlctAttr>();
pub unsafe extern "C" fn pthread_getattr_np(thread: pthread_t, attr: *mut pthread_attr_t) -> c_int {
let thread = unsafe { &*thread.cast::<Pthread>() };
let attr_ptr = attr.cast::<RlctAttr>();
unsafe { ptr::write(attr_ptr, RlctAttr::default()) };
let attr = unsafe { &mut *attr_ptr };
if thread.flags.load(Ordering::Acquire) & PthreadFlags::DETACHED.bits() != 0 {
+12 -8
View File
@@ -8,14 +8,11 @@ use core::{cell::Cell, ptr::NonNull};
use crate::{
error::Errno,
header::{sched::*, time::timespec},
platform::{
Pal, Sys,
types::{
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_t, size_t,
},
platform::types::{
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_t,
size_t,
},
pthread,
};
@@ -54,7 +51,12 @@ pub const PTHREAD_CANCELED: *mut c_void = (!0_usize) as *mut c_void;
pub const PTHREAD_CREATE_DETACHED: c_int = 0;
pub const PTHREAD_CREATE_JOINABLE: c_int = 1;
/// Specifies that the thread scheduling attributes shall be set to the
/// corresponding values from this attributes object.
pub const PTHREAD_EXPLICIT_SCHED: c_int = 0;
/// Specifies that the thread scheduling attributes shall be inherited from the
/// creating thread, and the scheduling attributes in the `attr` argument shall
/// be ignored.
pub const PTHREAD_INHERIT_SCHED: c_int = 1;
pub const PTHREAD_MUTEX_DEFAULT: c_int = 0;
@@ -74,7 +76,9 @@ pub const PTHREAD_PRIO_PROTECT: c_int = 0;
pub const PTHREAD_PROCESS_SHARED: c_int = 0;
pub const PTHREAD_PROCESS_PRIVATE: c_int = 1;
/// Signifies process scheduling contention scope.
pub const PTHREAD_SCOPE_PROCESS: c_int = 0;
/// Signifies system scheduling contention scope.
pub const PTHREAD_SCOPE_SYSTEM: c_int = 1;
pub mod attr;