twizzler_rt_abi/
thread.rs

1//! Runtime interface for threads.
2
3#![allow(unused_variables)]
4use core::time::Duration;
5
6use crate::{error::RawTwzError, Result};
7
8/// Runtime-internal thread ID.
9pub type ThreadId = crate::bindings::thread_id;
10/// Index of a TLS variable.
11pub type TlsIndex = crate::bindings::tls_index;
12/// TLS desc
13pub type TlsDesc = crate::bindings::tls_desc;
14/// Type of a linux-like wait point.
15pub type FutexWord = crate::bindings::futex_word;
16/// Atomic futex word, for a linux-like thread wait.
17pub type AtomicFutexWord = core::sync::atomic::AtomicU32;
18/// Arguments to spawn.
19pub type ThreadSpawnArgs = crate::bindings::spawn_args;
20
21impl From<Result<ThreadId>> for crate::bindings::spawn_result {
22    fn from(value: Result<ThreadId>) -> Self {
23        match value {
24            Ok(id) => Self {
25                id,
26                err: RawTwzError::success().raw(),
27            },
28            Err(e) => Self {
29                id: 0,
30                err: e.raw(),
31            },
32        }
33    }
34}
35
36impl From<crate::bindings::spawn_result> for Result<ThreadId> {
37    fn from(value: crate::bindings::spawn_result) -> Self {
38        let raw = RawTwzError::new(value.err);
39        if raw.is_success() {
40            Ok(value.id)
41        } else {
42            Err(raw.error())
43        }
44    }
45}
46
47/// If the futex word pointed to by `word` is equal to expected, put the thread to sleep. This
48/// operation is atomic -- the thread is enqueued on the sleep queue _first_, before the equality
49/// check. Returns false on timeout, true on all other cases.
50pub fn twz_rt_futex_wait(
51    word: &AtomicFutexWord,
52    expected: FutexWord,
53    timeout: Option<Duration>,
54) -> bool {
55    unsafe { crate::bindings::twz_rt_futex_wait(word.as_ptr().cast(), expected, timeout.into()) }
56}
57
58/// Wake up up to max threads waiting on `word`. If max is None, wake up all threads.
59pub fn twz_rt_futex_wake(word: &AtomicFutexWord, max: Option<usize>) -> bool {
60    let max = match max {
61        Some(max) => max as i64,
62        None => crate::bindings::FUTEX_WAKE_ALL,
63    };
64    unsafe { crate::bindings::twz_rt_futex_wake(word.as_ptr().cast(), max) }
65}
66
67/// Yield the calling thread.
68pub fn twz_rt_yield() {
69    unsafe {
70        crate::bindings::twz_rt_yield_now();
71    }
72}
73
74/// Sleep the calling thread for duration `dur`.
75pub fn twz_rt_sleep(dur: Duration) {
76    unsafe {
77        crate::bindings::twz_rt_sleep(dur.into());
78    }
79}
80
81/// Set the name of the calling thread.
82pub fn twz_rt_set_thread_name(name: &core::ffi::CStr) {
83    unsafe {
84        crate::bindings::twz_rt_set_name(name.as_ptr());
85    }
86}
87
88/// Get the address of a given TLS variable.
89pub fn twz_rt_tls_get_addr(index: &TlsIndex) -> *mut u8 {
90    unsafe { crate::bindings::twz_rt_tls_get_addr(index as *const _ as *mut _).cast() }
91}
92
93/// Spawn a thread. On success, that thread starts executing concurrently with the return of this
94/// function.
95pub fn twz_rt_spawn_thread(args: ThreadSpawnArgs) -> Result<ThreadId> {
96    unsafe { crate::bindings::twz_rt_spawn_thread(args).into() }
97}
98
99/// Wait for a thread to exit, optionally timing out.
100pub fn twz_rt_join_thread(id: ThreadId, timeout: Option<Duration>) -> Result<()> {
101    unsafe { RawTwzError::new(crate::bindings::twz_rt_join_thread(id, timeout.into())).result() }
102}