1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
use crate::std::io;
use alloc::boxed::Box;
use core::num::NonZeroUsize;

// Rust does't need the OS tids, it just needs unique ids, so we just use the
// raw `Thread` value casted to `usize`.
pub struct ThreadId(usize);

pub struct Thread(origin::thread::Thread);

impl Thread {
    pub fn id(&self) -> ThreadId {
        ThreadId(self.0.to_raw() as usize)
    }
}

pub struct JoinHandle(Thread);

impl JoinHandle {
    pub fn join(self) -> io::Result<()> {
        unsafe {
            origin::thread::join_thread(self.0 .0);
        }

        // Don't call drop, which would detach the thread we just joined.
        core::mem::forget(self);

        Ok(())
    }
}

impl Drop for JoinHandle {
    fn drop(&mut self) {
        unsafe {
            origin::thread::detach_thread(self.0 .0);
        }
    }
}

pub fn spawn<F>(f: F) -> JoinHandle
where
    F: FnOnce() + Send + 'static,
{
    let thread = origin::thread::create_thread(
        Box::new(|| {
            unsafe {
                let _handler = crate::stack_overflow::Handler::new();
            }

            f();
            None
        }),
        origin::thread::default_stack_size(),
        origin::thread::default_guard_size(),
    )
    .unwrap();

    JoinHandle(Thread(thread))
}

pub fn current() -> Thread {
    Thread(origin::thread::current_thread())
}

pub(crate) struct GetThreadId;

unsafe impl rustix_futex_sync::lock_api::GetThreadId for GetThreadId {
    const INIT: Self = Self;

    fn nonzero_thread_id(&self) -> NonZeroUsize {
        // TODO: Use `origin::thread::currrent_thread().addr()` once that's stable.
        NonZeroUsize::new(origin::thread::current_thread().to_raw_non_null().as_ptr() as usize).unwrap()
    }
}

pub(crate) type ReentrantMutex<T> = rustix_futex_sync::ReentrantMutex<GetThreadId, T>;
pub(crate) type ReentrantMutexGuard<'a, T> =
    rustix_futex_sync::ReentrantMutexGuard<'a, GetThreadId, T>;