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}