Skip to content

Commit e423225

Browse files
committed
Merge branch '✨-context-queries' into 🦆
2 parents 483a16f + a284732 commit e423225

File tree

16 files changed

+274
-11
lines changed

16 files changed

+274
-11
lines changed

src/r3/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ TODO
2525
### Added
2626

2727
- Bindings (`Bind`), a static storage with runtime initialization and configuration-time borrow checking. They can be used, for example, to provide a task or timer callback with a state data storage that can be mutably borrowed and persists across invocations.
28+
- `Kernel::{is_task_context, is_interrupt_context, is_boot_complete}`
2829

2930
### Fixed
3031

src/r3_core/src/kernel/global.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,35 @@ pub trait Kernel: private::Sealed {
128128
/// [Priority Boost]: crate#system-states
129129
fn is_priority_boost_active() -> bool;
130130

131+
/// Return a flag indicating whether the calling context is a
132+
/// [task context][].
133+
///
134+
/// This is equivalent to [`is_boot_complete`][]`() &&
135+
/// !`[`is_interrupt_context`][]`()`.
136+
///
137+
/// [task context]: crate#contexts
138+
/// [`is_boot_complete`]: Self::is_boot_complete
139+
/// [`is_interrupt_context`]: Self::is_interrupt_context
140+
fn is_task_context() -> bool;
141+
142+
/// Return a flag indicating whether the calling context is an
143+
/// [interrupt context][].
144+
///
145+
/// This is equivalent to [`is_boot_complete`][]`() &&
146+
/// !`[`is_task_context`][]`()`.
147+
///
148+
/// [interrupt context]: crate#contexts
149+
/// [`is_boot_complete`]: Self::is_boot_complete
150+
/// [`is_task_context`]: Self::is_task_context
151+
fn is_interrupt_context() -> bool;
152+
153+
/// Return a flag indicating whether [the boot phase][] is complete, i.e.,
154+
/// all startup hooks completed execution, and the kernel started
155+
/// scheduling tasks and taking interrupts.
156+
///
157+
/// [the boot phase]: crate#threads
158+
fn is_boot_complete() -> bool;
159+
131160
/// Set the current [system time].
132161
///
133162
/// This method *does not change* the relative arrival times of outstanding
@@ -381,6 +410,21 @@ impl<T: raw::KernelBase> Kernel for T {
381410
<T as raw::KernelBase>::raw_is_priority_boost_active()
382411
}
383412

413+
#[inline]
414+
fn is_task_context() -> bool {
415+
<T as raw::KernelBase>::raw_is_task_context()
416+
}
417+
418+
#[inline]
419+
fn is_interrupt_context() -> bool {
420+
<T as raw::KernelBase>::raw_is_interrupt_context()
421+
}
422+
423+
#[inline]
424+
fn is_boot_complete() -> bool {
425+
<T as raw::KernelBase>::raw_is_boot_complete()
426+
}
427+
384428
#[inline]
385429
fn set_time(time: Time) -> Result<(), TimeError> {
386430
<T as raw::KernelBase>::raw_set_time(time)

src/r3_core/src/kernel/raw.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,21 @@ pub unsafe trait KernelBase: fmt::Debug + Copy + Sized + 'static {
8181
/// [1]: crate::kernel::Kernel::is_priority_boost_active
8282
fn raw_is_priority_boost_active() -> bool;
8383

84+
/// Implements [`Kernel::is_task_context`][1].
85+
///
86+
/// [1]: crate::kernel::Kernel::is_task_context
87+
fn raw_is_task_context() -> bool;
88+
89+
/// Implements [`Kernel::is_interrupt_context`][1].
90+
///
91+
/// [1]: crate::kernel::Kernel::is_interrupt_context
92+
fn raw_is_interrupt_context() -> bool;
93+
94+
/// Implements [`Kernel::is_boot_complete`][1].
95+
///
96+
/// [1]: crate::kernel::Kernel::is_boot_complete
97+
fn raw_is_boot_complete() -> bool;
98+
8499
/// Implements [`Kernel::set_time`][1].
85100
///
86101
/// [1]: crate::kernel::Kernel::set_time

src/r3_kernel/src/lib.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,21 @@ unsafe impl<Traits: KernelTraits> raw::KernelBase for System<Traits> {
207207
false
208208
}
209209

210+
#[inline]
211+
fn raw_is_task_context() -> bool {
212+
Traits::is_task_context()
213+
}
214+
215+
#[inline]
216+
fn raw_is_interrupt_context() -> bool {
217+
Traits::is_interrupt_context()
218+
}
219+
220+
#[inline]
221+
fn raw_is_boot_complete() -> bool {
222+
Traits::is_scheduler_active()
223+
}
224+
210225
#[cfg_attr(not(feature = "inline_syscall"), inline(never))]
211226
fn raw_set_time(time: Time) -> Result<(), r3_core::kernel::TimeError> {
212227
timeout::set_system_time::<Traits>(time)
@@ -503,10 +518,20 @@ pub unsafe trait PortThreading: KernelCfg1 + KernelStatic<System<Self>> {
503518
fn is_cpu_lock_active() -> bool;
504519

505520
/// Return a flag indicating whether the current context is
506-
/// [an task context].
521+
/// [a task context].
507522
///
508-
/// [an task context]: crate#contexts
523+
/// [a task context]: r3_core#contexts
509524
fn is_task_context() -> bool;
525+
526+
/// Return a flag indicating whether the current context is
527+
/// [an interrupt context].
528+
///
529+
/// [an interrupt context]: r3_core#contexts
530+
fn is_interrupt_context() -> bool;
531+
532+
/// Return a flag indicating whether [`Self::dispatch_first_task`][] was
533+
/// called.
534+
fn is_scheduler_active() -> bool;
510535
}
511536

512537
/// Implemented by a port. This trait contains items related to controlling

src/r3_port_arm/src/threading/cfg.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,16 @@ macro_rules! use_port {
159159
fn is_task_context() -> bool {
160160
<Self as PortInstance>::port_state().is_task_context::<Self>()
161161
}
162+
163+
#[inline(always)]
164+
fn is_interrupt_context() -> bool {
165+
<Self as PortInstance>::port_state().is_interrupt_context::<Self>()
166+
}
167+
168+
#[inline(always)]
169+
fn is_scheduler_active() -> bool {
170+
<Self as PortInstance>::port_state().is_scheduler_active::<Self>()
171+
}
162172
}
163173
}
164174

src/r3_port_arm/src/threading/imp.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ impl State {
9191
mov sp, r0
9292
9393
# Save the stack pointer for later use
94+
# [tag:arm_main_stack_assigned_in_dft]
9495
str r0, [r1]
9596
9697
b {push_second_level_state_and_dispatch}.dispatch
@@ -442,6 +443,18 @@ impl State {
442443
(cpsr & 0xf) == 0xf // System mode
443444
}
444445

446+
#[inline]
447+
pub fn is_interrupt_context<Traits: PortInstance>(&self) -> bool {
448+
self.is_scheduler_active::<Traits>() && !self.is_task_context::<Traits>()
449+
}
450+
451+
#[inline]
452+
pub fn is_scheduler_active<Traits: PortInstance>(&self) -> bool {
453+
// `main_stack` is assigned by `dispatch_first_task`
454+
// [ref:arm_main_stack_assigned_in_dft]
455+
unsafe { *self.main_stack.get() != 0 }
456+
}
457+
445458
/// Implements [`crate::EntryPoint::irq_entry`]
446459
#[naked]
447460
pub unsafe extern "C" fn irq_entry<Traits: PortInstance>() -> ! {

src/r3_port_arm_m/src/threading/cfg.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,16 @@ macro_rules! use_port {
189189
fn is_task_context() -> bool {
190190
port_state().is_task_context::<Self>()
191191
}
192+
193+
#[inline(always)]
194+
fn is_interrupt_context() -> bool {
195+
port_state().is_interrupt_context::<Self>()
196+
}
197+
198+
#[inline(always)]
199+
fn is_scheduler_active() -> bool {
200+
port_state().is_scheduler_active::<Self>()
201+
}
192202
}
193203

194204
unsafe impl PortInterrupts for $Traits {

src/r3_port_arm_m/src/threading/imp.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,6 @@ impl State {
8383
pub unsafe fn port_boot<Traits: PortInstance>(&self) -> ! {
8484
unsafe { self.enter_cpu_lock::<Traits>() };
8585

86-
unsafe { *self.running_task_ptr.get() = Traits::state().running_task_ptr() as *mut () };
87-
8886
// Claim the ownership of `Peripherals`
8987
let mut peripherals = unsafe { cortex_m::Peripherals::steal() };
9088

@@ -107,6 +105,9 @@ impl State {
107105

108106
#[inline(always)]
109107
pub unsafe fn dispatch_first_task<Traits: PortInstance>(&'static self) -> ! {
108+
// [tag:running_task_ptr_set_in_dft]
109+
unsafe { *self.running_task_ptr.get() = Traits::state().running_task_ptr() as *mut () };
110+
110111
// Pend PendSV
111112
cortex_m::peripheral::SCB::set_pendsv();
112113

@@ -552,6 +553,27 @@ impl State {
552553
cortex_m::register::control::read().spsel() == cortex_m::register::control::Spsel::Psp
553554
}
554555

556+
#[inline]
557+
pub fn is_interrupt_context<Traits: PortInstance>(&self) -> bool {
558+
// `IPSR.Exception != 0`
559+
unsafe {
560+
let ipsr: u32;
561+
pp_asm!(
562+
"mrs {}, ipsr",
563+
out(reg) ipsr,
564+
options(nomem, preserves_flags, nostack),
565+
);
566+
(ipsr & ((1u32 << 9) - 1)) != 0
567+
}
568+
}
569+
570+
#[inline]
571+
pub fn is_scheduler_active<Traits: PortInstance>(&self) -> bool {
572+
// `runnin_task_ptr` is assigned by `dispatch_first_task`
573+
// [ref:running_task_ptr_set_in_dft]
574+
unsafe { !(*self.running_task_ptr.get()).is_null() }
575+
}
576+
555577
pub fn set_interrupt_line_priority<Traits: PortInstance>(
556578
&'static self,
557579
num: InterruptNum,

src/r3_port_riscv/src/threading/cfg.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,16 @@ macro_rules! use_port {
181181
fn is_task_context() -> bool {
182182
PORT_STATE.is_task_context::<Self>()
183183
}
184+
185+
#[inline(always)]
186+
fn is_interrupt_context() -> bool {
187+
PORT_STATE.is_interrupt_context::<Self>()
188+
}
189+
190+
#[inline(always)]
191+
fn is_scheduler_active() -> bool {
192+
PORT_STATE.is_scheduler_active::<Self>()
193+
}
184194
}
185195

186196
unsafe impl PortInterrupts for $Traits {

src/r3_port_riscv/src/threading/imp.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ impl State {
269269
pp_asm!("
270270
" crate::threading::imp::asm_inc::define_load_store!() "
271271
# Save the stack pointer for later use
272+
# [tag:riscv_main_stack_assigned_in_dft]
272273
STORE sp, ({MAIN_STACK}), a0
273274
274275
# `xstatus.XPIE` will be `1` all the time except in a software
@@ -962,10 +963,23 @@ impl State {
962963
(Traits::Csr::xstatus().read() & Traits::Csr::XSTATUS_XIE) == 0
963964
}
964965

966+
#[inline]
965967
pub fn is_task_context<Traits: PortInstance>(&self) -> bool {
966968
unsafe { INTERRUPT_NESTING < 0 }
967969
}
968970

971+
#[inline]
972+
pub fn is_interrupt_context<Traits: PortInstance>(&self) -> bool {
973+
self.is_scheduler_active::<Traits>() && !self.is_task_context::<Traits>()
974+
}
975+
976+
#[inline]
977+
pub fn is_scheduler_active<Traits: PortInstance>(&self) -> bool {
978+
// `MAIN_STACK` is assigned by `dispatch_first_task`
979+
// [ref:riscv_main_stack_assigned_in_dft]
980+
unsafe { MAIN_STACK != 0 }
981+
}
982+
969983
pub fn set_interrupt_line_priority<Traits: PortInstance>(
970984
&'static self,
971985
num: InterruptNum,

0 commit comments

Comments
 (0)