Skip to content

Commit

Permalink
Panic the task or ISR upon trying to block when it must not.
Browse files Browse the repository at this point in the history
  • Loading branch information
zyma98 committed Oct 9, 2024
1 parent f546d18 commit b3af165
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 18 deletions.
16 changes: 13 additions & 3 deletions src/sync/mailbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
interrupt::context_switch,
schedule::{current, scheduler::Scheduler},
task::{Task, TaskState},
time, unrecoverable,
time,
};
use alloc::sync::Arc;
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
Expand Down Expand Up @@ -178,7 +178,12 @@ impl Mailbox {
///
/// NOTE: *must not* call this method in ISR context.
pub fn wait(&self) {
unrecoverable::die_if_in_isr();
// The application logic must have gone terribly wrong if the task
// tries to block when the scheduler is suspended or if an ISR
// tries to block. In this case, panic the task or ISR.
if Scheduler::is_suspended() || current::is_in_isr_context() {
panic!();
}

let mut should_block = true;

Expand Down Expand Up @@ -230,7 +235,12 @@ impl Mailbox {
///
/// NOTE: *must not* call this method in ISR context.
pub fn wait_until_timeout(&self, timeout_ms: u32) -> bool {
unrecoverable::die_if_in_isr();
// The application logic must have gone terribly wrong if the task
// tries to block when the scheduler is suspended or if an ISR
// tries to block. In this case, panic the task or ISR.
if Scheduler::is_suspended() || current::is_in_isr_context() {
panic!();
}

let mut should_block = true;

Expand Down
28 changes: 21 additions & 7 deletions src/sync/wait_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use crate::{
interrupt::context_switch,
schedule::{current, scheduler::Scheduler},
task::{TaskListAdapter, TaskListInterfaces, TaskState},
unrecoverable,
};
use core::sync::atomic::{AtomicUsize, Ordering};
use intrusive_collections::LinkedList;
Expand Down Expand Up @@ -97,8 +96,6 @@ impl WaitQueue {
#[inline]
#[allow(unused)]
pub(super) fn wait(&self) {
unrecoverable::die_if_in_isr();

add_cur_task_to_block_queue(self);

// We have put the current task to the wait queue.
Expand All @@ -108,6 +105,13 @@ impl WaitQueue {
// Outline the logic to reduce the stack frame size of `.wait()`.
#[inline(never)]
fn add_cur_task_to_block_queue(wq: &WaitQueue) {
// The application logic must have gone terribly wrong if the task
// tries to block when the scheduler is suspended or if an ISR
// tries to block. In this case, panic the task or ISR.
if Scheduler::is_suspended() || current::is_in_isr_context() {
panic!();
}

// Should always grant full access to a task.
wq.inner.with_suspended_scheduler(|queue, sched_guard| {
queue.must_with_full_access(|full_access| {
Expand Down Expand Up @@ -140,8 +144,6 @@ impl WaitQueue {
where
F: FnMut() -> Option<R>,
{
unrecoverable::die_if_in_isr();

// Keep blocking until the predicate is satisfied.
loop {
let res = add_cur_task_to_block_queue_with_condition(self, &mut condition);
Expand All @@ -165,6 +167,13 @@ impl WaitQueue {
where
F: FnMut() -> Option<R>,
{
// The application logic must have gone terribly wrong if the task
// tries to block when the scheduler is suspended or if an ISR
// tries to block. In this case, panic the task or ISR.
if Scheduler::is_suspended() || current::is_in_isr_context() {
panic!();
}

// Should always grant full access to a task.
wq.inner.with_suspended_scheduler(|queue, sched_guard| {
queue.must_with_full_access(|full_access| {
Expand Down Expand Up @@ -216,8 +225,6 @@ impl WaitQueue {
G: UnlockableGuard<'a, LockType = L>,
L: Lockable<GuardType<'a> = G> + 'a,
{
unrecoverable::die_if_in_isr();

// Keep blocking until the predicate is satisfied.
loop {
let res = add_cur_task_to_block_queue_and_unlock(self, guard, &mut condition);
Expand Down Expand Up @@ -248,6 +255,13 @@ impl WaitQueue {
G: UnlockableGuard<'a, LockType = L>,
L: Lockable<GuardType<'a> = G> + 'a,
{
// The application logic must have gone terribly wrong if the task
// tries to block when the scheduler is suspended or if an ISR
// tries to block. In this case, panic the task or ISR.
if Scheduler::is_suspended() || current::is_in_isr_context() {
panic!();
}

// Should always grant full access to a task.
wq.inner.with_suspended_scheduler(|queue, sched_guard| {
queue.must_with_full_access(|full_access| {
Expand Down
7 changes: 7 additions & 0 deletions src/time/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,13 @@ fn sleep_ms_unchecked(ms: u32) {
// Outline the logic to reduce the stack frame size of `sleep_ms`.
#[inline(never)]
fn add_cur_task_to_sleep_queue(wake_at_tick: u32) {
// The application logic must have gone terribly wrong if the task
// tries to block when the scheduler is suspended or if an ISR
// tries to block. In this case, panic the task or ISR.
if Scheduler::is_suspended() || current::is_in_isr_context() {
panic!();
}

current::with_cur_task_arc(|cur_task| {
cur_task.set_state(TaskState::Blocked);
add_task_to_sleep_queue(cur_task, wake_at_tick);
Expand Down
8 changes: 0 additions & 8 deletions src/unrecoverable/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use crate::schedule::current;

pub trait Lethal {
type T;
fn unwrap_or_die(self) -> Self::T;
Expand Down Expand Up @@ -36,9 +34,3 @@ where
die()
}
}

pub fn die_if_in_isr() {
if current::is_in_isr_context() {
die();
}
}

0 comments on commit b3af165

Please sign in to comment.