pub unsafe trait PortThreading: KernelCfg1 + KernelStatic<System<Self>> {
    type PortTaskState: Send + Sync + Init + Debug + 'static;

    const PORT_TASK_STATE_INIT: Self::PortTaskState;
    const STACK_DEFAULT_SIZE: usize = 1_024usize;
    const STACK_ALIGN: usize = 8usize;

    // Required methods
    unsafe fn dispatch_first_task() -> !;
    unsafe fn yield_cpu();
    unsafe fn exit_and_dispatch(task: &'static TaskCb<Self>) -> !;
    unsafe fn enter_cpu_lock();
    unsafe fn leave_cpu_lock();
    unsafe fn initialize_task_state(task: &'static TaskCb<Self>);
    fn is_cpu_lock_active() -> bool;
    fn is_task_context() -> bool;
    fn is_interrupt_context() -> bool;
    fn is_scheduler_active() -> bool;

    // Provided method
    unsafe fn try_enter_cpu_lock() -> bool { ... }
}
Expand description

Implemented by a port. This trait contains items related to low-level operations for controlling CPU states and context switching.

Safety

Implementing a port is inherently unsafe because it’s responsible for initializing the execution environment and providing a dispatcher implementation.

These methods are only meant to be called by the kernel.

Required Associated Types§

source

type PortTaskState: Send + Sync + Init + Debug + 'static

Required Associated Constants§

source

const PORT_TASK_STATE_INIT: Self::PortTaskState

The initial value of TaskCb::port_task_state for all tasks.

Provided Associated Constants§

source

const STACK_DEFAULT_SIZE: usize = 1_024usize

The default stack size for tasks.

source

const STACK_ALIGN: usize = 8usize

The alignment requirement for task stack regions.

Both ends of stack regions are aligned by STACK_ALIGN. It’s automatically enforced by the kernel configurator for automatically allocated stack regions (this applies to tasks created without StackHunk). The kernel configurator does not check the alignemnt for manually-allocated stack regions.

Required Methods§

source

unsafe fn dispatch_first_task() -> !

Transfer the control to the dispatcher, discarding the current (startup) context. *state.running_task_ptr() is None at this point. The dispatcher should call PortToKernel::choose_running_task to find the next task to run and transfer the control to that task.

Precondition: CPU Lock active, a boot context

source

unsafe fn yield_cpu()

Yield the processor.

In a task context, this method immediately transfers the control to a dispatcher. The dispatcher should call PortToKernel::choose_running_task to find the next task to run and transfer the control to that task.

In an interrupt context, the effect of this method will be deferred until the processor completes the execution of all active interrupt handler threads.

Precondition: CPU Lock inactive

Port Implementation Note: One way to handle the interrupt context case is to set a flag variable and check it in the epilogue of a first-level interrupt handler. Another way is to raise a low-priority interrupt (such as PendSV in Arm-M) and implement dispatching in the handler.

source

unsafe fn exit_and_dispatch(task: &'static TaskCb<Self>) -> !

Destroy the state of the previously running task (task, which has already been removed from *state.running_task_ptr()) and proceed to the dispatcher.

Precondition: CPU Lock active

source

unsafe fn enter_cpu_lock()

Disable all kernel-managed interrupts (this state is called CPU Lock).

Precondition: CPU Lock inactive

source

unsafe fn leave_cpu_lock()

Re-enable kernel-managed interrupts previously disabled by enter_cpu_lock, thus deactivating the CPU Lock state.

Precondition: CPU Lock active

source

unsafe fn initialize_task_state(task: &'static TaskCb<Self>)

Prepare the task for activation. More specifically, set the current program counter to TaskAttr::entry_point and the current stack pointer to either end of TaskAttr::stack, ensuring the task will start execution from entry_point next time the task receives the control.

Do not call this for a running task. Calling this for a dormant task is always safe. For tasks in other states, whether this method is safe is dependent on how the programming language the task code is written in is implemented. In particular, this is unsafe for Rust task code because it might violate the requirement of Pin if there’s a Pin pointing to something on the task’s stack.

Precondition: CPU Lock active

source

fn is_cpu_lock_active() -> bool

Return a flag indicating whether a CPU Lock state is active.

source

fn is_task_context() -> bool

Return a flag indicating whether the current context is a task context.

source

fn is_interrupt_context() -> bool

Return a flag indicating whether the current context is an interrupt context.

source

fn is_scheduler_active() -> bool

Return a flag indicating whether Self::dispatch_first_task was called.

Provided Methods§

source

unsafe fn try_enter_cpu_lock() -> bool

Activate CPU Lock. Return true iff CPU Lock was inactive before the call.

Implementors§