From bc228c3d917a6074e072f20256e7e3e961c90497 Mon Sep 17 00:00:00 2001 From: auronandace Date: Thu, 2 Jul 2026 13:08:16 +0100 Subject: [PATCH] document pthread attr functions --- src/header/pthread/attr.rs | 328 ++++++++++++++++++++++++++++++++----- src/header/pthread/mod.rs | 20 ++- 2 files changed, 303 insertions(+), 45 deletions(-) diff --git a/src/header/pthread/attr.rs b/src/header/pthread/attr.rs index b3c27444ae..9627a08f52 100644 --- a/src/header/pthread/attr.rs +++ b/src/header/pthread/attr.rs @@ -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 . +/// +/// 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 . +/// +/// 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 . +/// +/// 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::()).guardsize) }; + unsafe { ptr::write(guardsize, (*attr.cast::()).guardsize) }; 0 } /// See . +/// +/// 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 . +/// +/// 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 . +/// +/// 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 . +/// +/// 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::()).scope.into()) }; + unsafe { ptr::write(contentionscope, (*attr.cast::()).scope.into()) }; 0 } /// See . +/// +/// 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::()).stack as _) }; - unsafe { ptr::write(stacksize, (*attr.cast::()).stacksize as _) }; + unsafe { ptr::write(stacksize, (*attr.cast::()).stacksize) }; 0 } /// See . +/// +/// 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::()).stacksize as _) }; + unsafe { ptr::write(stacksize, (*attr.cast::()).stacksize) }; 0 } /// See . +/// +/// 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::default()) }; @@ -131,18 +259,46 @@ pub unsafe extern "C" fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int { } /// See . +/// +/// 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::()).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::()).detachstate = ds; + } + } + 0 + } + _ => crate::header::errno::EINVAL, } - 0 } /// See . +/// +/// 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 . +/// +/// 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::()).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::()).inheritsched = insch; + } + } + 0 + } + _ => crate::header::errno::ENOTSUP, } - 0 } /// See . +/// +/// 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 . +/// +/// 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::()).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::()).schedpolicy = pol; + } + } + 0 + } + _ => crate::header::errno::ENOTSUP, } - 0 } /// See . +/// +/// 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::()).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::()).scope = ctnscope; + } + } + 0 + } + _ => crate::header::errno::ENOTSUP, } - 0 } /// See . +/// +/// 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::()).stack = stackaddr as usize; + if stacksize as c_long >= PTHREAD_STACK_MIN { + unsafe { + (*attr.cast::()).stack = stackaddr as usize; + } + unsafe { + (*attr.cast::()).stacksize = stacksize; + } + 0 + } else { + crate::header::errno::EINVAL } - unsafe { - (*attr.cast::()).stacksize = stacksize; - } - 0 } /// See . +/// +/// 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::()).stacksize = stacksize; + if stacksize as c_long >= PTHREAD_STACK_MIN { + unsafe { + (*attr.cast::()).stacksize = stacksize; + } + 0 + } else { + crate::header::errno::EINVAL } - 0 } +// TODO should be guarded by _GNU_SOURCE +/// Non-POSIX, see . +/// +/// 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::() }; - let attr_ptr = attr_ptr.cast::(); +pub unsafe extern "C" fn pthread_getattr_np(thread: pthread_t, attr: *mut pthread_attr_t) -> c_int { + let thread = unsafe { &*thread.cast::() }; + let attr_ptr = attr.cast::(); unsafe { ptr::write(attr_ptr, RlctAttr::default()) }; let attr = unsafe { &mut *attr_ptr }; if thread.flags.load(Ordering::Acquire) & PthreadFlags::DETACHED.bits() != 0 { diff --git a/src/header/pthread/mod.rs b/src/header/pthread/mod.rs index 7cd55d6fd9..8eea5c8827 100644 --- a/src/header/pthread/mod.rs +++ b/src/header/pthread/mod.rs @@ -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;