1#[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "illumos"))]
2use libc::pthread_attr_get_np as get_attr;
3#[cfg(any(target_os = "linux", target_os = "solaris", target_os = "netbsd"))]
4use libc::pthread_getattr_np as get_attr;
5
6pub unsafe fn guess_os_stack_limit() -> Option<usize> {
7 let mut attr = PthreadAttr::new()?;
8 (get_attr(libc::pthread_self(), &mut attr.0) == 0).then_some(())?;
9 let mut stackaddr = std::ptr::null_mut();
10 let mut stacksize = 0;
11 (libc::pthread_attr_getstack(&attr.0, &mut stackaddr, &mut stacksize) == 0).then_some(())?;
12 Some(stackaddr as usize)
13}
14
15struct PthreadAttr(libc::pthread_attr_t);
16
17impl Drop for PthreadAttr {
18 fn drop(&mut self) {
19 unsafe {
20 let ret = libc::pthread_attr_destroy(&mut self.0);
21 if ret != 0 {
22 let err = std::io::Error::last_os_error();
23 panic!(
24 "pthread_attr_destroy failed with error code {}: {}",
25 ret, err
26 );
27 }
28 }
29 }
30}
31
32impl PthreadAttr {
33 unsafe fn new() -> Option<Self> {
34 let mut attr = std::mem::MaybeUninit::<libc::pthread_attr_t>::uninit();
35 if libc::pthread_attr_init(attr.as_mut_ptr()) != 0 {
36 return None;
37 }
38 Some(PthreadAttr(attr.assume_init()))
39 }
40}