From a4f3eabc5584d7c76f1a665fced276ee29f37b0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Wed, 13 Sep 2023 14:37:21 +0200 Subject: [PATCH] fix(task): don't access scheduler from BlockedTaskQueue::wakeup_task MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/scheduler/mod.rs | 14 ++++++++--- src/scheduler/task.rs | 57 +++++++++++++++++++++++-------------------- 2 files changed, 41 insertions(+), 30 deletions(-) diff --git a/src/scheduler/mod.rs b/src/scheduler/mod.rs index 3ff4414b5c..f8dc878794 100644 --- a/src/scheduler/mod.rs +++ b/src/scheduler/mod.rs @@ -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); + } }); } @@ -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() @@ -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() { diff --git a/src/scheduler/task.rs b/src/scheduler/task.rs index a51c9cc7d3..ef48db357e 100644 --- a/src/scheduler/task.rs +++ b/src/scheduler/task.rs @@ -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; @@ -463,31 +464,26 @@ impl BlockedTaskQueue { } fn wakeup_task(task: Rc>) { - { - 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"))] @@ -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>> { let mut first_task = true; let mut cursor = self.list.cursor_front_mut(); @@ -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 @@ -623,7 +620,7 @@ impl BlockedTaskQueue { ); } - break; + return Some(task_ref); } first_task = false; @@ -631,13 +628,14 @@ impl BlockedTaskQueue { } 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>> { // Get the current time. let time = arch::processor::get_timer_ticks(); @@ -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() { @@ -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(); } @@ -689,5 +690,7 @@ impl BlockedTaskQueue { .current() .map_or_else(|| None, |node| node.wakeup_time), ); + + tasks } }