Function psm::on_stack[][src]

pub unsafe fn on_stack<R, F: FnOnce() -> R>(
    base: *mut u8,
    size: usize,
    callback: F
) -> R

Run the closure on the provided stack.

Once the closure completes its execution, the original stack pointer is restored and execution returns to the caller.

base address must be the low address of the stack memory region, regardless of the stack growth direction. It is not necessary for the whole region [base; base + size] to be usable at the time this function called, however it is required that at least the following hold:

Note, that some or all of these considerations are irrelevant to some applications. For example, Rust’s soundness story relies on all stacks having a guard-page, however if the user is able to guarantee that the memory region used for stack cannot be exceeded, a guard page may end up being an expensive unnecessity.

The previous stack may not be deallocated. If an ability to deallocate the old stack is desired consider replace_stack instead.

Guidelines

Memory regions that are aligned to a single page (usually 4kB) are an extremely portable choice for stacks.

Allocate at least 4kB of stack. Some architectures (such as SPARC) consume stack memory significantly faster compared to the more usual architectures such as x86 or ARM. Allocating less than 4kB of memory may make it impossible to commit more pages without overflowing the stack later on.

Unsafety

The stack base address must be aligned as appropriate for the target.

The stack size must be a multiple of stack alignment required by target.

The size must not overflow isize.

callback must not unwind or return control flow by any other means than directly returning.

Examples

use std::alloc;
const STACK_ALIGN: usize = 4096;
const STACK_SIZE: usize = 4096;
unsafe {
    let layout = alloc::Layout::from_size_align(STACK_SIZE, STACK_ALIGN).unwrap();
    let new_stack = alloc::alloc(layout);
    assert!(!new_stack.is_null(), "allocations must succeed!");
    let (stack, result) = psm::on_stack(new_stack, STACK_SIZE, || {
        (psm::stack_pointer(), 4 + 4)
    });
    println!("4 + 4 = {} has been calculated on stack {:p}", result, stack);
}