1 #![cfg_attr(test, allow(dead_code))] // why is this necessary?
2 use crate::boxed::FnBox;
5 use crate::time::Duration;
7 use super::abi::usercalls;
9 pub struct Thread(task_queue::JoinHandle);
11 pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
14 use crate::sync::{Mutex, MutexGuard, Once};
15 use crate::sync::mpsc;
16 use crate::boxed::FnBox;
18 pub type JoinHandle = mpsc::Receiver<()>;
20 pub(super) struct Task {
22 done: mpsc::Sender<()>,
26 pub(super) fn new(p: Box<dyn FnBox()>) -> (Task, JoinHandle) {
27 let (done, recv) = mpsc::channel();
28 (Task { p, done }, recv)
31 pub(super) fn run(self) {
33 let _ = self.done.send(());
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;
44 pub(super) fn lock() -> MutexGuard<'static, Vec<Task>> {
46 TASK_QUEUE_INIT.call_once(|| TASK_QUEUE = Some(Default::default()) );
47 TASK_QUEUE.as_ref().unwrap().lock().unwrap()
53 // unsafe: see thread::Builder::spawn_unchecked for safety requirements
54 pub unsafe fn new(_stack: usize, p: Box<dyn FnBox()>)
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);
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
73 usercalls::wait(0, usercalls::raw::WAIT_NO).unwrap_err().kind(),
74 io::ErrorKind::WouldBlock
78 pub fn set_name(_name: &CStr) {
79 // FIXME: could store this pointer in TLS somewhere
82 pub fn sleep(_dur: Duration) {
83 panic!("can't sleep"); // FIXME
87 let _ = self.0.recv();
93 pub unsafe fn current() -> Option<Guard> { None }
94 pub unsafe fn init() -> Option<Guard> { None }