Trait r3_core::kernel::Kernel

source ·
pub trait Kernel: Sealed {
    type DebugPrinter: Debug + Send + Sync;

Show 18 methods // Required methods fn debug() -> <Self as Kernel>::DebugPrinter; fn acquire_cpu_lock() -> Result<(), CpuLockError>; unsafe fn release_cpu_lock() -> Result<(), CpuLockError>; fn has_cpu_lock() -> bool; fn boost_priority() -> Result<(), BoostPriorityError> where Self: KernelBoostPriority; unsafe fn unboost_priority() -> Result<(), BoostPriorityError>; fn is_priority_boost_active() -> bool; fn is_task_context() -> bool; fn is_interrupt_context() -> bool; fn is_boot_complete() -> bool; fn set_time(time: Time) -> Result<(), TimeError>; fn time() -> Result<Time, TimeError> where Self: KernelTime; fn time_user_headroom() -> Duration where Self: KernelAdjustTime; fn adjust_time(delta: Duration) -> Result<(), AdjustTimeError> where Self: KernelAdjustTime; unsafe fn exit_task() -> Result<!, ExitTaskError>; fn park() -> Result<(), ParkError>; fn park_timeout(timeout: Duration) -> Result<(), ParkTimeoutError>; fn sleep(duration: Duration) -> Result<(), SleepError>;
}
Expand description

Provides access to the global functionalities of a kernel.

This trait is mostly comprised of the same methods as those of the traits from the raw module. However, this trait is covered under a stronger semver guarantee as it’s an application-facing API. (TODO: Link to the relevant portion of the document)

This trait intentionally doesn’t include raw::KernelBase as its supertrait. It’s incorrect to constrain a system type by this trait. See the examples below.

Examples

use r3_core::kernel::{prelude::*, traits, Task, ParkError, BoostPriorityError};

fn park_while<System>(mut f: impl FnMut() -> bool) -> Result<(), ParkError>
where
    System: traits::KernelBase,
{
    while f() {
        System::park()?;
    }
    Ok(())
}

// note: this function is not unwind-safe
fn with_priority_boost<System>(f: impl FnOnce())
    -> Result<(), BoostPriorityError>
where
    System: traits::KernelBase + traits::KernelBoostPriority,
{
    System::boost_priority()?;
    f();
    unsafe { System::unboost_priority() }
}

Don’t constrain a system type by this trait:

fn current_task<System>() -> LocalTask<System>
where
    System: traits::Kernel,
{
    // ERROR: `System` doesn't implement `traits::KernelBase`
    LocalTask::current().unwrap()
}

Required Associated Types§

Required Methods§

source

fn debug() -> <Self as Kernel>::DebugPrinter

Get an object that implements Debug for dumping the current kernel state.

Note that printing this object might consume a large amount of stack space.

source

fn acquire_cpu_lock() -> Result<(), CpuLockError>

Activate CPU Lock.

Returns BadContext if CPU Lock is already active.

source

unsafe fn release_cpu_lock() -> Result<(), CpuLockError>

Deactivate CPU Lock.

Returns BadContext if CPU Lock is already inactive.

Safety

CPU Lock is useful for creating a critical section. By making this method unsafe, safe code is prevented from interfering with a critical section.

Deactivating CPU Lock in a boot context is disallowed.

source

fn has_cpu_lock() -> bool

Return a flag indicating whether CPU Lock is currently active.

source

fn boost_priority() -> Result<(), BoostPriorityError>where Self: KernelBoostPriority,

Activate Priority Boost.

Returns BadContext if Priority Boost is already active, the calling context is not a task context, or CPU Lock is active.

source

unsafe fn unboost_priority() -> Result<(), BoostPriorityError>

Deactivate Priority Boost.

Returns BadContext if Priority Boost is already inactive, the calling context is not a task context, or CPU Lock is active.

Safety

Priority Boost is useful for creating a critical section. By making this method unsafe, safe code is prevented from interfering with a critical section.

source

fn is_priority_boost_active() -> bool

Return a flag indicating whether Priority Boost is currently active.

source

fn is_task_context() -> bool

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

This is equivalent to is_boot_complete() && !is_interrupt_context().

source

fn is_interrupt_context() -> bool

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

This is equivalent to is_boot_complete() && !is_task_context().

source

fn is_boot_complete() -> bool

Return a flag indicating whether the boot phase is complete, i.e., all startup hooks completed execution, and the kernel started scheduling tasks and taking interrupts.

source

fn set_time(time: Time) -> Result<(), TimeError>

Set the current system time.

