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