Skip to main content

dope_sys/thread/
attrs.rs

1use std::{mem, num::NonZero};
2
3use crate::{Errno, kernel};
4
5/// Native thread attributes carrying one validated stack extent.
6pub struct Attrs(libc::pthread_attr_t);
7
8impl Attrs {
9    /// Initializes attributes for a thread with the exact requested stack.
10    pub fn with_stack(stack: NonZero<usize>) -> Result<Self, Errno> {
11        let mut raw = mem::MaybeUninit::uninit();
12        // SAFETY: raw has the native attribute size and is initialized on success.
13        let result = unsafe { libc::pthread_attr_init(raw.as_mut_ptr()) };
14        // SAFETY: pthread_attr_init returns zero or a positive error code directly.
15        unsafe { kernel::raw::Status::new(result).try_pthread() }?;
16        // SAFETY: pthread_attr_init completed, so this value is initialized and
17        // owned here until its Drop destroys it.
18        let mut attr = Self(unsafe { raw.assume_init() });
19        let result = unsafe { libc::pthread_attr_setstacksize(&mut attr.0, stack.get()) };
20        // SAFETY: pthread_attr_setstacksize returns zero or a positive error code.
21        unsafe { kernel::raw::Status::new(result).try_pthread() }?;
22        Ok(attr)
23    }
24
25    pub(super) fn as_ptr(&self) -> *const libc::pthread_attr_t {
26        &self.0
27    }
28}
29
30/// Destroys the uniquely owned attributes; no caller can invalidate them first.
31impl Drop for Attrs {
32    fn drop(&mut self) {
33        // SAFETY: these initialized attributes are exclusively owned and destroyed
34        // once. Only stack size was changed, so no work-interval port is retained;
35        // destruction returns exactly zero on the admitted native implementations.
36        unsafe { libc::pthread_attr_destroy(&mut self.0) };
37    }
38}