]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys/sgx/thread.rs
`#[deny(unsafe_op_in_unsafe_fn)]` in sys/sgx
[rust.git] / library / std / src / sys / sgx / thread.rs
1 #![cfg_attr(test, allow(dead_code))] // why is this necessary?
2 use crate::ffi::CStr;
3 use crate::io;
4 use crate::time::Duration;
5
6 use super::abi::usercalls;
7
8 pub struct Thread(task_queue::JoinHandle);
9
10 pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
11
12 mod task_queue {
13     use crate::sync::mpsc;
14     use crate::sync::{Mutex, MutexGuard, Once};
15
16     pub type JoinHandle = mpsc::Receiver<()>;
17
18     pub(super) struct Task {
19         p: Box<dyn FnOnce()>,
20         done: mpsc::Sender<()>,
21     }
22
23     impl Task {
24         pub(super) fn new(p: Box<dyn FnOnce()>) -> (Task, JoinHandle) {
25             let (done, recv) = mpsc::channel();
26             (Task { p, done }, recv)
27         }
28
29         pub(super) fn run(self) {
30             (self.p)();
31             let _ = self.done.send(());
32         }
33     }
34
35     #[cfg_attr(test, linkage = "available_externally")]
36     #[export_name = "_ZN16__rust_internals3std3sys3sgx6thread15TASK_QUEUE_INITE"]
37     static TASK_QUEUE_INIT: Once = Once::new();
38     #[cfg_attr(test, linkage = "available_externally")]
39     #[export_name = "_ZN16__rust_internals3std3sys3sgx6thread10TASK_QUEUEE"]
40     static mut TASK_QUEUE: Option<Mutex<Vec<Task>>> = None;
41
42     pub(super) fn lock() -> MutexGuard<'static, Vec<Task>> {
43         unsafe {
44             TASK_QUEUE_INIT.call_once(|| TASK_QUEUE = Some(Default::default()));
45             TASK_QUEUE.as_ref().unwrap().lock().unwrap()
46         }
47     }
48 }
49
50 impl Thread {
51     // unsafe: see thread::Builder::spawn_unchecked for safety requirements
52     pub unsafe fn new(_stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
53         let mut queue_lock = task_queue::lock();
54         unsafe { usercalls::launch_thread()? };
55         let (task, handle) = task_queue::Task::new(p);
56         queue_lock.push(task);
57         Ok(Thread(handle))
58     }
59
60     pub(super) fn entry() {
61         let mut pending_tasks = task_queue::lock();
62         let task = rtunwrap!(Some, pending_tasks.pop());
63         drop(pending_tasks); // make sure to not hold the task queue lock longer than necessary
64         task.run()
65     }
66
67     pub fn yield_now() {
68         let wait_error = rtunwrap!(Err, usercalls::wait(0, usercalls::raw::WAIT_NO));
69         rtassert!(wait_error.kind() == io::ErrorKind::WouldBlock);
70     }
71
72     pub fn set_name(_name: &CStr) {
73         // FIXME: could store this pointer in TLS somewhere
74     }
75
76     pub fn sleep(dur: Duration) {
77         usercalls::wait_timeout(0, dur, || true);
78     }
79
80     pub fn join(self) {
81         let _ = self.0.recv();
82     }
83 }
84
85 pub mod guard {
86     pub type Guard = !;
87     pub unsafe fn current() -> Option<Guard> {
88         None
89     }
90     pub unsafe fn init() -> Option<Guard> {
91         None
92     }
93 }