sel4_root_task/lib.rs
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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
//
// Copyright 2023, Colias Group, LLC
//
// SPDX-License-Identifier: BSD-2-Clause
//
//! A runtime for root tasks.
//!
//! This crate defines an entrypoint at `_start` that performs the following Rust language runtime
//! and [`libsel4`](sel4) initialization:
//! - Set up the stack
//! - Initialize thread-local storage (using stack memory)
//! - Set up exception handling
//! - Set the seL4 IPC buffer for `libsel4` (using [`sel4::set_ipc_buffer`])
//! - Run C-style constructors (from `__init_array_start`/`__init_array_end`)
//!
//! After initialization, the entrypoint calls the root task main function, which must be declared
//! with [`#[root_task]`](root_task). For example:
//!
//! ```rust
//! #[root_task]
//! fn main(bootinfo: &sel4::BootInfo) -> ! {
//! todo!()
//! }
//! ```
//!
//! Building root tasks using this crate does not require a custom linker script when using `LLD`.
//! In particular, this crate is tested with the `LLD` binary that ships with `rustc` (`rust-lld`).
//! Using a GNU linker will likely require a custom linker script.
#![no_std]
#![feature(cfg_target_thread_local)]
#![feature(linkage)]
#![feature(never_type)]
pub use sel4_panicking_env::abort;
#[doc(inline)]
pub use sel4_panicking as panicking;
mod entry;
mod heap;
mod printing;
mod termination;
pub use heap::set_global_allocator_mutex_notification;
pub use termination::{Never, Termination};
#[sel4::sel4_cfg(PRINTING)]
pub use sel4_panicking_env::{debug_print, debug_println};
/// Declares a function to be the root task's main function.
///
/// For example:
///
/// ```rust
/// #[root_task]
/// fn main(bootinfo: &sel4::BootInfo) -> ! {
/// todo!()
/// }
/// ```
///
/// The main function have a signature of the form:
///
/// ```rust
/// fn<T: Termination>(&sel4::BootInfoPtr) -> T
/// ```
///
/// (See [`Termination`])
///
/// This macro takes two optional parameters, whose values can be any expression of type `usize`:
///
/// ```rust
/// #[root_task(
/// stack_size = <stack_size_expr: usize>,
/// heap_size = <heap_size_expr: usize>,
/// )]
/// ```
///
/// - `stack_size`: Declares the size of the initial thread's stack, in bytes. Note that this
/// includes space for thread-local storage. If absent, [`DEFAULT_STACK_SIZE`] will be used.
/// - `heap_size`: Creates a `#[global_allocator]`, backed by a static heap of the specified size.
/// If this parameter is not specified, no `#[global_allocator]` will be automatically declared,
/// and, unless one is manually declared, heap allocations will result in a link-time error.
///
/// Note that, if both parameters are provided, they must appear in the order above.
pub use sel4_root_task_macros::root_task;
#[doc(hidden)]
#[macro_export]
macro_rules! declare_root_task {
{
main = $main:expr $(,)?
} => {
$crate::_private::declare_root_task! {
main = $main,
stack_size = $crate::_private::DEFAULT_STACK_SIZE,
}
};
{
main = $main:expr,
stack_size = $stack_size:expr $(,)?
} => {
$crate::_private::declare_main!($main);
$crate::_private::declare_stack!($stack_size);
};
{
main = $main:expr,
$(stack_size = $stack_size:expr,)?
heap_size = $heap_size:expr $(,)?
} => {
$crate::_private::declare_heap!($heap_size);
$crate::_private::declare_root_task! {
main = $main,
$(stack_size = $stack_size,)?
}
};
}
/// The default stack size used by [`#[root_task]`](crate::root_task).
pub const DEFAULT_STACK_SIZE: usize = 1024
* if cfg!(panic = "unwind") && cfg!(debug_assertions) {
128
} else {
64
};
// For macros
#[doc(hidden)]
pub mod _private {
pub use sel4::BootInfoPtr;
pub use sel4_runtime_common::declare_stack;
pub use crate::heap::_private as heap;
pub use crate::{
declare_heap, declare_main, declare_root_task, entry::run_main, DEFAULT_STACK_SIZE,
};
}