blob: f99d40232866475fcb74b78f2ee29f2558fc5ad4 [file] [log] [blame]
//! Runtime components related to process startup.
/// `set_main!` is used to tell `libtock_runtime` where the process binary's
/// `main` function is. The process binary's `main` function must have the
/// signature `FnOnce() -> !`.
///
/// # Example
/// ```
/// libtock_runtime::set_main!{main};
///
/// fn main() -> ! { /* Omitted */ }
/// ```
// set_main! generates a function called `libtock_unsafe_main`, which is called
// by `rust_start`. The function has `unsafe` in its name because implementing
// it is `unsafe` (it *must* have the signature `libtock_unsafe_main() -> !`),
// but there is no way to enforce the use of `unsafe` through the type system.
// This function calls the client-provided function, which enforces its type
// signature.
#[macro_export]
macro_rules! set_main {
{$name:ident} => {
#[no_mangle]
fn libtock_unsafe_main() -> ! {
$name()
}
}
}
/// Executables must specify their stack size by using the `stack_size!` macro.
/// It takes a single argument, the desired stack size in bytes. Example:
/// ```
/// stack_size!{0x400}
/// ```
// stack_size works by putting a symbol equal to the size of the stack in the
// .stack_buffer section. The linker script uses the .stack_buffer section to
// size the stack. flash.sh looks for the symbol by name (hence #[no_mangle]) to
// determine the size of the stack to pass to elf2tab.
#[macro_export]
macro_rules! stack_size {
{$size:expr} => {
#[no_mangle]
#[link_section = ".stack_buffer"]
pub static mut STACK_MEMORY: [u8; $size] = [0; $size];
}
}
// rust_start is the first Rust code to execute in the process. It is called
// from start, which is written directly in assembly.
#[no_mangle]
extern "C" fn rust_start() -> ! {
// TODO: Call memop() to inform the kernel of the stack and heap sizes +
// locations. Also, perhaps we should support calling a heap initialization
// function?
extern "Rust" {
fn libtock_unsafe_main() -> !;
}
unsafe {
libtock_unsafe_main();
}
}