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§
type DebugPrinter: Debug + Send + Sync
Required Methods§
sourcefn debug() -> <Self as Kernel>::DebugPrinter
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.
sourcefn acquire_cpu_lock() -> Result<(), CpuLockError>
fn acquire_cpu_lock() -> Result<(), CpuLockError>
Activate CPU Lock.
Returns BadContext
if CPU Lock is already active.
sourceunsafe fn release_cpu_lock() -> Result<(), CpuLockError>
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.
sourcefn has_cpu_lock() -> bool
fn has_cpu_lock() -> bool
Return a flag indicating whether CPU Lock is currently active.
sourcefn boost_priority() -> Result<(), BoostPriorityError>where
Self: KernelBoostPriority,
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.
sourceunsafe fn unboost_priority() -> Result<(), BoostPriorityError>
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.
sourcefn is_priority_boost_active() -> bool
fn is_priority_boost_active() -> bool
Return a flag indicating whether Priority Boost is currently active.
sourcefn is_task_context() -> bool
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
()
.
sourcefn is_interrupt_context() -> bool
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
()
.
sourcefn is_boot_complete() -> bool
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.
sourcefn set_time(time: Time) -> Result<(), TimeError>
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.
sourcefn time() -> Result<Time, TimeError>where
Self: KernelTime,
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.
sourcefn time_user_headroom() -> Durationwhere
Self: KernelAdjustTime,
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.
sourcefn adjust_time(delta: Duration) -> Result<(), AdjustTimeError>where
Self: KernelAdjustTime,
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 not0
but a somewhat smaller value. The consequence is thatdelta
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.
sourceunsafe fn exit_task() -> Result<!, ExitTaskError>
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.
sourcefn park() -> Result<(), ParkError>
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)
.
sourcefn park_timeout(timeout: Duration) -> Result<(), ParkTimeoutError>
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)
.