]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/sgx/thread.rs
Add `std::os::fortanix_sgx` module
[rust.git] / src / libstd / sys / sgx / thread.rs
1 // Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use boxed::FnBox;
12 use ffi::CStr;
13 use io;
14 use time::Duration;
15
16 use super::abi::usercalls;
17
18 pub struct Thread(task_queue::JoinHandle);
19
20 pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
21
22 mod task_queue {
23     use sync::{Mutex, MutexGuard, Once};
24     use sync::mpsc;
25     use boxed::FnBox;
26
27     pub type JoinHandle = mpsc::Receiver<()>;
28
29     pub(super) struct Task {
30         p: Box<dyn FnBox()>,
31         done: mpsc::Sender<()>,
32     }
33
34     impl Task {
35         pub(super) fn new(p: Box<dyn FnBox()>) -> (Task, JoinHandle) {
36             let (done, recv) = mpsc::channel();
37             (Task { p, done }, recv)
38         }
39
40         pub(super) fn run(self) {
41             (self.p)();
42             let _ = self.done.send(());
43         }
44     }
45
46     static TASK_QUEUE_INIT: Once = Once::new();
47     static mut TASK_QUEUE: Option<Mutex<Vec<Task>>> = None;
48
49     pub(super) fn lock() -> MutexGuard<'static, Vec<Task>> {
50         unsafe {
51             TASK_QUEUE_INIT.call_once(|| TASK_QUEUE = Some(Default::default()) );
52             TASK_QUEUE.as_ref().unwrap().lock().unwrap()
53         }
54     }
55 }
56
57 impl Thread {
58     // unsafe: see thread::Builder::spawn_unchecked for safety requirements
59     pub unsafe fn new(_stack: usize, p: Box<dyn FnBox()>)
60         -> io::Result<Thread>
61     {
62         let mut queue_lock = task_queue::lock();
63         usercalls::launch_thread()?;
64         let (task, handle) = task_queue::Task::new(p);
65         queue_lock.push(task);
66         Ok(Thread(handle))
67     }
68
69     pub(super) fn entry() {
70         let mut guard = task_queue::lock();
71         let task = guard.pop().expect("Thread started but no tasks pending");
72         drop(guard); // make sure to not hold the task queue lock longer than necessary
73         task.run()
74     }
75
76     pub fn yield_now() {
77         assert_eq!(
78             usercalls::wait(0, usercalls::raw::WAIT_NO).unwrap_err().kind(),
79             io::ErrorKind::WouldBlock
80         );
81     }
82
83     pub fn set_name(_name: &CStr) {
84         // FIXME: could store this pointer in TLS somewhere
85     }
86
87     pub fn sleep(_dur: Duration) {
88         panic!("can't sleep"); // FIXME
89     }
90
91     pub fn join(self) {
92         let _ = self.0.recv();
93     }
94 }
95
96 pub mod guard {
97     pub type Guard = !;
98     pub unsafe fn current() -> Option<Guard> { None }
99     pub unsafe fn init() -> Option<Guard> { None }
100     pub unsafe fn deinit() {}
101 }