Skip to content

Commit

Permalink
fix(task): don't access scheduler from BlockedTaskQueue::wakeup_task
Browse files Browse the repository at this point in the history
Signed-off-by: Martin Kröning <[email protected]>
  • Loading branch information
mkroening committed Sep 13, 2023
1 parent 905435e commit a4f3eab
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 30 deletions.
14 changes: 11 additions & 3 deletions src/scheduler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,9 @@ impl PerCoreScheduler {
pub fn handle_waiting_tasks(&mut self) {
without_interrupts(|| {
crate::executor::run();
self.blocked_tasks.handle_waiting_tasks();
for task in self.blocked_tasks.handle_waiting_tasks() {
self.ready_queue.push(task);
}
});
}

Expand All @@ -307,7 +309,11 @@ impl PerCoreScheduler {
#[cfg(feature = "smp")]
pub fn custom_wakeup(&mut self, task: TaskHandle) {
if task.get_core_id() == self.core_id {
without_interrupts(|| self.blocked_tasks.custom_wakeup(task));
without_interrupts(|| {
if let Some(task) = self.blocked_tasks.custom_wakeup(task) {
self.ready_queue.push(task);
}
});
} else {
get_scheduler_input(task.get_core_id())
.lock()
Expand Down Expand Up @@ -449,7 +455,9 @@ impl PerCoreScheduler {
let mut input_locked = CoreLocal::get().scheduler_input.lock();

while let Some(task) = input_locked.wakeup_tasks.pop_front() {
self.blocked_tasks.custom_wakeup(task);
if let Some(task) = self.blocked_tasks.custom_wakeup(task) {
self.ready_queue.push(task);
}
}

while let Some(new_task) = input_locked.new_tasks.pop_front() {
Expand Down
57 changes: 30 additions & 27 deletions src/scheduler/task.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use alloc::boxed::Box;
use alloc::collections::{LinkedList, VecDeque};
use alloc::rc::Rc;
use alloc::vec::Vec;
use core::cell::RefCell;
use core::cmp::Ordering;
use core::fmt;
Expand Down Expand Up @@ -463,31 +464,26 @@ impl BlockedTaskQueue {
}

fn wakeup_task(task: Rc<RefCell<Task>>) {
{
let mut borrowed = task.borrow_mut();
debug!(
"Waking up task {} on core {}",
borrowed.id, borrowed.core_id
);

assert!(
borrowed.core_id == core_id(),
"Try to wake up task {} on the wrong core {} != {}",
borrowed.id,
borrowed.core_id,
core_id()
);
let mut borrowed = task.borrow_mut();
debug!(
"Waking up task {} on core {}",
borrowed.id, borrowed.core_id
);

assert!(
borrowed.status == TaskStatus::Blocked,
"Trying to wake up task {} which is not blocked",
borrowed.id
);
borrowed.status = TaskStatus::Ready;
}
assert!(
borrowed.core_id == core_id(),
"Try to wake up task {} on the wrong core {} != {}",
borrowed.id,
borrowed.core_id,
core_id()
);

// Add the task to the ready queue.
core_scheduler().ready_queue.push(task);
assert!(
borrowed.status == TaskStatus::Blocked,
"Trying to wake up task {} which is not blocked",
borrowed.id
);
borrowed.status = TaskStatus::Ready;
}

#[cfg(any(feature = "tcp", feature = "udp"))]
Expand Down Expand Up @@ -574,7 +570,7 @@ impl BlockedTaskQueue {
}

/// Manually wake up a blocked task.
pub fn custom_wakeup(&mut self, task: TaskHandle) {
pub fn custom_wakeup(&mut self, task: TaskHandle) -> Option<Rc<RefCell<Task>>> {
let mut first_task = true;
let mut cursor = self.list.cursor_front_mut();

Expand All @@ -589,7 +585,8 @@ impl BlockedTaskQueue {
while let Some(node) = cursor.current() {
if node.task.borrow().id == task.get_id() {
// Remove it from the list of blocked tasks and wake it up.
Self::wakeup_task(node.task.clone());
let task_ref = node.task.clone();
Self::wakeup_task(task_ref.clone());
cursor.remove_current();

// If this is the first task, adjust the One-Shot Timer to fire at the
Expand Down Expand Up @@ -623,21 +620,22 @@ impl BlockedTaskQueue {
);
}

break;
return Some(task_ref);
}

first_task = false;
cursor.move_next();
}

error!("Could not wakeup {task:?}");
None
}

/// Wakes up all tasks whose wakeup time has elapsed.
///
/// Should be called by the One-Shot Timer interrupt handler when the wakeup time for
/// at least one task has elapsed.
pub fn handle_waiting_tasks(&mut self) {
pub fn handle_waiting_tasks(&mut self) -> Vec<Rc<RefCell<Task>>> {
// Get the current time.
let time = arch::processor::get_timer_ticks();

Expand All @@ -650,6 +648,8 @@ impl BlockedTaskQueue {
}
}

let mut tasks = vec![];

// Loop through all blocked tasks.
let mut cursor = self.list.cursor_front_mut();
while let Some(node) = cursor.current() {
Expand All @@ -662,6 +662,7 @@ impl BlockedTaskQueue {

// Otherwise, this task has elapsed, so remove it from the list and wake it up.
Self::wakeup_task(node.task.clone());
tasks.push(node.task.clone());
cursor.remove_current();
}

Expand Down Expand Up @@ -689,5 +690,7 @@ impl BlockedTaskQueue {
.current()
.map_or_else(|| None, |node| node.wakeup_time),
);

tasks
}
}

0 comments on commit a4f3eab

Please sign in to comment.