Skip to content

kernel::spawn

Task creation and stack allocation (plan W1.3, W0.1).

Stacks are bump-allocated from the linker-defined task_stacks region (_task_stack_start/_task_stack_end) — no magic addresses. Each task’s initial TaskContext is built so the first dispatch (rfe in the trap handler) lands at the entry point with a clean single register window.

enum StackSource {
Pool,
Heap,
}

Where a new task’s stack comes from.

Implements: Clone, Copy, Eq, PartialEq, StructuralPartialEq

fn stack_guard_intact(stack_base: u32, stack_size: u32) -> bool

True if tcb’s stack guard is still intact.

A false return means the task has already written past the bottom of its stack and has corrupted whatever lies below. Tasks with stack_size == 0 (the idle task, which runs on the boot stack) are always reported intact.

fn sys_spawn(name: &'static str, entry: fn(..), priority: hal::types::Priority, stack_size: usize) -> Option<hal::types::TaskId>

Kernel-internal spawn. Returns None if no TCB slot or stack is available.

References: Priority, TaskId

fn sys_spawn_from(name: &'static str, entry: fn(..), priority: hal::types::Priority, stack_size: usize, affinity: scheduler::Affinity, stack: StackSource) -> Option<hal::types::TaskId>

Spawn with an explicit stack source.

The caller must delete the task through dynobj::delete_task, which is what returns the stack. Letting a heap-backed task simply run off the end of its entry point leaks the stack exactly as the pool would.

References: Affinity, Priority, StackSource, TaskId

fn sys_spawn_with_affinity(name: &'static str, entry: fn(..), priority: hal::types::Priority, stack_size: usize, affinity: scheduler::Affinity) -> Option<hal::types::TaskId>

Spawn with an explicit core affinity.

Affinity::Any is what sys_spawn passes and what most tasks want. Pinning is for a task that cannot float: a driver whose peripheral interrupt is routed to one core’s matrix, or work with a timing budget that a migration would blow.

References: Affinity, Priority, TaskId

const STACK_GUARD: u32;

Written at the lowest address of every task stack and checked on each context switch. Stack growth is downward, so this word is the first thing an overflow destroys.