1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
#![warn(missing_docs)] //! Isolated tasks of execution use std::panic; use crate::binding::Never; use crate::boxed::prelude::*; use crate::boxed::type_info::TypeInfo; use crate::boxed::Heap; /// Isolated task of execution /// /// All Arret and RFI code must run inside a task. It provides a dedicated garbage collected /// [`Heap`] as well as an isolation boundary against panics. A task is inherently single threaded; /// it's not possible for one task to be executing on multiple threads at the same time. pub struct Task { heap: Heap, } impl Task { const DEFAULT_CAPACITY: usize = 32; /// Creates a new empty task pub fn new() -> Task { Self::with_type_info(TypeInfo::empty()) } pub(crate) fn with_type_info(type_info: TypeInfo) -> Task { Self { heap: Heap::new(type_info, Self::DEFAULT_CAPACITY), } } /// Returns this task's dedicated heap pub fn heap(&self) -> &Heap { &self.heap } /// Returns a mutable reference to this task's dedicated heap pub fn heap_mut(&mut self) -> &mut Heap { &mut self.heap } /// Panics the current task /// /// This destroys the current task and invokes any cleanup required. pub fn panic(&mut self, message: String) -> Never { // Using `resume_unwind` accomplishes two things: // // 1. Avoids printing the panic info to stderr as this is an "intentional" panic // 2. Skips incrementing our panic count. This is important for compile time evaluation of // panics. The compiler and stdlib have a different panic count due to being in separate // binaries. With a normal `panic!` the panic count will be increment on the stdlib and // decremented in the compiler. On the second panic the stdlib thinks it's already // panicking and aborts. This is a hacky workaround. // // TODO: Fix panics uniformly and remove this method. If we panic inside e.g. Rust stdlib // we won't follow this path. panic::resume_unwind(Box::new(message)); } } impl Default for Task { fn default() -> Task { Task::new() } } impl AsHeap for Task { fn as_heap(&self) -> &Heap { &self.heap } fn as_heap_mut(&mut self) -> &mut Heap { &mut self.heap } }