This method does not change the relative arrival times of outstanding timed events nor the relative time of the frontier (a concept used in the definition of adjust_time).

This method will return TimeError::BadContext when called in a non-task context.

Rationale: This restriction originates from μITRON4.0. It’s actually unnecessary in r3_kernel’s current implementation, but allows more leeway in a kernel implementation.

source

fn time() -> Result<Time, TimeError>where Self: KernelTime,

Get the current system time.

This method will return TimeError::BadContext when called in a non-task context.

Rationale: This restriction originates from μITRON4.0. It’s actually unnecessary in r3_kernel’s current implementation, but allows more leeway in a kernel implementation.

source

fn time_user_headroom() -> Durationwhere Self: KernelAdjustTime,

The extent of how overdue a timed event can be made or how far a timed event can be delayed past Duration::MAX by a call to adjust_time.

This must be greater than or equal to one second. It might report a smaller number than the actual limit, for example, because the kernel might use a time representation wider than Duration.

Rationale: Although it was intended to be an associated constant, trait bounds could not be applied to an associated constant due to the lack of compiler support.

source

fn adjust_time(delta: Duration) -> Result<(), AdjustTimeError>where Self: KernelAdjustTime,

Move the current system time forward or backward by the specified amount.

This method changes the relative arrival times of outstanding timed events.

The kernel uses a limited number of bits to represent the arrival times of outstanding timed events. This means that there’s some upper bound on how far the system time can be moved away without breaking internal invariants. This method ensures this bound is not violated by the methods described below. This method will return BadObjectState if this check fails.

Moving Forward (delta > 0): If there are no outstanding time events, adjustment in this direction is unbounded. Otherwise, let t be the relative arrival time (in relation to the current time) of the earliest outstanding time event. If t - delta < -time_user_headroom (i.e., if the adjustment would make the event overdue by more than time_user_headroom), the check will fail.

The events made overdue by the call will be processed when the timer driver announces a new tick. It’s unspecified whether this happens before or after the call returns.

Moving Backward (delta < 0): First, we introduce the concept of a frontier. The frontier represents the point of time at which the system time advanced the most. Usually, the frontier is identical to the current system time because the system time keeps moving forward (a). However, adjusting the system time to past makes them temporarily separate from each other (b). In this case, the frontier stays in place until the system time eventually catches up with the frontier and they start moving together again (c).

Let frontier be the current relative time of the frontier (in relation to the current time). If frontier - delta > time_user_headroom (i.e., if the adjustment would move the frontier too far away), the check will fail.

Observation: Even under ideal circumstances, all timed events are bound to be overdue by a very small extent because of various factors such as an intrinsic interrupt latency, insufficient timer resolution, and uses of CPU Lock. This means the minimum value of t in the above explanation is not 0 but a somewhat smaller value. The consequence is that delta can never reliably be >= time_user_headroom.

Notes: As noted in its documentation, time_user_headroom merely defines the lower bound of a kernel’s tolerance. Some kernel implementations might be more lenient and accept an adjustment request even under a circumstance where the above check fails.

Relation to Other Specifications: adj_tim from the TOPPERS 3rd generation kernels

Rationale: When moving the system time forward, capping by a frontier instead of an actual latest arrival time has advantages over other schemes that involve tracking the latest arrival time:

  • Linear-scanning all outstanding timed events to find the latest arrival time would take a linear time.

  • Using a double-ended data structure for an event queue, such as a balanced search tree and double heaps, would increase the runtime cost of maintaining the structure.

Also, the gap between the current time and the frontier is completely in control of the code that calls adjust_time, making the behavior more predictable.

source

unsafe fn exit_task() -> Result<!, ExitTaskError>

Terminate the current task, putting it into the Dormant state.

The kernel makes an implicit call to this function when a task entry point function returns.

Safety

On a successful call, this function destroys the current task’s stack without running any destructors on stack-allocated objects and renders all references pointing to such objects invalid. The caller is responsible for taking this possibility into account and ensuring this doesn’t lead to an undefined behavior.

source

fn park() -> Result<(), ParkError>

Put the current task into the Waiting state until the task’s token is made available by Task::unpark. The token is initially absent when the task is activated.

The token will be consumed when this method returns successfully.

This system service may block. Therefore, calling this method is not allowed in a non-waitable context and will return Err(BadContext).

source

fn park_timeout(timeout: Duration) -> Result<(), ParkTimeoutError>

park with timeout.

This system service may block. Therefore, calling this method is not allowed in a non-waitable context and will return Err(BadContext).

source

fn sleep(duration: Duration) -> Result<(), SleepError>

Block the current task for the specified duration.

Implementors§