From 9e3387e957d263e5843b78fadb35c07bbf7ff669 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Mon, 25 Nov 2024 09:38:19 +0300 Subject: [PATCH 01/50] Implement cooperative scheduler --- src/task_manager.rs | 220 ++++++++++++++++++-------------------------- 1 file changed, 87 insertions(+), 133 deletions(-) diff --git a/src/task_manager.rs b/src/task_manager.rs index 8deafa5..8d03fd3 100644 --- a/src/task_manager.rs +++ b/src/task_manager.rs @@ -1,167 +1,121 @@ extern crate alloc; -use alloc::vec::Vec; -use core::future::Future; -use core::pin::Pin; -use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; +// A double-ended queue implemented with a growable ring buffer +use alloc::collections::VecDeque; +use core::array; +use crate::context; -/// The number of tasks can fit into a type usize. -pub type TaskNumberType = usize; - -// TODO: rewrite with cfg! -#[cfg(not(feature = "c-library"))] -/// Type of setup function, that is called once at the beginning of task. -type TaskSetupFunctionType = fn() -> (); -#[cfg(feature = "c-library")] -/// Type of setup function, that is called once at the beginning of task. -type TaskSetupFunctionType = extern "C" fn() -> (); #[cfg(not(feature = "c-library"))] -/// Type of loop function, that is called in loop. -type TaskLoopFunctionType = fn() -> (); +type FunctionType = fn(); #[cfg(feature = "c-library")] +type FunctionType = extern "C" fn(); + /// Type of loop function, that is called in loop. -type TaskLoopFunctionType = extern "C" fn() -> (); -#[cfg(not(feature = "c-library"))] -/// Type of condition function for stopping loop function execution. -type TaskStopConditionFunctionType = fn() -> bool; -#[cfg(feature = "c-library")] -/// Type of condition function for stopping loop function execution. -type TaskStopConditionFunctionType = extern "C" fn() -> bool; - -#[repr(C)] -/// Task representation for task manager. -struct Task { - /// Setup function, that is called once at the beginning of task. - setup_fn: TaskSetupFunctionType, - /// Loop function, that is called in loop. - loop_fn: TaskLoopFunctionType, - /// Condition function for stopping loop function execution. - stop_condition_fn: TaskStopConditionFunctionType, -} +type TaskLoopFunctionType = FunctionType; +type TaskPriorityType = usize; + +const NUM_PRIORITIES: usize = 11; -#[repr(C)] -/// Future shell for task for execution. -struct FutureTask { - /// Task to execute in task manager. - task: Task, - /// Marker for setup function completion. - is_setup_completed: bool, +enum TaskStatusType { + Ready, + Sleep, + WokeUp, + Terminated, } -impl Future for FutureTask { - type Output = (); - - fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - let mut array: [usize; 8] = core::array::from_fn(|i| i); - array[0] = 5; - if (self.task.stop_condition_fn)() { - Poll::Ready(()) - } else { - if !self.is_setup_completed { - (self.task.setup_fn)(); - self.is_setup_completed = true; - } else { - (self.task.loop_fn)(); - } - Poll::Pending - } - } +pub struct Task { + /// Loop function, that is called in loop. + loop_fn: TaskLoopFunctionType, + status: TaskStatusType, + priority: TaskPriorityType, } -/// Creates simple task waker. May be more difficult in perspective. -fn task_waker() -> Waker { - fn raw_clone(_: *const ()) -> RawWaker { - RawWaker::new(core::ptr::null::<()>(), &NOOP_WAKER_VTABLE) +impl Task { + pub fn new(loop_fn: TaskLoopFunctionType, priority: TaskPriorityType) -> Self { + Task {loop_fn, status: TaskStatusType::Ready, priority} } - fn raw_wake(_: *const ()) {} - - fn raw_wake_by_ref(_: *const ()) {} - - fn raw_drop(_: *const ()) {} - - static NOOP_WAKER_VTABLE: RawWakerVTable = - RawWakerVTable::new(raw_clone, raw_wake, raw_wake_by_ref, raw_drop); - - let raw_waker = RawWaker::new(core::ptr::null::<()>(), &NOOP_WAKER_VTABLE); - unsafe { Waker::from_raw(raw_waker) } + fn update_status(&mut self, new_status: TaskStatusType) { + self.status = new_status; + } } -#[repr(C)] -/// Task manager representation. Based on round-robin scheduling without priorities. -pub struct TaskManager { - /// Vector of tasks to execute. - tasks: Vec, - /// Index of task, that should be executed. - task_to_execute_index: TaskNumberType, +struct TaskManager { + priority_array: [VecDeque; NUM_PRIORITIES], } -/// Operating system task manager. -static mut TASK_MANAGER: TaskManager = TaskManager::new(); - impl TaskManager { - /// Creates new task manager. - const fn new() -> TaskManager { + fn new() -> TaskManager { TaskManager { - tasks: Vec::new(), - task_to_execute_index: 0, + priority_array: array::from_fn(|_| VecDeque::new()), + } + } + + fn pop_from_queue(&mut self, priority: TaskPriorityType) -> Option { + self.priority_array[priority].pop_front() + } + + fn push_to_queue(&mut self, task: Task) { + self.priority_array[task.priority].push_back(task); + } + + fn is_queue_empty(&self, priority: TaskPriorityType) -> bool { + self.priority_array[priority].is_empty() + } + + fn pop_next_task(&mut self) -> Option { + for priority in (0 ..NUM_PRIORITIES).rev(){ + if self.is_queue_empty(priority) { continue; } + let next_task = self.pop_from_queue(priority); + return next_task; } + None } - /// Add task to task manager. You should pass setup, loop and condition functions. pub fn add_task( - setup_fn: TaskSetupFunctionType, + &mut self, loop_fn: TaskLoopFunctionType, - stop_condition_fn: TaskStopConditionFunctionType, - ) { - let task = Task { - setup_fn, - loop_fn, - stop_condition_fn, - }; - let future_task = FutureTask { - task, - is_setup_completed: false, - }; - unsafe { - TASK_MANAGER.tasks.push(future_task); + priority: TaskPriorityType, + ) -> Result<(), &'static str> { + if (priority >= NUM_PRIORITIES) { + return Err("Invalid priority value"); } + let new_task = Task::new(loop_fn, priority); + self.push_to_queue(new_task); + Ok(()) } - /// One step of task manager's work. - // TODO: Support priorities. - // TODO: Delete tasks from task vector if they are pending? - fn task_manager_step() { - if unsafe { !TASK_MANAGER.tasks.is_empty() } { - let waker = task_waker(); - - let task = unsafe { &mut TASK_MANAGER.tasks[TASK_MANAGER.task_to_execute_index] }; - let mut task_future_pin = Pin::new(task); - let _ = task_future_pin - .as_mut() - .poll(&mut Context::from_waker(&waker)); - - unsafe { - if TASK_MANAGER.task_to_execute_index + 1 < TASK_MANAGER.tasks.len() { - TASK_MANAGER.task_to_execute_index += 1; - } else { - TASK_MANAGER.task_to_execute_index = 0; - } - } - } + pub fn yield_to_scheduler(&self, mut task: Task, new_status: TaskStatusType) { + save_context(&mut task); // WIP + task.update_status(new_status); } - /// Starts task manager work. - pub fn start_task_manager() -> ! { - loop { - TaskManager::task_manager_step(); - } + pub fn wake_up(&self, task: &mut Task) { + load_context(task); // WIP + task.update_status(TaskStatusType::Ready); } - /// Starts task manager work. Returns after 1000 steps only for testing task_manager_step. - pub fn test_start_task_manager() { - for _n in 1..=1000 { - TaskManager::task_manager_step(); + pub fn start_task_manager(&mut self) { + loop { + // if task is None, array is empty, waiting for new tasks in system + let Some(mut task) = self.pop_next_task(); + match task.status { + TaskStatusType::Ready => { + (task.loop_fn)(); + if task.status = TaskStatusType::Sleep { + self.push_to_queue(task); + } // deleting task is not adding it back to the queue + } + TaskStatusType::Sleep => { + self.push_to_queue(task); + } + TaskStatusType::WokeUp => { + self.wake_up(&mut task); + task.status = TaskStatusType::Ready; + self.push_to_queue(task); + } + TaskStatusType::Terminated => {} + } } } } From b822163031d3d6b2fc60873b6023e3d4f2449709 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Mon, 25 Nov 2024 11:14:21 +0300 Subject: [PATCH 02/50] Add template for context switcher --- src/context_switcher.rs | 67 +++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/task_manager.rs | 10 +++--- 3 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 src/context_switcher.rs diff --git a/src/context_switcher.rs b/src/context_switcher.rs new file mode 100644 index 0000000..2a71753 --- /dev/null +++ b/src/context_switcher.rs @@ -0,0 +1,67 @@ +extern crate alloc; + +use alloc::boxed::Box; +use crate::task_manager::Task; + +enum Architecture { + Mips64, + RiscV32, + Xtensa, +} + +fn create_switcher() -> Box { + #[cfg(target_arch = "mips64")] + return Box::new(Mips64Switcher); + + #[cfg(target_arch = "riscv32")] + return Box::new(RiscV32Switcher); + + #[cfg(target_arch = "xtensa")] + return Box::new(XtensaSwitcher); + + #[cfg(not(any(target_arch = "mips64", target_arch = "riscv32", target_arch = "xtensa")))] + return Box::new(Mips64Switcher); +} + +pub(crate) struct ContextSwitcher { + switcher: Box, +} + +impl ContextSwitcher { + pub(crate) fn new() -> Self { + ContextSwitcher { + switcher: create_switcher(), + } + } + pub(crate) fn save_context(&self, task: &Task) { + self.switcher.save_context(task); + } + + pub(crate) fn load_context(&self, task: &Task) { + self.switcher.load_context(task); + } + +} + +trait SwitcherMethods { + fn save_context(task: &Task); + fn load_context(task: &Task); +} + +struct Mips64Switcher; +impl SwitcherMethods for Mips64Switcher { + fn save_context(task: &Task) {} + fn load_context(task: &Task) {} +} + +struct RiscV32Switcher; +impl SwitcherMethods for RiscV32Switcher { + fn save_context(task: &Task) {} + fn load_context(task: &Task) {} +} + +struct XtensaSwitcher; +impl SwitcherMethods for XtensaSwitcher { + fn save_context(task: &Task) {} + fn load_context(task: &Task) {} +} diff --git a/src/lib.rs b/src/lib.rs index d6ec545..083fcdd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,7 @@ use ports::PortTrait; #[cfg(feature = "c-library")] pub mod c_api; pub mod task_manager; +mod context_switcher; pub mod timer; #[cfg(any(target_arch = "riscv32", target_arch = "xtensa"))] #[cfg(feature = "network")] diff --git a/src/task_manager.rs b/src/task_manager.rs index 8d03fd3..ee4e2c6 100644 --- a/src/task_manager.rs +++ b/src/task_manager.rs @@ -3,7 +3,7 @@ extern crate alloc; // A double-ended queue implemented with a growable ring buffer use alloc::collections::VecDeque; use core::array; -use crate::context; +use crate::context_switcher::ContextSwitcher; #[cfg(not(feature = "c-library"))] type FunctionType = fn(); @@ -42,12 +42,14 @@ impl Task { struct TaskManager { priority_array: [VecDeque; NUM_PRIORITIES], + switcher: ContextSwitcher, } impl TaskManager { fn new() -> TaskManager { TaskManager { priority_array: array::from_fn(|_| VecDeque::new()), + switcher: ContextSwitcher::new(), } } @@ -77,7 +79,7 @@ impl TaskManager { loop_fn: TaskLoopFunctionType, priority: TaskPriorityType, ) -> Result<(), &'static str> { - if (priority >= NUM_PRIORITIES) { + if priority >= NUM_PRIORITIES { return Err("Invalid priority value"); } let new_task = Task::new(loop_fn, priority); @@ -86,12 +88,12 @@ impl TaskManager { } pub fn yield_to_scheduler(&self, mut task: Task, new_status: TaskStatusType) { - save_context(&mut task); // WIP + self.switcher.save_context(&mut task); task.update_status(new_status); } pub fn wake_up(&self, task: &mut Task) { - load_context(task); // WIP + self.switcher.load_context(task); task.update_status(TaskStatusType::Ready); } From 73ee05358d7f241bc2419c9e75e41741ff66f9ac Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Mon, 25 Nov 2024 11:23:06 +0300 Subject: [PATCH 03/50] Remove excess type FunctionType --- src/task_manager.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/task_manager.rs b/src/task_manager.rs index ee4e2c6..0d843df 100644 --- a/src/task_manager.rs +++ b/src/task_manager.rs @@ -5,13 +5,12 @@ use alloc::collections::VecDeque; use core::array; use crate::context_switcher::ContextSwitcher; +/// Type of loop function, that is called in loop. #[cfg(not(feature = "c-library"))] -type FunctionType = fn(); +type TaskLoopFunctionType = fn(); #[cfg(feature = "c-library")] -type FunctionType = extern "C" fn(); +type TaskLoopFunctionType = extern "C" fn(); -/// Type of loop function, that is called in loop. -type TaskLoopFunctionType = FunctionType; type TaskPriorityType = usize; const NUM_PRIORITIES: usize = 11; From 3c873cb09fd9f14c7f1856725b8e625915216715 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Fri, 29 Nov 2024 07:24:27 +0300 Subject: [PATCH 04/50] Add task id --- src/task_manager.rs | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/task_manager.rs b/src/task_manager.rs index 0d843df..34f2e96 100644 --- a/src/task_manager.rs +++ b/src/task_manager.rs @@ -10,7 +10,7 @@ use crate::context_switcher::ContextSwitcher; type TaskLoopFunctionType = fn(); #[cfg(feature = "c-library")] type TaskLoopFunctionType = extern "C" fn(); - +type TaskIdType = usize; type TaskPriorityType = usize; const NUM_PRIORITIES: usize = 11; @@ -23,35 +23,38 @@ enum TaskStatusType { } pub struct Task { + id: TaskIdType, /// Loop function, that is called in loop. loop_fn: TaskLoopFunctionType, status: TaskStatusType, priority: TaskPriorityType, } -impl Task { - pub fn new(loop_fn: TaskLoopFunctionType, priority: TaskPriorityType) -> Self { - Task {loop_fn, status: TaskStatusType::Ready, priority} - } - - fn update_status(&mut self, new_status: TaskStatusType) { - self.status = new_status; - } -} - struct TaskManager { priority_array: [VecDeque; NUM_PRIORITIES], switcher: ContextSwitcher, + next_task_id: TaskIdType, } impl TaskManager { - fn new() -> TaskManager { + fn new() -> Self { TaskManager { priority_array: array::from_fn(|_| VecDeque::new()), switcher: ContextSwitcher::new(), + next_task_id: 0, } } + fn create_task(&mut self, loop_fn: TaskLoopFunctionType, priority: TaskPriorityType) -> Task { + self.next_task_id += 1; + let id = self.next_task_id; + Task {id, loop_fn, status: TaskStatusType::Ready, priority} + } + + fn update_status(task: &mut Task, new_status: TaskStatusType) { + task.status = new_status; + } + fn pop_from_queue(&mut self, priority: TaskPriorityType) -> Option { self.priority_array[priority].pop_front() } @@ -81,14 +84,14 @@ impl TaskManager { if priority >= NUM_PRIORITIES { return Err("Invalid priority value"); } - let new_task = Task::new(loop_fn, priority); + let new_task = self.create_task(loop_fn, priority); self.push_to_queue(new_task); Ok(()) } pub fn yield_to_scheduler(&self, mut task: Task, new_status: TaskStatusType) { self.switcher.save_context(&mut task); - task.update_status(new_status); + self.update_status(&mut task, new_status); } pub fn wake_up(&self, task: &mut Task) { From 396d59efd65eb795757bc735ad22c8d719623c5d Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Fri, 29 Nov 2024 07:25:54 +0300 Subject: [PATCH 05/50] Remove context_switcher --- src/context_switcher.rs | 67 ----------------------------------------- src/task_manager.rs | 13 -------- 2 files changed, 80 deletions(-) delete mode 100644 src/context_switcher.rs diff --git a/src/context_switcher.rs b/src/context_switcher.rs deleted file mode 100644 index 2a71753..0000000 --- a/src/context_switcher.rs +++ /dev/null @@ -1,67 +0,0 @@ -extern crate alloc; - -use alloc::boxed::Box; -use crate::task_manager::Task; - -enum Architecture { - Mips64, - RiscV32, - Xtensa, -} - -fn create_switcher() -> Box { - #[cfg(target_arch = "mips64")] - return Box::new(Mips64Switcher); - - #[cfg(target_arch = "riscv32")] - return Box::new(RiscV32Switcher); - - #[cfg(target_arch = "xtensa")] - return Box::new(XtensaSwitcher); - - #[cfg(not(any(target_arch = "mips64", target_arch = "riscv32", target_arch = "xtensa")))] - return Box::new(Mips64Switcher); -} - -pub(crate) struct ContextSwitcher { - switcher: Box, -} - -impl ContextSwitcher { - pub(crate) fn new() -> Self { - ContextSwitcher { - switcher: create_switcher(), - } - } - pub(crate) fn save_context(&self, task: &Task) { - self.switcher.save_context(task); - } - - pub(crate) fn load_context(&self, task: &Task) { - self.switcher.load_context(task); - } - -} - -trait SwitcherMethods { - fn save_context(task: &Task); - fn load_context(task: &Task); -} - -struct Mips64Switcher; -impl SwitcherMethods for Mips64Switcher { - fn save_context(task: &Task) {} - fn load_context(task: &Task) {} -} - -struct RiscV32Switcher; -impl SwitcherMethods for RiscV32Switcher { - fn save_context(task: &Task) {} - fn load_context(task: &Task) {} -} - -struct XtensaSwitcher; -impl SwitcherMethods for XtensaSwitcher { - fn save_context(task: &Task) {} - fn load_context(task: &Task) {} -} diff --git a/src/task_manager.rs b/src/task_manager.rs index 34f2e96..243c34f 100644 --- a/src/task_manager.rs +++ b/src/task_manager.rs @@ -3,7 +3,6 @@ extern crate alloc; // A double-ended queue implemented with a growable ring buffer use alloc::collections::VecDeque; use core::array; -use crate::context_switcher::ContextSwitcher; /// Type of loop function, that is called in loop. #[cfg(not(feature = "c-library"))] @@ -32,7 +31,6 @@ pub struct Task { struct TaskManager { priority_array: [VecDeque; NUM_PRIORITIES], - switcher: ContextSwitcher, next_task_id: TaskIdType, } @@ -40,7 +38,6 @@ impl TaskManager { fn new() -> Self { TaskManager { priority_array: array::from_fn(|_| VecDeque::new()), - switcher: ContextSwitcher::new(), next_task_id: 0, } } @@ -89,16 +86,6 @@ impl TaskManager { Ok(()) } - pub fn yield_to_scheduler(&self, mut task: Task, new_status: TaskStatusType) { - self.switcher.save_context(&mut task); - self.update_status(&mut task, new_status); - } - - pub fn wake_up(&self, task: &mut Task) { - self.switcher.load_context(task); - task.update_status(TaskStatusType::Ready); - } - pub fn start_task_manager(&mut self) { loop { // if task is None, array is empty, waiting for new tasks in system From f9d5fe100900eda5fd3430aa53d72902df6cf9ea Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Fri, 29 Nov 2024 08:22:03 +0300 Subject: [PATCH 06/50] Add put_to_sleep method --- src/task_manager.rs | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/src/task_manager.rs b/src/task_manager.rs index 243c34f..9eb59af 100644 --- a/src/task_manager.rs +++ b/src/task_manager.rs @@ -14,10 +14,11 @@ type TaskPriorityType = usize; const NUM_PRIORITIES: usize = 11; +#[derive(PartialEq)] enum TaskStatusType { + Running, Ready, Sleep, - WokeUp, Terminated, } @@ -35,7 +36,7 @@ struct TaskManager { } impl TaskManager { - fn new() -> Self { + pub fn new() -> Self { TaskManager { priority_array: array::from_fn(|_| VecDeque::new()), next_task_id: 0, @@ -86,26 +87,53 @@ impl TaskManager { Ok(()) } + fn find_task(&mut self, id: TaskIdType) -> Option { + for queue in self.priority_array { + for task in queue { + if task.id == id { + return Some(task); + } + continue; + } + } + None + } + + pub fn put_to_sleep(&mut self, id: TaskIdType) -> Result<(), &'static str> { + match self.find_task(id) { + None => { + Err("Error: put_to_sleep: No task with that id") + } + Some(mut task) => { + if task.status == TaskStatusType::Running { + return Err("Error: put_to_sleep: Task with this id is currently running") + } + if task.status != TaskStatusType::Ready { + return Err("Error: put_to_sleep: Task with this id can not go to sleep"); + } + self.update_status(&mut task, TaskStatusType::Sleep); + Ok(()) + } + } + } + pub fn start_task_manager(&mut self) { loop { // if task is None, array is empty, waiting for new tasks in system let Some(mut task) = self.pop_next_task(); match task.status { TaskStatusType::Ready => { + task.status = TaskStatusType::Running; (task.loop_fn)(); - if task.status = TaskStatusType::Sleep { + if task.status != TaskStatusType::Sleep { self.push_to_queue(task); } // deleting task is not adding it back to the queue } TaskStatusType::Sleep => { self.push_to_queue(task); } - TaskStatusType::WokeUp => { - self.wake_up(&mut task); - task.status = TaskStatusType::Ready; - self.push_to_queue(task); - } TaskStatusType::Terminated => {} + _ => {} } } } From a14b93baeb295e9c4d78285c0b2966aa8c22c49d Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Fri, 29 Nov 2024 08:35:37 +0300 Subject: [PATCH 07/50] Add terminate_task method --- src/task_manager.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/task_manager.rs b/src/task_manager.rs index 9eb59af..9c7b119 100644 --- a/src/task_manager.rs +++ b/src/task_manager.rs @@ -117,6 +117,24 @@ impl TaskManager { } } + pub fn terminate_task(&mut self, id: TaskIdType) -> Result<(), &'static str> { + match self.find_task(id) { + None => { + Err("Error: terminate_task: No task with that id") + } + Some(mut task) => { + if task.status == TaskStatusType::Running { + return Err("Error: terminate_task: Task with this id is currently running") + } + if task.status != TaskStatusType::Ready { + return Err("Error: terminate_task: Task with this id can not go to sleep"); + } + self.update_status(&mut task, TaskStatusType::Terminated); + Ok(()) + } + } + } + pub fn start_task_manager(&mut self) { loop { // if task is None, array is empty, waiting for new tasks in system From 5a30dfbabfac653f916ce42b65b837129ae93cd1 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Fri, 29 Nov 2024 08:41:07 +0300 Subject: [PATCH 08/50] Remove context_switchers from lib.rs --- src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 083fcdd..d6ec545 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,7 +5,6 @@ use ports::PortTrait; #[cfg(feature = "c-library")] pub mod c_api; pub mod task_manager; -mod context_switcher; pub mod timer; #[cfg(any(target_arch = "riscv32", target_arch = "xtensa"))] #[cfg(feature = "network")] From b5e5821991abd43869871ac9c5cfd1491d852cb8 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Sat, 7 Dec 2024 13:42:04 +0300 Subject: [PATCH 09/50] Add changes before merging --- Cargo.lock | 197 ++++++++++++++++++++++---------------------- src/task_manager.rs | 59 +++++++------ 2 files changed, 132 insertions(+), 124 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f4182b6..3f2ff81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,12 +1,12 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -19,33 +19,33 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ "windows-sys", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", "windows-sys", @@ -53,9 +53,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "atomic-waker" @@ -101,9 +101,9 @@ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bytemuck" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" [[package]] name = "byteorder" @@ -119,9 +119,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.17" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -129,9 +129,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.17" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", @@ -141,14 +141,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.13" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -159,15 +159,15 @@ checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "critical-section" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" [[package]] name = "darling" @@ -190,7 +190,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -201,7 +201,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -212,7 +212,7 @@ checksum = "4e018fccbeeb50ff26562ece792ed06659b9c2dae79ece77c4456bb10d9bf79b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -264,7 +264,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -285,7 +285,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -311,7 +311,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b94a4b8d74e7cc7baabcca5b2277b41877e039ad9cd49959d48ef94dac7eab4b" dependencies = [ "quote", - "syn 2.0.77", + "syn 2.0.87", "termcolor", ] @@ -362,7 +362,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -487,9 +487,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" [[package]] name = "heapless" @@ -522,9 +522,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "indexmap" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", "hashbrown", @@ -544,9 +544,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libm" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "linked_list_allocator" @@ -581,15 +581,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "minijinja" -version = "2.3.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1028b628753a7e1a88fc59c9ba4b02ecc3bc0bd3c7af23df667bc28df9b3310e" +checksum = "2c37e1b517d1dcd0e51dc36c4567b9d5a29262b3ec8da6cb5d35e27a8fb529b5" dependencies = [ "serde", ] @@ -620,7 +620,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -640,9 +640,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -652,9 +652,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "portable-atomic" -version = "1.7.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" [[package]] name = "portable_atomic_enum" @@ -674,7 +674,7 @@ checksum = "a33fa6ec7f2047f572d49317cca19c87195de99c6e5b6ee492da701cfe02b053" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -712,9 +712,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -752,20 +752,20 @@ dependencies = [ [[package]] name = "riscv-rt-macros" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d100d466dbb76681ef6a9386f3da9abc570d57394e86da0ba5af8c4408486d" +checksum = "30f19a85fe107b65031e0ba8ec60c34c2494069fe910d6c297f5e7cb5a6f76d0" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.87", ] [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "sequential-macro" @@ -784,29 +784,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.210" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -842,7 +842,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.77", + "syn 2.0.87", ] [[package]] @@ -852,15 +852,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", - "quote", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.77" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -898,7 +897,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.77", + "syn 2.0.87", "toml", ] @@ -913,9 +912,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.21" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b072cee73c449a636ffd6f32bd8de3a9f7119139aff882f44943ce2986dc5cf" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap", "serde", @@ -926,9 +925,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "utf8parse" @@ -938,9 +937,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "void" @@ -950,27 +949,27 @@ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ "windows-sys", ] [[package]] name = "windows-sys" -version = "0.52.0" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -984,57 +983,57 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] @@ -1077,5 +1076,5 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.87", ] diff --git a/src/task_manager.rs b/src/task_manager.rs index 9c7b119..a87620e 100644 --- a/src/task_manager.rs +++ b/src/task_manager.rs @@ -30,7 +30,7 @@ pub struct Task { priority: TaskPriorityType, } -struct TaskManager { +pub struct TaskManager { priority_array: [VecDeque; NUM_PRIORITIES], next_task_id: TaskIdType, } @@ -88,32 +88,26 @@ impl TaskManager { } fn find_task(&mut self, id: TaskIdType) -> Option { - for queue in self.priority_array { - for task in queue { - if task.id == id { - return Some(task); - } - continue; + for queue in self.priority_array.iter_mut() { + if let Some(pos) = queue.iter().position(|task| task.id == id) { + return Some(queue.remove(pos).unwrap()); } } None } pub fn put_to_sleep(&mut self, id: TaskIdType) -> Result<(), &'static str> { - match self.find_task(id) { - None => { - Err("Error: put_to_sleep: No task with that id") + if let Some(mut task) = self.find_task(id) { + if task.status == TaskStatusType::Running { + return Err("Error: put_to_sleep: Task with this id is currently running") } - Some(mut task) => { - if task.status == TaskStatusType::Running { - return Err("Error: put_to_sleep: Task with this id is currently running") - } - if task.status != TaskStatusType::Ready { - return Err("Error: put_to_sleep: Task with this id can not go to sleep"); - } - self.update_status(&mut task, TaskStatusType::Sleep); - Ok(()) + if task.status != TaskStatusType::Ready { + return Err("Error: put_to_sleep: Task with this id can not go to sleep"); } + task.status = TaskStatusType::Sleep; + Ok(()) + } else { + Err("Error: put_to_sleep: No task with that id") } } @@ -129,23 +123,21 @@ impl TaskManager { if task.status != TaskStatusType::Ready { return Err("Error: terminate_task: Task with this id can not go to sleep"); } - self.update_status(&mut task, TaskStatusType::Terminated); + TaskManager::update_status(&mut task, TaskStatusType::Terminated); Ok(()) } } } - pub fn start_task_manager(&mut self) { + pub fn start_task_manager(&mut self) -> ! { loop { // if task is None, array is empty, waiting for new tasks in system - let Some(mut task) = self.pop_next_task(); + let Some(mut task) = self.pop_next_task() else { continue }; match task.status { TaskStatusType::Ready => { task.status = TaskStatusType::Running; (task.loop_fn)(); - if task.status != TaskStatusType::Sleep { - self.push_to_queue(task); - } // deleting task is not adding it back to the queue + self.push_to_queue(task); } TaskStatusType::Sleep => { self.push_to_queue(task); @@ -156,3 +148,20 @@ impl TaskManager { } } } + + +// data strictures: +// - pub use binary_heap::BinaryHeap; +// - pub use btree_map::BTreeMap; +// - pub use btree_set::BTreeSet; +// - pub use linked_list::LinkedList; +// - pub use vec_deque::VecDeque; +// - Module vec +// - Module array + + +// если я верно понимаю, один объект был сделан, чтобы это был не совсем трейт, ибо в системе может +// быть только 1 экземпляр TaskManager, но всё равно мне кажется, что это не лучшее решение... уж +// лучше посмотреть, можно ли сделать синглтон, читаю эту штуку +// https://stackoverflow.com/questions/27791532/how-do-i-create-a-global-mutable-singleton +// answers on question about unsafetyness of using 'static mut' in single-thread context https://users.rust-lang.org/t/is-static-mut-unsafe-in-a-single-threaded-context/94242/4 From 1f6777ac5b147179196af5e14f6523b18fbab2e2 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Sat, 7 Dec 2024 16:59:59 +0300 Subject: [PATCH 10/50] Change sched according to preemptive --- src/task_manager/cooperative.rs | 272 +++++++++++++++++++++----------- 1 file changed, 181 insertions(+), 91 deletions(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index 11e2de1..0897910 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -1,136 +1,226 @@ extern crate alloc; use crate::task_manager::{ - task::{ - Task, TaskLoopFunctionType, TaskNumberType, TaskSetupFunctionType, - TaskStopConditionFunctionType, - }, - TaskManagerTrait, TASK_MANAGER, + task::{Task, TaskLoopFunctionType, TaskSetupFunctionType, TaskStopConditionFunctionType}, + TaskManager, TaskManagerTrait, TASK_MANAGER, }; use alloc::vec::Vec; -use core::task::{Poll, RawWaker, RawWakerVTable, Waker}; -use core::{future::Future, pin::Pin, task::Context}; +use core::array; -#[repr(C)] -/// Future shell for task for cooperative execution. -pub struct FutureTask { - /// Task to execute in task manager. - pub(crate) task: Task, - /// Marker for setup function completion. - pub(crate) is_setup_completed: bool, -} +type TaskIdType = usize; +type TaskPriorityType = usize; -impl Future for FutureTask { - type Output = (); +const NUM_PRIORITIES: usize = 11; - fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - let mut array: [usize; 8] = core::array::from_fn(|i| i); - array[0] = 5; - if (self.task.stop_condition_fn)() { - Poll::Ready(()) - } else { - if !self.is_setup_completed { - (self.task.setup_fn)(); - self.is_setup_completed = true; - } else { - (self.task.loop_fn)(); - } - Poll::Pending - } - } +#[derive(PartialEq)] +enum TaskStatusType { + Created, + Ready, + Running, + Sleep, + Terminated, } -/// Creates simple task waker. May be more difficult in perspective. -pub fn task_waker() -> Waker { - fn raw_clone(_: *const ()) -> RawWaker { - RawWaker::new(core::ptr::null::<()>(), &NOOP_WAKER_VTABLE) - } - - fn raw_wake(_: *const ()) {} - - fn raw_wake_by_ref(_: *const ()) {} - - fn raw_drop(_: *const ()) {} - - static NOOP_WAKER_VTABLE: RawWakerVTable = - RawWakerVTable::new(raw_clone, raw_wake, raw_wake_by_ref, raw_drop); - - let raw_waker = RawWaker::new(core::ptr::null::<()>(), &NOOP_WAKER_VTABLE); - unsafe { Waker::from_raw(raw_waker) } +#[repr(C)] +/// Future shell for a task for cooperative execution. +pub struct CooperativeTask { + /// Task to execute in task manager. + pub(crate) task_core: Task, + id: TaskIdType, + status: TaskStatusType, + priority: TaskPriorityType, } #[repr(C)] /// Task manager representation. Based on round-robin scheduling without priorities. pub struct CooperativeTaskManager { /// Vector of tasks to execute. - pub(crate) tasks: Vec, - /// Index of task, that should be executed. - pub(crate) task_to_execute_index: TaskNumberType, + pub(crate) tasks: [Vec; NUM_PRIORITIES], + /// Index of a task, that should be executed. + pub(crate) next_task_id: TaskIdType, } -impl TaskManagerTrait for CooperativeTaskManager { - fn add_task( +impl CooperativeTaskManager { + /// Creates new task manager. + pub(crate) const fn new() -> CooperativeTaskManager { + CooperativeTaskManager { + tasks: array::from_fn(|_| Vec::new()), + next_task_id: 0, + } + } + + fn create_task( setup_fn: TaskSetupFunctionType, loop_fn: TaskLoopFunctionType, stop_condition_fn: TaskStopConditionFunctionType, - ) { + priority: TaskPriorityType, + ) -> CooperativeTask { let task = Task { setup_fn, loop_fn, stop_condition_fn, }; - let future_task = FutureTask { - task, - is_setup_completed: false, - }; + unsafe { - TASK_MANAGER.tasks.push(future_task); + TASK_MANAGER.next_task_id += 1; + let task_id = TASK_MANAGER.next_task_id; + CooperativeTask { + task_core: task, + id: task_id, + status: TaskStatusType::Created, + priority, + } } } - fn start_task_manager() -> ! { - loop { - Self::task_manager_step(); + fn push_to_queue(task: CooperativeTask) { + unsafe { + let mut task_vector = &TASK_MANAGER.tasks[task.priority]; + task_vector.push(task); } } -} -impl CooperativeTaskManager { - /// Creates new task manager. - pub(crate) const fn new() -> CooperativeTaskManager { - CooperativeTaskManager { - tasks: Vec::new(), - task_to_execute_index: 0, + fn setup_task(task: &mut CooperativeTask) { + let res = (task.task_core.setup_fn)(); + if res == () { + task.status = TaskStatusType::Ready } + Err("Error: setup_task: setup_fn is invalid."); + } + pub fn add_task( + setup_fn: TaskSetupFunctionType, + loop_fn: TaskLoopFunctionType, + stop_condition_fn: TaskStopConditionFunctionType, + priority: TaskPriorityType, + ) { + if priority <= 0 && priority >= NUM_PRIORITIES { + Err("Error: add_task: Task's priority is invalid. It must be between 0 and 11."); + } + let mut new_task = TaskManager::create_task(setup_fn, loop_fn, stop_condition_fn, priority); + TaskManager::setup_task(&mut new_task); + TaskManager::push_to_queue(new_task); + } + + pub unsafe fn find_task<'a>(id: TaskIdType) -> Result<&'a mut CooperativeTask, &'a str> { + for vec in TASK_MANAGER.tasks.iter_mut() { + for task in vec.iter_mut() { + if task.id == id { + return Ok(task); + } + } + } + Err("Error: find_task: Task with this id not found.") + } + + pub fn put_to_sleep(id: TaskIdType) { + let res = unsafe { TaskManager::find_task(id) }; + if let Ok(mut task) = res { + match task.status { + TaskStatusType::Running => { + Err("Error: put_to_sleep: Task with this id is currently running."); + } + TaskStatusType::Sleep => { + Err("Error: put_to_sleep: Task with this id is currently sleeping."); + } + TaskStatusType::Terminated => { + Err("Error: put_to_sleep: Task with this id is terminated and recently will be removed."); + } + _ => { + task.status = TaskStatusType::Sleep; + } + } + } else { + Err(res.unwrap()); + } + } + + pub fn terminate_task(id: TaskIdType) { + let res = unsafe { TaskManager::find_task(id) }; + if let Ok(mut task) = res { + task.status = TaskStatusType::Terminated; + TaskManager::delete_task(task); + } else { + Err(res.unwrap()); + } + } + + fn delete_task(task: &mut CooperativeTask) { + unsafe { + let vec = &mut TASK_MANAGER.tasks[task.priority]; + if let Some(pos) = vec.iter().position(|vec_task| vec_task.id == task.id) { + vec.remove(pos); + } + } + } + + fn has_tasks() -> bool { + unsafe { + for vec in TASK_MANAGER.tasks.iter() { + if !vec.is_empty() { + return true; + } + } + } + false } - /// One step of task manager's work. - // TODO: Support priorities. - // TODO: Delete tasks from task vector if they are pending? - fn task_manager_step() { - if unsafe { !TASK_MANAGER.tasks.is_empty() } { - let waker = task_waker(); - - let task = unsafe { &mut TASK_MANAGER.tasks[TASK_MANAGER.task_to_execute_index] }; - let mut task_future_pin = Pin::new(task); - let _ = task_future_pin - .as_mut() - .poll(&mut Context::from_waker(&waker)); - - unsafe { - if TASK_MANAGER.task_to_execute_index + 1 < TASK_MANAGER.tasks.len() { - TASK_MANAGER.task_to_execute_index += 1; - } else { - TASK_MANAGER.task_to_execute_index = 0; + fn get_next_task<'a>() -> Result<&'a mut CooperativeTask, &'a str> { + unsafe { + for vec in TASK_MANAGER.tasks.iter_mut() { + if let Some(task) = vec.last_mut() { + return Ok(task); } } } + Err("Error: get_next_task: No tasks currently, waiting for new tasks.") } /// Starts task manager work. Returns after 1000 steps only for testing task_manager_step. - pub fn test_start_task_manager() { - for _n in 1..=1000 { - Self::task_manager_step(); + pub fn schedule() { + if TaskManager::has_tasks() { + let Ok(mut task) = TaskManager::get_next_task(); + match task.status { + TaskStatusType::Created => { + TaskManager::setup_task(task); + } + TaskStatusType::Ready => { + task.status = TaskStatusType::Running; + (task.task_core.loop_fn)(); + } + TaskStatusType::Running => {} + TaskStatusType::Sleep => {} + TaskStatusType::Terminated => { + TaskManager::delete_task(task); + } + } } } } + +// impl TaskManagerTrait for CooperativeTaskManager { +// fn add_task( +// setup_fn: TaskSetupFunctionType, +// loop_fn: TaskLoopFunctionType, +// stop_condition_fn: TaskStopConditionFunctionType, +// priority: TaskPriorityType, +// ) { +// let task = Task { +// setup_fn, +// loop_fn, +// stop_condition_fn, +// }; +// let future_task = FutureTask { +// task, +// is_setup_completed: false, +// }; +// unsafe { +// TASK_MANAGER.tasks.push(future_task); +// } +// } +// +// fn start_task_manager() -> ! { +// loop { +// Self::task_manager_step(); +// } +// } +// } From 597d9fb99c251e4c9840c4e09b3aa326c28d43a6 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Mon, 9 Dec 2024 10:41:12 +0300 Subject: [PATCH 11/50] Implement TaskManagerTrait --- src/task_manager/cooperative.rs | 42 ++++++++++++--------------------- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index 0897910..fb42688 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -197,30 +197,18 @@ impl CooperativeTaskManager { } } -// impl TaskManagerTrait for CooperativeTaskManager { -// fn add_task( -// setup_fn: TaskSetupFunctionType, -// loop_fn: TaskLoopFunctionType, -// stop_condition_fn: TaskStopConditionFunctionType, -// priority: TaskPriorityType, -// ) { -// let task = Task { -// setup_fn, -// loop_fn, -// stop_condition_fn, -// }; -// let future_task = FutureTask { -// task, -// is_setup_completed: false, -// }; -// unsafe { -// TASK_MANAGER.tasks.push(future_task); -// } -// } -// -// fn start_task_manager() -> ! { -// loop { -// Self::task_manager_step(); -// } -// } -// } +impl TaskManagerTrait for CooperativeTaskManager { + fn add_task( + setup_fn: TaskSetupFunctionType, + loop_fn: TaskLoopFunctionType, + stop_condition_fn: TaskStopConditionFunctionType, + ) { + TaskManager::add_task(setup_fn, loop_fn, stop_condition_fn, 0); + } + + fn start_task_manager() -> ! { + loop { + TaskManager::schedule(); + } + } +} From cd97e6011369797082f406d091366a78caae8666 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Mon, 9 Dec 2024 10:43:07 +0300 Subject: [PATCH 12/50] Rename method to add_priority_task --- src/task_manager/cooperative.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index fb42688..f763a91 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -87,7 +87,8 @@ impl CooperativeTaskManager { } Err("Error: setup_task: setup_fn is invalid."); } - pub fn add_task( + + pub fn add_priority_task( setup_fn: TaskSetupFunctionType, loop_fn: TaskLoopFunctionType, stop_condition_fn: TaskStopConditionFunctionType, @@ -203,7 +204,7 @@ impl TaskManagerTrait for CooperativeTaskManager { loop_fn: TaskLoopFunctionType, stop_condition_fn: TaskStopConditionFunctionType, ) { - TaskManager::add_task(setup_fn, loop_fn, stop_condition_fn, 0); + TaskManager::add_priority_task(setup_fn, loop_fn, stop_condition_fn, 0); } fn start_task_manager() -> ! { From 38e2abfdd6c990b90504c62f3155185067ad85ec Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Mon, 9 Dec 2024 10:44:17 +0300 Subject: [PATCH 13/50] Rename task_core to core --- src/task_manager/cooperative.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index f763a91..244d436 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -25,7 +25,7 @@ enum TaskStatusType { /// Future shell for a task for cooperative execution. pub struct CooperativeTask { /// Task to execute in task manager. - pub(crate) task_core: Task, + pub(crate) core: Task, id: TaskIdType, status: TaskStatusType, priority: TaskPriorityType, @@ -65,7 +65,7 @@ impl CooperativeTaskManager { TASK_MANAGER.next_task_id += 1; let task_id = TASK_MANAGER.next_task_id; CooperativeTask { - task_core: task, + core: task, id: task_id, status: TaskStatusType::Created, priority, @@ -81,7 +81,7 @@ impl CooperativeTaskManager { } fn setup_task(task: &mut CooperativeTask) { - let res = (task.task_core.setup_fn)(); + let res = (task.core.setup_fn)(); if res == () { task.status = TaskStatusType::Ready } @@ -186,7 +186,7 @@ impl CooperativeTaskManager { } TaskStatusType::Ready => { task.status = TaskStatusType::Running; - (task.task_core.loop_fn)(); + (task.core.loop_fn)(); } TaskStatusType::Running => {} TaskStatusType::Sleep => {} From e96e24f1304955243a1111e83bb8abb552136023 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Mon, 9 Dec 2024 10:45:33 +0300 Subject: [PATCH 14/50] Fix condition for priority in add_priority_task --- src/task_manager/cooperative.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index 244d436..24cddaa 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -94,7 +94,7 @@ impl CooperativeTaskManager { stop_condition_fn: TaskStopConditionFunctionType, priority: TaskPriorityType, ) { - if priority <= 0 && priority >= NUM_PRIORITIES { + if priority >= 0 && priority <= NUM_PRIORITIES { Err("Error: add_task: Task's priority is invalid. It must be between 0 and 11."); } let mut new_task = TaskManager::create_task(setup_fn, loop_fn, stop_condition_fn, priority); From 43f2da037585a1b2b7f40e04bce859249849df93 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Mon, 9 Dec 2024 10:53:02 +0300 Subject: [PATCH 15/50] Add stop condition check in schedule() --- src/task_manager/cooperative.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index 24cddaa..b12507d 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -191,7 +191,11 @@ impl CooperativeTaskManager { TaskStatusType::Running => {} TaskStatusType::Sleep => {} TaskStatusType::Terminated => { - TaskManager::delete_task(task); + if (task.core.stop_condition_fn)() { + TaskManager::delete_task(task); + } else { + task.status = TaskStatusType::Ready; + } } } } From dfa253671f95dcca136d47353ed3cae9b360c7fe Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Mon, 9 Dec 2024 11:12:12 +0300 Subject: [PATCH 16/50] Fix fn call from CooperativeTM not TM --- src/task_manager/cooperative.rs | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index b12507d..11f33af 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -2,7 +2,7 @@ extern crate alloc; use crate::task_manager::{ task::{Task, TaskLoopFunctionType, TaskSetupFunctionType, TaskStopConditionFunctionType}, - TaskManager, TaskManagerTrait, TASK_MANAGER, + TaskManagerTrait, TASK_MANAGER, }; use alloc::vec::Vec; use core::array; @@ -97,9 +97,10 @@ impl CooperativeTaskManager { if priority >= 0 && priority <= NUM_PRIORITIES { Err("Error: add_task: Task's priority is invalid. It must be between 0 and 11."); } - let mut new_task = TaskManager::create_task(setup_fn, loop_fn, stop_condition_fn, priority); - TaskManager::setup_task(&mut new_task); - TaskManager::push_to_queue(new_task); + let mut new_task = + CooperativeTaskManager::create_task(setup_fn, loop_fn, stop_condition_fn, priority); + CooperativeTaskManager::setup_task(&mut new_task); + CooperativeTaskManager::push_to_queue(new_task); } pub unsafe fn find_task<'a>(id: TaskIdType) -> Result<&'a mut CooperativeTask, &'a str> { @@ -114,7 +115,7 @@ impl CooperativeTaskManager { } pub fn put_to_sleep(id: TaskIdType) { - let res = unsafe { TaskManager::find_task(id) }; + let res = unsafe { CooperativeTaskManager::find_task(id) }; if let Ok(mut task) = res { match task.status { TaskStatusType::Running => { @@ -136,10 +137,10 @@ impl CooperativeTaskManager { } pub fn terminate_task(id: TaskIdType) { - let res = unsafe { TaskManager::find_task(id) }; + let res = unsafe { CooperativeTaskManager::find_task(id) }; if let Ok(mut task) = res { task.status = TaskStatusType::Terminated; - TaskManager::delete_task(task); + CooperativeTaskManager::delete_task(task); } else { Err(res.unwrap()); } @@ -178,11 +179,11 @@ impl CooperativeTaskManager { /// Starts task manager work. Returns after 1000 steps only for testing task_manager_step. pub fn schedule() { - if TaskManager::has_tasks() { - let Ok(mut task) = TaskManager::get_next_task(); + if CooperativeTaskManager::has_tasks() { + let Ok(mut task) = CooperativeTaskManager::get_next_task() else {}; match task.status { TaskStatusType::Created => { - TaskManager::setup_task(task); + CooperativeTaskManager::setup_task(task); } TaskStatusType::Ready => { task.status = TaskStatusType::Running; @@ -192,7 +193,7 @@ impl CooperativeTaskManager { TaskStatusType::Sleep => {} TaskStatusType::Terminated => { if (task.core.stop_condition_fn)() { - TaskManager::delete_task(task); + CooperativeTaskManager::delete_task(task); } else { task.status = TaskStatusType::Ready; } @@ -208,12 +209,12 @@ impl TaskManagerTrait for CooperativeTaskManager { loop_fn: TaskLoopFunctionType, stop_condition_fn: TaskStopConditionFunctionType, ) { - TaskManager::add_priority_task(setup_fn, loop_fn, stop_condition_fn, 0); + CooperativeTaskManager::add_priority_task(setup_fn, loop_fn, stop_condition_fn, 0); } fn start_task_manager() -> ! { loop { - TaskManager::schedule(); + CooperativeTaskManager::schedule(); } } } From 7c66e2a9dec1fa2a6cd32de7da85bbc6dd8e0142 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Mon, 9 Dec 2024 12:15:09 +0300 Subject: [PATCH 17/50] Fix errors and warnings --- src/task_manager/cooperative.rs | 59 +++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index 11f33af..ef75761 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -5,7 +5,6 @@ use crate::task_manager::{ TaskManagerTrait, TASK_MANAGER, }; use alloc::vec::Vec; -use core::array; type TaskIdType = usize; type TaskPriorityType = usize; @@ -43,8 +42,21 @@ pub struct CooperativeTaskManager { impl CooperativeTaskManager { /// Creates new task manager. pub(crate) const fn new() -> CooperativeTaskManager { + let tasks = [ + Vec::new(), + Vec::new(), + Vec::new(), + Vec::new(), + Vec::new(), + Vec::new(), + Vec::new(), + Vec::new(), + Vec::new(), + Vec::new(), + Vec::new(), + ]; CooperativeTaskManager { - tasks: array::from_fn(|_| Vec::new()), + tasks, next_task_id: 0, } } @@ -75,7 +87,7 @@ impl CooperativeTaskManager { fn push_to_queue(task: CooperativeTask) { unsafe { - let mut task_vector = &TASK_MANAGER.tasks[task.priority]; + let task_vector = &mut TASK_MANAGER.tasks[task.priority]; task_vector.push(task); } } @@ -85,7 +97,7 @@ impl CooperativeTaskManager { if res == () { task.status = TaskStatusType::Ready } - Err("Error: setup_task: setup_fn is invalid."); + // else "Error: setup_task: setup_fn is invalid." } pub fn add_priority_task( @@ -94,55 +106,53 @@ impl CooperativeTaskManager { stop_condition_fn: TaskStopConditionFunctionType, priority: TaskPriorityType, ) { - if priority >= 0 && priority <= NUM_PRIORITIES { - Err("Error: add_task: Task's priority is invalid. It must be between 0 and 11."); - } + // if priority >= 0 && priority <= NUM_PRIORITIES { + // "Error: add_task: Task's priority is invalid. It must be between 0 and 11." + // } let mut new_task = CooperativeTaskManager::create_task(setup_fn, loop_fn, stop_condition_fn, priority); CooperativeTaskManager::setup_task(&mut new_task); CooperativeTaskManager::push_to_queue(new_task); } - pub unsafe fn find_task<'a>(id: TaskIdType) -> Result<&'a mut CooperativeTask, &'a str> { + pub unsafe fn find_task<'a>(id: TaskIdType) -> Option<&'a mut CooperativeTask> { for vec in TASK_MANAGER.tasks.iter_mut() { for task in vec.iter_mut() { if task.id == id { - return Ok(task); + return Some(task); } } } - Err("Error: find_task: Task with this id not found.") + None // ("Error: find_task: Task with this id not found.") } pub fn put_to_sleep(id: TaskIdType) { let res = unsafe { CooperativeTaskManager::find_task(id) }; - if let Ok(mut task) = res { + if let Some(task) = res { match task.status { TaskStatusType::Running => { - Err("Error: put_to_sleep: Task with this id is currently running."); + // "Error: put_to_sleep: Task with this id is currently running." } TaskStatusType::Sleep => { - Err("Error: put_to_sleep: Task with this id is currently sleeping."); + // "Error: put_to_sleep: Task with this id is currently sleeping." } TaskStatusType::Terminated => { - Err("Error: put_to_sleep: Task with this id is terminated and recently will be removed."); + // "Error: put_to_sleep: + // Task with this id is terminated + // and recently will be removed." } _ => { task.status = TaskStatusType::Sleep; } } - } else { - Err(res.unwrap()); } } pub fn terminate_task(id: TaskIdType) { let res = unsafe { CooperativeTaskManager::find_task(id) }; - if let Ok(mut task) = res { + if let Some(task) = res { task.status = TaskStatusType::Terminated; CooperativeTaskManager::delete_task(task); - } else { - Err(res.unwrap()); } } @@ -166,21 +176,22 @@ impl CooperativeTaskManager { false } - fn get_next_task<'a>() -> Result<&'a mut CooperativeTask, &'a str> { + fn get_next_task<'a>() -> Option<&'a mut CooperativeTask> { unsafe { for vec in TASK_MANAGER.tasks.iter_mut() { if let Some(task) = vec.last_mut() { - return Ok(task); + return Some(task); } } } - Err("Error: get_next_task: No tasks currently, waiting for new tasks.") + None // ("Error: get_next_task: No tasks currently, waiting for new tasks.") } - /// Starts task manager work. Returns after 1000 steps only for testing task_manager_step. pub fn schedule() { if CooperativeTaskManager::has_tasks() { - let Ok(mut task) = CooperativeTaskManager::get_next_task() else {}; + let Some(task) = CooperativeTaskManager::get_next_task() else { + todo!() + }; match task.status { TaskStatusType::Created => { CooperativeTaskManager::setup_task(task); From 3f5186d1b0776167b9ab4f18f2e3687e11458c72 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Wed, 11 Dec 2024 16:42:37 +0300 Subject: [PATCH 18/50] Add comments and refactor code --- src/task_manager/cooperative.rs | 191 ++++++++++++++++++-------------- 1 file changed, 107 insertions(+), 84 deletions(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index ef75761..3958b7f 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -6,13 +6,18 @@ use crate::task_manager::{ }; use alloc::vec::Vec; +/// The number of tasks id can fit into a type usize. type TaskIdType = usize; +/// Type of priority number of a task. type TaskPriorityType = usize; +/// Number of existing priorities. const NUM_PRIORITIES: usize = 11; +/// The status of the task changes during execution. ```enum TaskStatusType``` contains possible states. #[derive(PartialEq)] enum TaskStatusType { + // add description of each status Created, Ready, Running, @@ -21,24 +26,51 @@ enum TaskStatusType { } #[repr(C)] -/// Future shell for a task for cooperative execution. +/// The main structure for a cooperative task. Shell for ```Task```, the same +/// for both cooperative and preemptive task managers. pub struct CooperativeTask { - /// Task to execute in task manager. + /// Contains 3 functions for task execution inherited from the ```Task```: ```setup_fn```, + /// ```loop_fn``` and ```stop_condition_fn```. pub(crate) core: Task, + /// Each task has a unique ```id```. The First ```id``` number is 0. id: TaskIdType, + /// Status of existing ```CooperativeTask```. It may change during the task executing. status: TaskStatusType, + /// Each ```CooperativeTask``` has a ```priority```. + /// It is taken into account when selecting the next task to execute. priority: TaskPriorityType, } +/// Cooperative task manager representation. Based on round-robin scheduling with priorities. #[repr(C)] -/// Task manager representation. Based on round-robin scheduling without priorities. pub struct CooperativeTaskManager { - /// Vector of tasks to execute. + /// Array of vectors with ```CooperativeTask``` to execute. pub(crate) tasks: [Vec; NUM_PRIORITIES], - /// Index of a task, that should be executed. + /// ```id``` of a task that will be created the next. pub(crate) next_task_id: TaskIdType, } +/// Cooperative implementation of ```TaskManagerTrait```. +impl TaskManagerTrait for CooperativeTaskManager { + /// Add a task to task manager. + /// It should pass setup, loop, and condition functions. + /// Task added with this function has ```priority``` 0. + fn add_task( + setup_fn: TaskSetupFunctionType, + loop_fn: TaskLoopFunctionType, + stop_condition_fn: TaskStopConditionFunctionType, + ) { + CooperativeTaskManager::add_priority_task(setup_fn, loop_fn, stop_condition_fn, 0); + } + + /// Starts task manager work. + fn start_task_manager() -> ! { + loop { + CooperativeTaskManager::schedule(); + } + } +} + impl CooperativeTaskManager { /// Creates new task manager. pub(crate) const fn new() -> CooperativeTaskManager { @@ -61,45 +93,9 @@ impl CooperativeTaskManager { } } - fn create_task( - setup_fn: TaskSetupFunctionType, - loop_fn: TaskLoopFunctionType, - stop_condition_fn: TaskStopConditionFunctionType, - priority: TaskPriorityType, - ) -> CooperativeTask { - let task = Task { - setup_fn, - loop_fn, - stop_condition_fn, - }; - - unsafe { - TASK_MANAGER.next_task_id += 1; - let task_id = TASK_MANAGER.next_task_id; - CooperativeTask { - core: task, - id: task_id, - status: TaskStatusType::Created, - priority, - } - } - } - - fn push_to_queue(task: CooperativeTask) { - unsafe { - let task_vector = &mut TASK_MANAGER.tasks[task.priority]; - task_vector.push(task); - } - } - - fn setup_task(task: &mut CooperativeTask) { - let res = (task.core.setup_fn)(); - if res == () { - task.status = TaskStatusType::Ready - } - // else "Error: setup_task: setup_fn is invalid." - } - + /// Add a task to task manager. + /// It should pass setup, loop, and condition functions. + /// Task added with this function has given priority. pub fn add_priority_task( setup_fn: TaskSetupFunctionType, loop_fn: TaskLoopFunctionType, @@ -115,6 +111,7 @@ impl CooperativeTaskManager { CooperativeTaskManager::push_to_queue(new_task); } + /// Find a task by ```id``` and return it. pub unsafe fn find_task<'a>(id: TaskIdType) -> Option<&'a mut CooperativeTask> { for vec in TASK_MANAGER.tasks.iter_mut() { for task in vec.iter_mut() { @@ -126,6 +123,7 @@ impl CooperativeTaskManager { None // ("Error: find_task: Task with this id not found.") } + /// Task can put to sleep another task by ```id```. pub fn put_to_sleep(id: TaskIdType) { let res = unsafe { CooperativeTaskManager::find_task(id) }; if let Some(task) = res { @@ -148,6 +146,7 @@ impl CooperativeTaskManager { } } + /// Task can terminate and delete another task by ```id``` even if it executes. pub fn terminate_task(id: TaskIdType) { let res = unsafe { CooperativeTaskManager::find_task(id) }; if let Some(task) = res { @@ -156,41 +155,11 @@ impl CooperativeTaskManager { } } - fn delete_task(task: &mut CooperativeTask) { - unsafe { - let vec = &mut TASK_MANAGER.tasks[task.priority]; - if let Some(pos) = vec.iter().position(|vec_task| vec_task.id == task.id) { - vec.remove(pos); - } - } - } - - fn has_tasks() -> bool { - unsafe { - for vec in TASK_MANAGER.tasks.iter() { - if !vec.is_empty() { - return true; - } - } - } - false - } - - fn get_next_task<'a>() -> Option<&'a mut CooperativeTask> { - unsafe { - for vec in TASK_MANAGER.tasks.iter_mut() { - if let Some(task) = vec.last_mut() { - return Some(task); - } - } - } - None // ("Error: get_next_task: No tasks currently, waiting for new tasks.") - } - + /// One task manager iteration. pub fn schedule() { if CooperativeTaskManager::has_tasks() { let Some(task) = CooperativeTaskManager::get_next_task() else { - todo!() + todo!() // Err }; match task.status { TaskStatusType::Created => { @@ -212,20 +181,74 @@ impl CooperativeTaskManager { } } } -} -impl TaskManagerTrait for CooperativeTaskManager { - fn add_task( + fn create_task( setup_fn: TaskSetupFunctionType, loop_fn: TaskLoopFunctionType, stop_condition_fn: TaskStopConditionFunctionType, - ) { - CooperativeTaskManager::add_priority_task(setup_fn, loop_fn, stop_condition_fn, 0); + priority: TaskPriorityType, + ) -> CooperativeTask { + let task = Task { + setup_fn, + loop_fn, + stop_condition_fn, + }; + + unsafe { + TASK_MANAGER.next_task_id += 1; + let task_id = TASK_MANAGER.next_task_id; + CooperativeTask { + core: task, + id: task_id, + status: TaskStatusType::Created, + priority, + } + } } - fn start_task_manager() -> ! { - loop { - CooperativeTaskManager::schedule(); + fn push_to_queue(task: CooperativeTask) { + unsafe { + let task_vector = &mut TASK_MANAGER.tasks[task.priority]; + task_vector.push(task); } } + + fn setup_task(task: &mut CooperativeTask) { + let res = (task.core.setup_fn)(); + if res == () { + task.status = TaskStatusType::Ready + } + // else "Error: setup_task: setup_fn is invalid." + } + + fn delete_task(task: &mut CooperativeTask) { + unsafe { + let vec = &mut TASK_MANAGER.tasks[task.priority]; + if let Some(pos) = vec.iter().position(|vec_task| vec_task.id == task.id) { + vec.remove(pos); + } + } + } + + fn has_tasks() -> bool { + unsafe { + for vec in TASK_MANAGER.tasks.iter() { + if !vec.is_empty() { + return true; + } + } + } + false + } + + fn get_next_task<'a>() -> Option<&'a mut CooperativeTask> { + unsafe { + for vec in TASK_MANAGER.tasks.iter_mut() { + if let Some(task) = vec.last_mut() { + return Some(task); + } + } + } + None // ("Error: get_next_task: No tasks currently, waiting for new tasks.") + } } From c7d71d4025d1d18defb144355e569e9fe07c201f Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Wed, 11 Dec 2024 16:48:14 +0300 Subject: [PATCH 19/50] Add TODO errors handling comment --- src/task_manager/cooperative.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index 3958b7f..19df6e5 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -71,6 +71,7 @@ impl TaskManagerTrait for CooperativeTaskManager { } } +// TODO: errors handling impl CooperativeTaskManager { /// Creates new task manager. pub(crate) const fn new() -> CooperativeTaskManager { From 73b24fb5d0cc0b5f0a80deae13acefd02c61446c Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Wed, 11 Dec 2024 17:03:39 +0300 Subject: [PATCH 20/50] Remove .idea --- .idea/.gitignore | 8 -------- .idea/Martos.iml | 21 --------------------- .idea/modules.xml | 8 -------- .idea/vcs.xml | 6 ------ 4 files changed, 43 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/Martos.iml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 13566b8..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/.idea/Martos.iml b/.idea/Martos.iml deleted file mode 100644 index 899c38e..0000000 --- a/.idea/Martos.iml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 501ec39..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From e8e9bd362d5a29825b767f55f04c5d32de2b40c4 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Thu, 12 Dec 2024 22:01:31 +0300 Subject: [PATCH 21/50] Add comments for statuses --- src/task_manager/cooperative.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index 19df6e5..01fe79b 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -17,11 +17,18 @@ const NUM_PRIORITIES: usize = 11; /// The status of the task changes during execution. ```enum TaskStatusType``` contains possible states. #[derive(PartialEq)] enum TaskStatusType { - // add description of each status + /// Task status after it is created. Created, + /// Task status after setup function. It is ready to be executed. Ready, + /// Task status when loop function is running. Running, - Sleep, + /// Task status when it is sleeping. + Sleeping, + /// Task status when it terminated. + /// It can be in both cases + /// when a task is finished and when the other task called ```terminate_task``` function + /// with id of a task that will be terminated. Terminated, } @@ -132,7 +139,7 @@ impl CooperativeTaskManager { TaskStatusType::Running => { // "Error: put_to_sleep: Task with this id is currently running." } - TaskStatusType::Sleep => { + TaskStatusType::Sleeping => { // "Error: put_to_sleep: Task with this id is currently sleeping." } TaskStatusType::Terminated => { @@ -141,7 +148,7 @@ impl CooperativeTaskManager { // and recently will be removed." } _ => { - task.status = TaskStatusType::Sleep; + task.status = TaskStatusType::Sleeping; } } } @@ -171,7 +178,7 @@ impl CooperativeTaskManager { (task.core.loop_fn)(); } TaskStatusType::Running => {} - TaskStatusType::Sleep => {} + TaskStatusType::Sleeping => {} TaskStatusType::Terminated => { if (task.core.stop_condition_fn)() { CooperativeTaskManager::delete_task(task); From 0d276b1fc11ed9a4f3a34f3946de24cbaf44282b Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Thu, 12 Dec 2024 22:13:03 +0300 Subject: [PATCH 22/50] Add panic when errors --- src/task_manager/cooperative.rs | 48 +++++++++++++++------------------ 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index 01fe79b..d888a70 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -32,9 +32,9 @@ enum TaskStatusType { Terminated, } +/// The main structure for a cooperative task. +/// Shell for ```Task```, the same for both cooperative and preemptive task managers. #[repr(C)] -/// The main structure for a cooperative task. Shell for ```Task```, the same -/// for both cooperative and preemptive task managers. pub struct CooperativeTask { /// Contains 3 functions for task execution inherited from the ```Task```: ```setup_fn```, /// ```loop_fn``` and ```stop_condition_fn```. @@ -78,7 +78,6 @@ impl TaskManagerTrait for CooperativeTaskManager { } } -// TODO: errors handling impl CooperativeTaskManager { /// Creates new task manager. pub(crate) const fn new() -> CooperativeTaskManager { @@ -110,9 +109,9 @@ impl CooperativeTaskManager { stop_condition_fn: TaskStopConditionFunctionType, priority: TaskPriorityType, ) { - // if priority >= 0 && priority <= NUM_PRIORITIES { - // "Error: add_task: Task's priority is invalid. It must be between 0 and 11." - // } + if priority >= 0 && priority <= NUM_PRIORITIES { + panic!("Error: add_task: Task's priority is invalid. It must be between 0 and 11."); + } let mut new_task = CooperativeTaskManager::create_task(setup_fn, loop_fn, stop_condition_fn, priority); CooperativeTaskManager::setup_task(&mut new_task); @@ -120,32 +119,32 @@ impl CooperativeTaskManager { } /// Find a task by ```id``` and return it. - pub unsafe fn find_task<'a>(id: TaskIdType) -> Option<&'a mut CooperativeTask> { + pub unsafe fn find_task<'a>(id: TaskIdType) -> &'a mut CooperativeTask { for vec in TASK_MANAGER.tasks.iter_mut() { for task in vec.iter_mut() { if task.id == id { - return Some(task); + return task; } } } - None // ("Error: find_task: Task with this id not found.") + panic!("Error: find_task: Task with this id not found."); } /// Task can put to sleep another task by ```id```. pub fn put_to_sleep(id: TaskIdType) { let res = unsafe { CooperativeTaskManager::find_task(id) }; - if let Some(task) = res { + if let task = res { match task.status { TaskStatusType::Running => { - // "Error: put_to_sleep: Task with this id is currently running." + panic!("Error: put_to_sleep: Task with this id is currently running."); } TaskStatusType::Sleeping => { - // "Error: put_to_sleep: Task with this id is currently sleeping." + panic!("Error: put_to_sleep: Task with this id is currently sleeping."); } TaskStatusType::Terminated => { - // "Error: put_to_sleep: - // Task with this id is terminated - // and recently will be removed." + panic!( + "Error: put_to_sleep: Task with this id is terminated and recently will be removed." + ); } _ => { task.status = TaskStatusType::Sleeping; @@ -157,7 +156,7 @@ impl CooperativeTaskManager { /// Task can terminate and delete another task by ```id``` even if it executes. pub fn terminate_task(id: TaskIdType) { let res = unsafe { CooperativeTaskManager::find_task(id) }; - if let Some(task) = res { + if let task = res { task.status = TaskStatusType::Terminated; CooperativeTaskManager::delete_task(task); } @@ -166,9 +165,7 @@ impl CooperativeTaskManager { /// One task manager iteration. pub fn schedule() { if CooperativeTaskManager::has_tasks() { - let Some(task) = CooperativeTaskManager::get_next_task() else { - todo!() // Err - }; + let task = CooperativeTaskManager::get_next_task(); match task.status { TaskStatusType::Created => { CooperativeTaskManager::setup_task(task); @@ -222,11 +219,8 @@ impl CooperativeTaskManager { } fn setup_task(task: &mut CooperativeTask) { - let res = (task.core.setup_fn)(); - if res == () { - task.status = TaskStatusType::Ready - } - // else "Error: setup_task: setup_fn is invalid." + (task.core.setup_fn)(); + task.status = TaskStatusType::Ready; } fn delete_task(task: &mut CooperativeTask) { @@ -249,14 +243,14 @@ impl CooperativeTaskManager { false } - fn get_next_task<'a>() -> Option<&'a mut CooperativeTask> { + fn get_next_task<'a>() -> &'a mut CooperativeTask { unsafe { for vec in TASK_MANAGER.tasks.iter_mut() { if let Some(task) = vec.last_mut() { - return Some(task); + return task; } } } - None // ("Error: get_next_task: No tasks currently, waiting for new tasks.") + panic!("Error: get_next_task: No tasks currently, waiting for new tasks."); } } From 9f18efaaf11b2df997e91132a2402035433c37c3 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Thu, 12 Dec 2024 22:18:33 +0300 Subject: [PATCH 23/50] Fix warnings --- src/task_manager/cooperative.rs | 40 ++++++++++++++++----------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index d888a70..ef80f40 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -109,7 +109,7 @@ impl CooperativeTaskManager { stop_condition_fn: TaskStopConditionFunctionType, priority: TaskPriorityType, ) { - if priority >= 0 && priority <= NUM_PRIORITIES { + if priority >= NUM_PRIORITIES { panic!("Error: add_task: Task's priority is invalid. It must be between 0 and 11."); } let mut new_task = @@ -133,22 +133,21 @@ impl CooperativeTaskManager { /// Task can put to sleep another task by ```id```. pub fn put_to_sleep(id: TaskIdType) { let res = unsafe { CooperativeTaskManager::find_task(id) }; - if let task = res { - match task.status { - TaskStatusType::Running => { - panic!("Error: put_to_sleep: Task with this id is currently running."); - } - TaskStatusType::Sleeping => { - panic!("Error: put_to_sleep: Task with this id is currently sleeping."); - } - TaskStatusType::Terminated => { - panic!( - "Error: put_to_sleep: Task with this id is terminated and recently will be removed." - ); - } - _ => { - task.status = TaskStatusType::Sleeping; - } + let task = res; + match task.status { + TaskStatusType::Running => { + panic!("Error: put_to_sleep: Task with this id is currently running."); + } + TaskStatusType::Sleeping => { + panic!("Error: put_to_sleep: Task with this id is currently sleeping."); + } + TaskStatusType::Terminated => { + panic!( + "Error: put_to_sleep: Task with this id is terminated and recently will be removed." + ); + } + _ => { + task.status = TaskStatusType::Sleeping; } } } @@ -156,10 +155,9 @@ impl CooperativeTaskManager { /// Task can terminate and delete another task by ```id``` even if it executes. pub fn terminate_task(id: TaskIdType) { let res = unsafe { CooperativeTaskManager::find_task(id) }; - if let task = res { - task.status = TaskStatusType::Terminated; - CooperativeTaskManager::delete_task(task); - } + let task = res; + task.status = TaskStatusType::Terminated; + CooperativeTaskManager::delete_task(task); } /// One task manager iteration. From 916d452d77b69c42b728aa2d99464ac9986be1f4 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Fri, 13 Dec 2024 15:26:45 +0300 Subject: [PATCH 24/50] Add test_start_task_manager for tests --- src/task_manager/cooperative.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index ef80f40..310af1a 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -251,4 +251,11 @@ impl CooperativeTaskManager { } panic!("Error: get_next_task: No tasks currently, waiting for new tasks."); } + + /// Starts task manager work. Returns after 1000 steps only for testing task_manager_step. + pub fn test_start_task_manager() { + for _n in 1..=1000 { + CooperativeTaskManager::schedule(); + } + } } From fe0c8274e46d1dfbc6b6c534766f604cb668efa9 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Sat, 14 Dec 2024 15:39:42 +0300 Subject: [PATCH 25/50] Fix bugs according to test --- src/task_manager/cooperative.rs | 12 +++++++++++- tests/unit_tests.rs | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index 310af1a..a1e6169 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -55,6 +55,7 @@ pub struct CooperativeTaskManager { pub(crate) tasks: [Vec; NUM_PRIORITIES], /// ```id``` of a task that will be created the next. pub(crate) next_task_id: TaskIdType, + // pub(crate) current_task_id: TaskIdType, } /// Cooperative implementation of ```TaskManagerTrait```. @@ -152,6 +153,14 @@ impl CooperativeTaskManager { } } + // pub fn get_curr_task_id() -> TaskIdType { + // TASK_MANAGER.current_task_id + // } + // + // pub fn terminate_curr_task() { + // terminate_task(get_curr_task_id()); + // } + /// Task can terminate and delete another task by ```id``` even if it executes. pub fn terminate_task(id: TaskIdType) { let res = unsafe { CooperativeTaskManager::find_task(id) }; @@ -171,6 +180,7 @@ impl CooperativeTaskManager { TaskStatusType::Ready => { task.status = TaskStatusType::Running; (task.core.loop_fn)(); + task.status = TaskStatusType::Terminated; } TaskStatusType::Running => {} TaskStatusType::Sleeping => {} @@ -244,7 +254,7 @@ impl CooperativeTaskManager { fn get_next_task<'a>() -> &'a mut CooperativeTask { unsafe { for vec in TASK_MANAGER.tasks.iter_mut() { - if let Some(task) = vec.last_mut() { + if let Some(task) = vec.first_mut() { return task; } } diff --git a/tests/unit_tests.rs b/tests/unit_tests.rs index c55e6c6..c780f68 100644 --- a/tests/unit_tests.rs +++ b/tests/unit_tests.rs @@ -30,7 +30,7 @@ mod unit_tests { /// Stop function for task for test_one_finite_task_task_manager. fn test_one_finite_task_task_manager_stop_condition_fn() -> bool { let value = unsafe { TEST_ONE_FINITE_TASK_TASK_MANAGER_COUNTER.as_ptr().read() }; - if value % 50 == 0 { + if value == 1000 { return true; } false From c8b6db7ef12887aea4d0e8a8207ef6c2ab1d691b Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Wed, 18 Dec 2024 08:33:36 +0300 Subject: [PATCH 26/50] Test add_fn, find_fn --- src/task_manager/cooperative.rs | 31 +++++++++++- tests/unit_tests.rs | 88 ++++++++++++++++++++++++++++++++- 2 files changed, 116 insertions(+), 3 deletions(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index a1e6169..ae43bc8 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -53,7 +53,7 @@ pub struct CooperativeTask { pub struct CooperativeTaskManager { /// Array of vectors with ```CooperativeTask``` to execute. pub(crate) tasks: [Vec; NUM_PRIORITIES], - /// ```id``` of a task that will be created the next. + /// ```id``` of a task that will be created the next. The First task has id 1. pub(crate) next_task_id: TaskIdType, // pub(crate) current_task_id: TaskIdType, } @@ -268,4 +268,33 @@ impl CooperativeTaskManager { CooperativeTaskManager::schedule(); } } + + pub fn count_tasks_with_priority(priority: TaskPriorityType) -> usize { + unsafe { TASK_MANAGER.tasks[priority].len() } + } + + pub fn has_no_tasks() -> bool { + unsafe { TASK_MANAGER.tasks.iter().all(|vec| vec.is_empty()) } + } + + pub fn count_all_tasks() -> usize { + unsafe { TASK_MANAGER.tasks.iter().map(|vec| vec.len()).sum() } + } + + pub fn reset_task_manager() { + unsafe { + for vec in TASK_MANAGER.tasks.iter_mut() { + vec.clear(); + } + TASK_MANAGER.next_task_id = 0; + } + } + + pub fn get_task_id_from_position(priority: TaskPriorityType, position: usize) -> TaskIdType { + unsafe { TASK_MANAGER.tasks[priority][position].id } + } + + pub fn get_task_id_from_task(task: &mut CooperativeTask) -> TaskIdType { + task.id + } } diff --git a/tests/unit_tests.rs b/tests/unit_tests.rs index c780f68..c8742b4 100644 --- a/tests/unit_tests.rs +++ b/tests/unit_tests.rs @@ -1,4 +1,4 @@ -#[cfg(all(test, not(feature = "mips64_timer_tests")))] +// #[cfg(all(test, not(feature = "mips64_timer_tests")))] mod unit_tests { use martos::task_manager::TaskManager; use martos::task_manager::TaskManagerTrait; @@ -12,11 +12,87 @@ mod unit_tests { // TODO: refactor unit tests. They should check less. Separate tests for setup, loop and stop functions. // TODO: refactor unit tests. Task manager and timer tests should be in different files in one directory. + fn dummy_setup_fn() {} + fn dummy_loop_fn() {} + fn dummy_condition_true() -> bool { + true + } + fn dummy_condition_false() -> bool { + false + } + + #[test] + #[sequential] + #[should_panic( + expected = "Error: add_task: Task's priority is invalid. It must be between 0 and 11." + )] + /// Test add a task with nonexistent priority + fn test_add_task_invalid_priority() { + TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 100); + TaskManager::test_start_task_manager(); + } + + #[test] + #[sequential] + fn test_add_two_priority_tasks_and_check_vectors() { + TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 0); + TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 1); + TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 0); + + assert_eq!(TaskManager::count_tasks_with_priority(0), 2); + assert_eq!(TaskManager::count_tasks_with_priority(1), 1); + assert_eq!(TaskManager::count_all_tasks(), 3); + TaskManager::reset_task_manager(); + } + + #[test] + #[sequential] + fn test_add_task_and_check_if_priority_zero() { + TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); + assert_eq!(TaskManager::count_tasks_with_priority(0), 1); + assert_eq!(TaskManager::count_all_tasks(), 1); + TaskManager::reset_task_manager(); + } + + #[test] + #[sequential] + fn test_find_task_by_id() { + TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 10); + let id_from_position = TaskManager::get_task_id_from_position(10, 0); + + let found_task = unsafe { TaskManager::find_task(id_from_position) }; + + assert_eq!( + id_from_position, + TaskManager::get_task_id_from_task(found_task) + ); + TaskManager::reset_task_manager(); + } + + #[test] + #[sequential] + #[should_panic(expected = "Error: find_task: Task with this id not found.")] + fn test_find_task_by_invalid_id() { + TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 10); + let found_task = unsafe { TaskManager::find_task(2) }; + TaskManager::reset_task_manager(); + } + + #[test] + #[sequential] + fn test_put_to_sleep_other_task() { + TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 10); + let found_task = unsafe { TaskManager::find_task(2) }; + TaskManager::reset_task_manager(); + } + #[test] #[sequential] /// Tests if task manager without tasks works during some time. fn test_empty_task_manager() { TaskManager::test_start_task_manager(); + assert!(TaskManager::has_no_tasks()); + TaskManager::reset_task_manager(); } /// Counter for task for test_one_finite_task_task_manager. @@ -26,11 +102,13 @@ mod unit_tests { /// Loop function for task for test_one_finite_task_task_manager. fn test_one_finite_task_task_manager_loop_fn() { TEST_ONE_FINITE_TASK_TASK_MANAGER_COUNTER.fetch_add(1, Ordering::Relaxed); + // То есть состояния помогают только контролировать flow???? + // А по факту вся суть в состояниях... или наоборот, состояния формируют работу, а эти все функции для проверки чисто рудименты... } /// Stop function for task for test_one_finite_task_task_manager. fn test_one_finite_task_task_manager_stop_condition_fn() -> bool { let value = unsafe { TEST_ONE_FINITE_TASK_TASK_MANAGER_COUNTER.as_ptr().read() }; - if value == 1000 { + if value % 50 == 0 { return true; } false @@ -50,6 +128,7 @@ mod unit_tests { unsafe { TEST_ONE_FINITE_TASK_TASK_MANAGER_COUNTER.as_ptr().read() }, 50 ); + TaskManager::reset_task_manager(); } /// Counter for task for test_one_infinite_task_task_manager. @@ -74,6 +153,7 @@ mod unit_tests { test_one_infinite_task_task_manager_stop_condition_fn, ); TaskManager::test_start_task_manager(); + TaskManager::reset_task_manager(); } /// Counter for task for test_two_finite_tasks_task_manager. @@ -132,6 +212,7 @@ mod unit_tests { unsafe { TEST_TWO_FINITE_TASK_TASK_MANAGER_COUNTER2.as_ptr().read() }, 25 ); + TaskManager::reset_task_manager(); } /// Counter for task for test_two_different_tasks_task_manager. @@ -190,6 +271,7 @@ mod unit_tests { }, 50 ); + TaskManager::reset_task_manager(); } /// Counter for task for test_two_infinite_tasks_task_manager. @@ -231,6 +313,7 @@ mod unit_tests { test_two_infinite_tasks_task_manager_stop_condition_fn2, ); TaskManager::test_start_task_manager(); + TaskManager::reset_task_manager(); } /// Counter for task for test_setup_task_manager. @@ -260,6 +343,7 @@ mod unit_tests { unsafe { TEST_SETUP_TASK_MANAGER_COUNTER.as_ptr().read() }, 42 ); + TaskManager::reset_task_manager(); } #[test] From 48d640a5333b2d5c5c8754d56715c2dcc4ff069e Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Wed, 18 Dec 2024 08:39:04 +0300 Subject: [PATCH 27/50] Remove Created state --- src/task_manager/cooperative.rs | 62 ++++++++++++++------------------- 1 file changed, 26 insertions(+), 36 deletions(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index ae43bc8..6f1378a 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -17,8 +17,6 @@ const NUM_PRIORITIES: usize = 11; /// The status of the task changes during execution. ```enum TaskStatusType``` contains possible states. #[derive(PartialEq)] enum TaskStatusType { - /// Task status after it is created. - Created, /// Task status after setup function. It is ready to be executed. Ready, /// Task status when loop function is running. @@ -113,12 +111,36 @@ impl CooperativeTaskManager { if priority >= NUM_PRIORITIES { panic!("Error: add_task: Task's priority is invalid. It must be between 0 and 11."); } - let mut new_task = + let new_task = CooperativeTaskManager::create_task(setup_fn, loop_fn, stop_condition_fn, priority); - CooperativeTaskManager::setup_task(&mut new_task); + (new_task.core.setup_fn)(); CooperativeTaskManager::push_to_queue(new_task); } + fn create_task( + setup_fn: TaskSetupFunctionType, + loop_fn: TaskLoopFunctionType, + stop_condition_fn: TaskStopConditionFunctionType, + priority: TaskPriorityType, + ) -> CooperativeTask { + let task = Task { + setup_fn, + loop_fn, + stop_condition_fn, + }; + + unsafe { + TASK_MANAGER.next_task_id += 1; + let task_id = TASK_MANAGER.next_task_id; + CooperativeTask { + core: task, + id: task_id, + status: TaskStatusType::Ready, + priority, + } + } + } + /// Find a task by ```id``` and return it. pub unsafe fn find_task<'a>(id: TaskIdType) -> &'a mut CooperativeTask { for vec in TASK_MANAGER.tasks.iter_mut() { @@ -174,9 +196,6 @@ impl CooperativeTaskManager { if CooperativeTaskManager::has_tasks() { let task = CooperativeTaskManager::get_next_task(); match task.status { - TaskStatusType::Created => { - CooperativeTaskManager::setup_task(task); - } TaskStatusType::Ready => { task.status = TaskStatusType::Running; (task.core.loop_fn)(); @@ -195,30 +214,6 @@ impl CooperativeTaskManager { } } - fn create_task( - setup_fn: TaskSetupFunctionType, - loop_fn: TaskLoopFunctionType, - stop_condition_fn: TaskStopConditionFunctionType, - priority: TaskPriorityType, - ) -> CooperativeTask { - let task = Task { - setup_fn, - loop_fn, - stop_condition_fn, - }; - - unsafe { - TASK_MANAGER.next_task_id += 1; - let task_id = TASK_MANAGER.next_task_id; - CooperativeTask { - core: task, - id: task_id, - status: TaskStatusType::Created, - priority, - } - } - } - fn push_to_queue(task: CooperativeTask) { unsafe { let task_vector = &mut TASK_MANAGER.tasks[task.priority]; @@ -226,11 +221,6 @@ impl CooperativeTaskManager { } } - fn setup_task(task: &mut CooperativeTask) { - (task.core.setup_fn)(); - task.status = TaskStatusType::Ready; - } - fn delete_task(task: &mut CooperativeTask) { unsafe { let vec = &mut TASK_MANAGER.tasks[task.priority]; From f61e8ea911bfd90772bbb394ad78b0f5214c5ced Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Wed, 18 Dec 2024 15:19:57 +0300 Subject: [PATCH 28/50] Add tests functions, current_task_id --- src/task_manager/cooperative.rs | 113 ++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 41 deletions(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index 6f1378a..eb272de 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -15,8 +15,8 @@ type TaskPriorityType = usize; const NUM_PRIORITIES: usize = 11; /// The status of the task changes during execution. ```enum TaskStatusType``` contains possible states. -#[derive(PartialEq)] -enum TaskStatusType { +#[derive(PartialEq, Copy, Clone, Debug)] +pub enum TaskStatusType { /// Task status after setup function. It is ready to be executed. Ready, /// Task status when loop function is running. @@ -38,12 +38,12 @@ pub struct CooperativeTask { /// ```loop_fn``` and ```stop_condition_fn```. pub(crate) core: Task, /// Each task has a unique ```id```. The First ```id``` number is 0. - id: TaskIdType, + pub(crate) id: TaskIdType, /// Status of existing ```CooperativeTask```. It may change during the task executing. - status: TaskStatusType, + pub(crate) status: TaskStatusType, /// Each ```CooperativeTask``` has a ```priority```. /// It is taken into account when selecting the next task to execute. - priority: TaskPriorityType, + pub(crate) priority: TaskPriorityType, } /// Cooperative task manager representation. Based on round-robin scheduling with priorities. @@ -53,7 +53,7 @@ pub struct CooperativeTaskManager { pub(crate) tasks: [Vec; NUM_PRIORITIES], /// ```id``` of a task that will be created the next. The First task has id 1. pub(crate) next_task_id: TaskIdType, - // pub(crate) current_task_id: TaskIdType, + pub(crate) current_task_id: TaskIdType, } /// Cooperative implementation of ```TaskManagerTrait```. @@ -96,6 +96,7 @@ impl CooperativeTaskManager { CooperativeTaskManager { tasks, next_task_id: 0, + current_task_id: 0, } } @@ -129,6 +130,7 @@ impl CooperativeTaskManager { stop_condition_fn, }; + // TODO: Handling of tasks' id overflow. unsafe { TASK_MANAGER.next_task_id += 1; let task_id = TASK_MANAGER.next_task_id; @@ -142,21 +144,30 @@ impl CooperativeTaskManager { } /// Find a task by ```id``` and return it. - pub unsafe fn find_task<'a>(id: TaskIdType) -> &'a mut CooperativeTask { - for vec in TASK_MANAGER.tasks.iter_mut() { - for task in vec.iter_mut() { - if task.id == id { - return task; + pub fn get_task_from_id<'a>(id: TaskIdType) -> &'a mut CooperativeTask { + unsafe { + for vec in TASK_MANAGER.tasks.iter_mut() { + for task in vec.iter_mut() { + if task.id == id { + return task; + } } } + panic!("Error: get_task_from_id: Task with this id not found."); } - panic!("Error: find_task: Task with this id not found."); + } + + pub fn get_id_from_position(priority: TaskPriorityType, position: usize) -> TaskIdType { + unsafe { TASK_MANAGER.tasks[priority][position].id } + } + + pub fn get_id_from_task(task: &mut CooperativeTask) -> TaskIdType { + task.id } /// Task can put to sleep another task by ```id```. pub fn put_to_sleep(id: TaskIdType) { - let res = unsafe { CooperativeTaskManager::find_task(id) }; - let task = res; + let task = CooperativeTaskManager::get_task_from_id(id); match task.status { TaskStatusType::Running => { panic!("Error: put_to_sleep: Task with this id is currently running."); @@ -166,31 +177,38 @@ impl CooperativeTaskManager { } TaskStatusType::Terminated => { panic!( - "Error: put_to_sleep: Task with this id is terminated and recently will be removed." - ); + "Error: put_to_sleep: Task with this id is terminated and soon will be removed." + ); } - _ => { - task.status = TaskStatusType::Sleeping; + TaskStatusType::Ready => { + task.status = TaskStatusType::Sleeping; // Need wake up function? } } } - // pub fn get_curr_task_id() -> TaskIdType { - // TASK_MANAGER.current_task_id - // } - // - // pub fn terminate_curr_task() { - // terminate_task(get_curr_task_id()); - // } - /// Task can terminate and delete another task by ```id``` even if it executes. pub fn terminate_task(id: TaskIdType) { - let res = unsafe { CooperativeTaskManager::find_task(id) }; - let task = res; + let task = CooperativeTaskManager::get_task_from_id(id); task.status = TaskStatusType::Terminated; CooperativeTaskManager::delete_task(task); } + pub fn get_curr_task_id() -> TaskIdType { + unsafe { TASK_MANAGER.current_task_id } + } + + pub fn terminate_curr_task() { + CooperativeTaskManager::terminate_task(CooperativeTaskManager::get_curr_task_id()); + } + + pub fn wake_up_task(id: TaskIdType) { + let task = CooperativeTaskManager::get_task_from_id(id); + if task.status != TaskStatusType::Sleeping { + panic!("Error: wake_up_task: Task with this id is currently not sleeping."); + } + task.status = TaskStatusType::Ready; + } + /// One task manager iteration. pub fn schedule() { if CooperativeTaskManager::has_tasks() { @@ -199,25 +217,25 @@ impl CooperativeTaskManager { TaskStatusType::Ready => { task.status = TaskStatusType::Running; (task.core.loop_fn)(); - task.status = TaskStatusType::Terminated; - } - TaskStatusType::Running => {} - TaskStatusType::Sleeping => {} - TaskStatusType::Terminated => { if (task.core.stop_condition_fn)() { - CooperativeTaskManager::delete_task(task); + task.status = TaskStatusType::Terminated; } else { task.status = TaskStatusType::Ready; } } + TaskStatusType::Running => {} + TaskStatusType::Sleeping => {} + TaskStatusType::Terminated => { + CooperativeTaskManager::delete_task(task); + } } } } fn push_to_queue(task: CooperativeTask) { unsafe { - let task_vector = &mut TASK_MANAGER.tasks[task.priority]; - task_vector.push(task); + let vec = &mut TASK_MANAGER.tasks[task.priority]; + vec.push(task); } } @@ -244,7 +262,8 @@ impl CooperativeTaskManager { fn get_next_task<'a>() -> &'a mut CooperativeTask { unsafe { for vec in TASK_MANAGER.tasks.iter_mut() { - if let Some(task) = vec.first_mut() { + if let Some(task) = vec.last_mut() { + TASK_MANAGER.current_task_id = task.id; return task; } } @@ -280,11 +299,23 @@ impl CooperativeTaskManager { } } - pub fn get_task_id_from_position(priority: TaskPriorityType, position: usize) -> TaskIdType { - unsafe { TASK_MANAGER.tasks[priority][position].id } + pub fn get_status(task: &mut CooperativeTask) -> TaskStatusType { + task.status } - pub fn get_task_id_from_task(task: &mut CooperativeTask) -> TaskIdType { - task.id + pub fn ready_status() -> TaskStatusType { + TaskStatusType::Ready + } + + pub fn sleeping_status() -> TaskStatusType { + TaskStatusType::Sleeping + } + + pub fn terminated_status() -> TaskStatusType { + TaskStatusType::Terminated + } + + pub fn running_status() -> TaskStatusType { + TaskStatusType::Running } } From 5caf5fec99b8072921f781d9186ef1a8c1e5813e Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Wed, 18 Dec 2024 15:21:14 +0300 Subject: [PATCH 29/50] Add simple test for put_to_sleep --- tests/unit_tests.rs | 112 ++++++++++++++++++++++++++++++++------------ 1 file changed, 81 insertions(+), 31 deletions(-) diff --git a/tests/unit_tests.rs b/tests/unit_tests.rs index c8742b4..12ba67d 100644 --- a/tests/unit_tests.rs +++ b/tests/unit_tests.rs @@ -1,14 +1,13 @@ // #[cfg(all(test, not(feature = "mips64_timer_tests")))] mod unit_tests { - use martos::task_manager::TaskManager; - use martos::task_manager::TaskManagerTrait; + use martos::task_manager::{TaskManager, TaskManagerTrait}; use martos::timer::Timer; use sequential_test::sequential; + use std::cell::RefCell; use std::{ sync::atomic::{AtomicU32, Ordering}, time::Duration, }; - // TODO: refactor unit tests. They should check less. Separate tests for setup, loop and stop functions. // TODO: refactor unit tests. Task manager and timer tests should be in different files in one directory. @@ -17,9 +16,6 @@ mod unit_tests { fn dummy_condition_true() -> bool { true } - fn dummy_condition_false() -> bool { - false - } #[test] #[sequential] @@ -56,33 +52,87 @@ mod unit_tests { #[test] #[sequential] - fn test_find_task_by_id() { + fn test_get_task_by_id() { TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 10); - let id_from_position = TaskManager::get_task_id_from_position(10, 0); + let id = TaskManager::get_id_from_position(10, 0); - let found_task = unsafe { TaskManager::find_task(id_from_position) }; + let found_task = TaskManager::get_task_from_id(id); - assert_eq!( - id_from_position, - TaskManager::get_task_id_from_task(found_task) - ); + assert_eq!(id, TaskManager::get_id_from_task(found_task)); TaskManager::reset_task_manager(); } #[test] #[sequential] - #[should_panic(expected = "Error: find_task: Task with this id not found.")] + #[should_panic(expected = "Error: get_task_from_id: Task with this id not found.")] fn test_find_task_by_invalid_id() { TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 10); - let found_task = unsafe { TaskManager::find_task(2) }; + let found_task = TaskManager::get_task_from_id(2); TaskManager::reset_task_manager(); } + fn test_put_to_sleep_other_task_loop_fn() { + TaskManager::put_to_sleep(1); + } #[test] #[sequential] - fn test_put_to_sleep_other_task() { - TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 10); - let found_task = unsafe { TaskManager::find_task(2) }; + fn test_put_to_sleep_task_from_task() { + TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); + assert_eq!(TaskManager::get_id_from_position(0, 0), 1); + + TaskManager::add_task( + dummy_setup_fn, + test_put_to_sleep_other_task_loop_fn, + dummy_condition_true, + ); + assert_eq!(TaskManager::get_id_from_position(0, 1), 2); + + let task = TaskManager::get_task_from_id(1); + + assert_eq!(TaskManager::get_status(task), TaskManager::ready_status()); + + TaskManager::test_start_task_manager(); + + assert_eq!( + TaskManager::get_status(task), + TaskManager::sleeping_status() + ); + + TaskManager::reset_task_manager(); + } + + thread_local! { + static EXEC_ORDER: RefCell> = RefCell::new(Vec::new()); + } + #[test] + #[sequential] + fn test_get_next_task_same_priority() { + fn first_task_loop_fn() { + EXEC_ORDER.with(|order| { + order.borrow_mut().push("first"); + }); + } + + fn second_task_loop_fn() { + EXEC_ORDER.with(|order| { + order.borrow_mut().push("second"); + }); + } + + fn third_task_loop_fn() { + EXEC_ORDER.with(|order| { + order.borrow_mut().push("third"); + }); + } + TaskManager::add_task(dummy_setup_fn, first_task_loop_fn, dummy_condition_true); + TaskManager::add_task(dummy_setup_fn, second_task_loop_fn, dummy_condition_true); + TaskManager::add_task(dummy_setup_fn, third_task_loop_fn, dummy_condition_true); + + TaskManager::test_start_task_manager(); + + EXEC_ORDER.with(|order| { + assert_eq!(*order.borrow(), ["third", "second", "first"]); + }); TaskManager::reset_task_manager(); } @@ -95,7 +145,7 @@ mod unit_tests { TaskManager::reset_task_manager(); } - /// Counter for task for test_one_finite_task_task_manager. + /// Counter for a task for test_one_finite_task_task_manager. static TEST_ONE_FINITE_TASK_TASK_MANAGER_COUNTER: AtomicU32 = AtomicU32::new(1); /// Setup function for task for test_one_finite_task_task_manager. fn test_one_finite_task_task_manager_setup_fn() {} @@ -131,7 +181,7 @@ mod unit_tests { TaskManager::reset_task_manager(); } - /// Counter for task for test_one_infinite_task_task_manager. + /// Counter for a task for test_one_infinite_task_task_manager. static TEST_ONE_INFINITE_TASK_TASK_MANAGER_COUNTER: AtomicU32 = AtomicU32::new(1); /// Setup function for task for test_one_infinite_task_task_manager. fn test_one_infinite_task_task_manager_setup_fn() {} @@ -156,7 +206,7 @@ mod unit_tests { TaskManager::reset_task_manager(); } - /// Counter for task for test_two_finite_tasks_task_manager. + /// Counter for a task for test_two_finite_tasks_task_manager. static TEST_TWO_FINITE_TASK_TASK_MANAGER_COUNTER1: AtomicU32 = AtomicU32::new(1); /// Setup function for task for test_two_finite_tasks_task_manager. fn test_two_finite_tasks_task_manager_setup_fn1() {} @@ -172,7 +222,7 @@ mod unit_tests { } false } - /// Counter for task for test_two_finite_tasks_task_manager. + /// Counter for a task for test_two_finite_tasks_task_manager. static TEST_TWO_FINITE_TASK_TASK_MANAGER_COUNTER2: AtomicU32 = AtomicU32::new(1); /// Setup function for task for test_two_finite_tasks_task_manager. fn test_two_finite_tasks_task_manager_setup_fn2() {} @@ -215,7 +265,7 @@ mod unit_tests { TaskManager::reset_task_manager(); } - /// Counter for task for test_two_different_tasks_task_manager. + /// Counter for a task for test_two_different_tasks_task_manager. static TEST_TWO_DIFFERENT_TASK_TASK_MANAGER_COUNTER1: AtomicU32 = AtomicU32::new(1); /// Setup function for task for test_two_different_tasks_task_manager. fn test_two_different_tasks_task_manager_setup_fn1() {} @@ -223,7 +273,7 @@ mod unit_tests { fn test_two_different_tasks_task_manager_loop_fn1() { TEST_TWO_DIFFERENT_TASK_TASK_MANAGER_COUNTER1.fetch_add(1, Ordering::Relaxed); } - /// Stop function for task for test_two_different_tasks_task_manager. + /// Stop function for a task for test_two_different_tasks_task_manager. fn test_two_different_tasks_task_manager_stop_condition_fn1() -> bool { let value = unsafe { TEST_TWO_DIFFERENT_TASK_TASK_MANAGER_COUNTER1 @@ -235,7 +285,7 @@ mod unit_tests { } false } - /// Counter for task for test_two_different_tasks_task_manager. + /// Counter for a task for test_two_different_tasks_task_manager. static TEST_TWO_DIFFERENT_TASK_TASK_MANAGER_COUNTER2: AtomicU32 = AtomicU32::new(1); /// Setup function for task for test_two_different_tasks_task_manager. fn test_two_different_tasks_task_manager_setup_fn2() {} @@ -243,7 +293,7 @@ mod unit_tests { fn test_two_different_tasks_task_manager_loop_fn2() { TEST_TWO_DIFFERENT_TASK_TASK_MANAGER_COUNTER2.fetch_add(1, Ordering::Relaxed); } - /// Stop function for task for test_two_different_tasks_task_manager. + /// Stop function for a task for test_two_different_tasks_task_manager. fn test_two_different_tasks_task_manager_stop_condition_fn2() -> bool { false } @@ -274,7 +324,7 @@ mod unit_tests { TaskManager::reset_task_manager(); } - /// Counter for task for test_two_infinite_tasks_task_manager. + /// Counter for a task for test_two_infinite_tasks_task_manager. static TEST_TWO_INFINITE_TASK_TASK_MANAGER_COUNTER1: AtomicU32 = AtomicU32::new(1); /// Setup function for task for test_two_infinite_tasks_task_manager. fn test_two_infinite_tasks_task_manager_setup_fn1() {} @@ -282,11 +332,11 @@ mod unit_tests { fn test_two_infinite_tasks_task_manager_loop_fn1() { TEST_TWO_INFINITE_TASK_TASK_MANAGER_COUNTER1.fetch_add(1, Ordering::Relaxed); } - /// Stop function for task for test_two_infinite_tasks_task_manager. + /// Stop function for a task for test_two_infinite_tasks_task_manager. fn test_two_infinite_tasks_task_manager_stop_condition_fn1() -> bool { false } - /// Counter for task for test_two_infinite_tasks_task_manager. + /// Counter for a task for test_two_infinite_tasks_task_manager. static TEST_TWO_INFINITE_TASK_TASK_MANAGER_COUNTER2: AtomicU32 = AtomicU32::new(1); /// Setup function for task for test_two_infinite_tasks_task_manager. fn test_two_infinite_tasks_task_manager_setup_fn2() {} @@ -294,7 +344,7 @@ mod unit_tests { fn test_two_infinite_tasks_task_manager_loop_fn2() { TEST_TWO_INFINITE_TASK_TASK_MANAGER_COUNTER2.fetch_add(1, Ordering::Relaxed); } - /// Stop function for task for test_two_infinite_tasks_task_manager. + /// Stop function for a task for test_two_infinite_tasks_task_manager. fn test_two_infinite_tasks_task_manager_stop_condition_fn2() -> bool { false } @@ -316,7 +366,7 @@ mod unit_tests { TaskManager::reset_task_manager(); } - /// Counter for task for test_setup_task_manager. + /// Counter for a task for test_setup_task_manager. static TEST_SETUP_TASK_MANAGER_COUNTER: AtomicU32 = AtomicU32::new(1); /// Setup function for task for test_setup_task_manager. fn test_setup_task_manager_setup_fn() { From 980d22b6cc6765ae37e97fb96d6e12777abb1fe3 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Thu, 19 Dec 2024 08:52:27 +0300 Subject: [PATCH 30/50] Tests for get_id, replace reset to fn head --- tests/unit_tests.rs | 67 +++++++++++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 18 deletions(-) diff --git a/tests/unit_tests.rs b/tests/unit_tests.rs index 12ba67d..91a2210 100644 --- a/tests/unit_tests.rs +++ b/tests/unit_tests.rs @@ -24,6 +24,7 @@ mod unit_tests { )] /// Test add a task with nonexistent priority fn test_add_task_invalid_priority() { + TaskManager::reset_task_manager(); TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 100); TaskManager::test_start_task_manager(); } @@ -31,6 +32,7 @@ mod unit_tests { #[test] #[sequential] fn test_add_two_priority_tasks_and_check_vectors() { + TaskManager::reset_task_manager(); TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 0); TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 1); TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 0); @@ -38,67 +40,96 @@ mod unit_tests { assert_eq!(TaskManager::count_tasks_with_priority(0), 2); assert_eq!(TaskManager::count_tasks_with_priority(1), 1); assert_eq!(TaskManager::count_all_tasks(), 3); - TaskManager::reset_task_manager(); } #[test] #[sequential] fn test_add_task_and_check_if_priority_zero() { + TaskManager::reset_task_manager(); TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); assert_eq!(TaskManager::count_tasks_with_priority(0), 1); assert_eq!(TaskManager::count_all_tasks(), 1); - TaskManager::reset_task_manager(); } #[test] #[sequential] fn test_get_task_by_id() { + TaskManager::reset_task_manager(); TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 10); let id = TaskManager::get_id_from_position(10, 0); let found_task = TaskManager::get_task_from_id(id); assert_eq!(id, TaskManager::get_id_from_task(found_task)); - TaskManager::reset_task_manager(); } #[test] #[sequential] #[should_panic(expected = "Error: get_task_from_id: Task with this id not found.")] - fn test_find_task_by_invalid_id() { + fn test_get_task_by_invalid_id() { + TaskManager::reset_task_manager(); TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 10); let found_task = TaskManager::get_task_from_id(2); + } + + #[test] + #[sequential] + fn test_get_id_from_position() { + TaskManager::reset_task_manager(); + // ID of a first added task is 1. + TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 10); + + let task_id = TaskManager::get_id_from_position(10, 0); + assert_eq!(task_id, 1); + } + + #[test] + #[sequential] + #[should_panic(expected = "Error: get_id_from_position: Position out of bounds.")] + fn test_get_id_from_invalid_position() { + TaskManager::reset_task_manager(); + // ID of a first added task is 1. + TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 10); + let task_id = TaskManager::get_id_from_position(10, 1); + } + + #[test] + #[sequential] + fn test_get_id_from_task() { TaskManager::reset_task_manager(); + TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); + + let task = TaskManager::get_task_from_id(1); + assert_eq!(TaskManager::get_id_from_task(task), 1); } - fn test_put_to_sleep_other_task_loop_fn() { + fn test_put_to_sleep_task_from_task_loop_fn() { TaskManager::put_to_sleep(1); } #[test] #[sequential] fn test_put_to_sleep_task_from_task() { + TaskManager::reset_task_manager(); TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); assert_eq!(TaskManager::get_id_from_position(0, 0), 1); TaskManager::add_task( dummy_setup_fn, - test_put_to_sleep_other_task_loop_fn, + test_put_to_sleep_task_from_task_loop_fn, dummy_condition_true, ); assert_eq!(TaskManager::get_id_from_position(0, 1), 2); - let task = TaskManager::get_task_from_id(1); + let task_1 = TaskManager::get_task_from_id(1); - assert_eq!(TaskManager::get_status(task), TaskManager::ready_status()); + assert_eq!(TaskManager::get_status(task_1), TaskManager::ready_status()); TaskManager::test_start_task_manager(); assert_eq!( - TaskManager::get_status(task), + TaskManager::get_status(task_1), TaskManager::sleeping_status() ); - - TaskManager::reset_task_manager(); } thread_local! { @@ -107,6 +138,7 @@ mod unit_tests { #[test] #[sequential] fn test_get_next_task_same_priority() { + TaskManager::reset_task_manager(); fn first_task_loop_fn() { EXEC_ORDER.with(|order| { order.borrow_mut().push("first"); @@ -133,16 +165,15 @@ mod unit_tests { EXEC_ORDER.with(|order| { assert_eq!(*order.borrow(), ["third", "second", "first"]); }); - TaskManager::reset_task_manager(); } #[test] #[sequential] /// Tests if task manager without tasks works during some time. fn test_empty_task_manager() { + TaskManager::reset_task_manager(); TaskManager::test_start_task_manager(); assert!(TaskManager::has_no_tasks()); - TaskManager::reset_task_manager(); } /// Counter for a task for test_one_finite_task_task_manager. @@ -167,6 +198,7 @@ mod unit_tests { #[sequential] /// Tests if task manager with one finite task works correctly during some time without panic. fn test_one_finite_task_task_manager() { + TaskManager::reset_task_manager(); TaskManager::add_task( test_one_finite_task_task_manager_setup_fn, test_one_finite_task_task_manager_loop_fn, @@ -178,7 +210,6 @@ mod unit_tests { unsafe { TEST_ONE_FINITE_TASK_TASK_MANAGER_COUNTER.as_ptr().read() }, 50 ); - TaskManager::reset_task_manager(); } /// Counter for a task for test_one_infinite_task_task_manager. @@ -242,6 +273,7 @@ mod unit_tests { #[sequential] /// Tests if task manager with two finite tasks works correctly during some time without panic. fn test_two_finite_tasks_task_manager() { + TaskManager::reset_task_manager(); TaskManager::add_task( test_two_finite_tasks_task_manager_setup_fn1, test_two_finite_tasks_task_manager_loop_fn1, @@ -262,7 +294,6 @@ mod unit_tests { unsafe { TEST_TWO_FINITE_TASK_TASK_MANAGER_COUNTER2.as_ptr().read() }, 25 ); - TaskManager::reset_task_manager(); } /// Counter for a task for test_two_different_tasks_task_manager. @@ -301,6 +332,7 @@ mod unit_tests { #[sequential] /// Tests if task manager with two different (finite and infinite) tasks works correctly during some time without panic. fn test_two_different_tasks_task_manager() { + TaskManager::reset_task_manager(); TaskManager::add_task( test_two_different_tasks_task_manager_setup_fn1, test_two_different_tasks_task_manager_loop_fn1, @@ -321,7 +353,6 @@ mod unit_tests { }, 50 ); - TaskManager::reset_task_manager(); } /// Counter for a task for test_two_infinite_tasks_task_manager. @@ -352,6 +383,7 @@ mod unit_tests { #[sequential] /// Tests if task manager with two infinite tasks works correctly during some without panic. fn test_two_infinite_tasks_task_manager() { + TaskManager::reset_task_manager(); TaskManager::add_task( test_two_infinite_tasks_task_manager_setup_fn1, test_two_infinite_tasks_task_manager_loop_fn1, @@ -363,7 +395,6 @@ mod unit_tests { test_two_infinite_tasks_task_manager_stop_condition_fn2, ); TaskManager::test_start_task_manager(); - TaskManager::reset_task_manager(); } /// Counter for a task for test_setup_task_manager. @@ -382,6 +413,7 @@ mod unit_tests { #[sequential] /// Tests if task manager works correctly with setup function during some time without panic. fn test_setup_task_manager() { + TaskManager::reset_task_manager(); TaskManager::add_task( test_setup_task_manager_setup_fn, test_setup_task_manager_loop_fn, @@ -393,7 +425,6 @@ mod unit_tests { unsafe { TEST_SETUP_TASK_MANAGER_COUNTER.as_ptr().read() }, 42 ); - TaskManager::reset_task_manager(); } #[test] From 5640ff93cb57cf72c2f2b0401cd55707f4970518 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Thu, 19 Dec 2024 08:55:48 +0300 Subject: [PATCH 31/50] Add panic get_id_from_position --- src/task_manager/cooperative.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index eb272de..7158866 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -21,7 +21,7 @@ pub enum TaskStatusType { Ready, /// Task status when loop function is running. Running, - /// Task status when it is sleeping. + /// Task status when it is sleeping. After waking up, a task again starts loop_fn. Sleeping, /// Task status when it terminated. /// It can be in both cases @@ -158,7 +158,12 @@ impl CooperativeTaskManager { } pub fn get_id_from_position(priority: TaskPriorityType, position: usize) -> TaskIdType { - unsafe { TASK_MANAGER.tasks[priority][position].id } + unsafe { + TASK_MANAGER.tasks[priority] + .get(position) + .unwrap_or_else(|| panic!("Error: get_id_from_position: Position out of bounds.")) + .id + } } pub fn get_id_from_task(task: &mut CooperativeTask) -> TaskIdType { From 0debdfa5420a543163b963b9edfa7ffa68e75d77 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Thu, 19 Dec 2024 09:37:52 +0300 Subject: [PATCH 32/50] Test diff states for put_to_sleep --- tests/unit_tests.rs | 77 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests.rs b/tests/unit_tests.rs index 91a2210..99964ba 100644 --- a/tests/unit_tests.rs +++ b/tests/unit_tests.rs @@ -103,9 +103,82 @@ mod unit_tests { assert_eq!(TaskManager::get_id_from_task(task), 1); } - fn test_put_to_sleep_task_from_task_loop_fn() { + fn test_put_to_sleep_loop_fn() { TaskManager::put_to_sleep(1); } + + #[test] + #[sequential] + #[should_panic(expected = "Error: put_to_sleep: Task with this id is currently running.")] + fn test_put_to_sleep_running_task() { + TaskManager::reset_task_manager(); + TaskManager::add_task( + dummy_setup_fn, + test_put_to_sleep_loop_fn, + dummy_condition_true, + ); + TaskManager::test_start_task_manager(); + } + + #[test] + #[sequential] + #[should_panic(expected = "Error: put_to_sleep: Task with this id is currently sleeping.")] + fn test_put_to_sleep_sleeping_task() { + TaskManager::reset_task_manager(); + TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); + + let task_1 = TaskManager::get_task_from_id(1); + + assert_eq!(TaskManager::get_status(task_1), TaskManager::ready_status()); + + TaskManager::add_task( + dummy_setup_fn, + test_put_to_sleep_loop_fn, + dummy_condition_true, + ); + TaskManager::schedule(); + assert_eq!( + TaskManager::get_status(task_1), + TaskManager::sleeping_status() + ); + + TaskManager::add_task( + dummy_setup_fn, + test_put_to_sleep_loop_fn, + dummy_condition_true, + ); + TaskManager::test_start_task_manager(); + } + + #[test] + #[sequential] + #[should_panic( + expected = "Error: put_to_sleep: Task with this id is terminated and soon will be removed." + )] + fn test_put_to_sleep_terminated_task() { + TaskManager::reset_task_manager(); + TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); + + let task_1 = TaskManager::get_task_from_id(1); + + assert_eq!(TaskManager::get_status(task_1), TaskManager::ready_status()); + + TaskManager::schedule(); + + assert_eq!( + TaskManager::get_status(task_1), + TaskManager::terminated_status() + ); + + TaskManager::add_task( + dummy_setup_fn, + test_put_to_sleep_loop_fn, + dummy_condition_true, + ); + + TaskManager::test_start_task_manager(); + } + #[test] #[sequential] fn test_put_to_sleep_task_from_task() { @@ -115,7 +188,7 @@ mod unit_tests { TaskManager::add_task( dummy_setup_fn, - test_put_to_sleep_task_from_task_loop_fn, + test_put_to_sleep_loop_fn, dummy_condition_true, ); assert_eq!(TaskManager::get_id_from_position(0, 1), 2); From 956b5684863b854c22029fe76a69244303eef9fe Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Thu, 19 Dec 2024 09:51:52 +0300 Subject: [PATCH 33/50] Add wake_up and test it --- src/task_manager/cooperative.rs | 8 ++++ tests/unit_tests.rs | 70 ++++++++++++++++++++++++++++++--- 2 files changed, 72 insertions(+), 6 deletions(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index 7158866..28ace25 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -191,6 +191,14 @@ impl CooperativeTaskManager { } } + pub fn wake_up(id: TaskIdType) { + let task = CooperativeTaskManager::get_task_from_id(id); + if task.status != TaskStatusType::Sleeping { + panic!("Error: wake_up_task: Task with this id is currently not sleeping."); + } + task.status = TaskStatusType::Ready; + } + /// Task can terminate and delete another task by ```id``` even if it executes. pub fn terminate_task(id: TaskIdType) { let task = CooperativeTaskManager::get_task_from_id(id); diff --git a/tests/unit_tests.rs b/tests/unit_tests.rs index 99964ba..c79051b 100644 --- a/tests/unit_tests.rs +++ b/tests/unit_tests.rs @@ -103,7 +103,7 @@ mod unit_tests { assert_eq!(TaskManager::get_id_from_task(task), 1); } - fn test_put_to_sleep_loop_fn() { + fn test_put_to_sleep_task_1_loop_fn() { TaskManager::put_to_sleep(1); } @@ -114,7 +114,7 @@ mod unit_tests { TaskManager::reset_task_manager(); TaskManager::add_task( dummy_setup_fn, - test_put_to_sleep_loop_fn, + test_put_to_sleep_task_1_loop_fn, dummy_condition_true, ); TaskManager::test_start_task_manager(); @@ -133,7 +133,7 @@ mod unit_tests { TaskManager::add_task( dummy_setup_fn, - test_put_to_sleep_loop_fn, + test_put_to_sleep_task_1_loop_fn, dummy_condition_true, ); TaskManager::schedule(); @@ -144,7 +144,7 @@ mod unit_tests { TaskManager::add_task( dummy_setup_fn, - test_put_to_sleep_loop_fn, + test_put_to_sleep_task_1_loop_fn, dummy_condition_true, ); TaskManager::test_start_task_manager(); @@ -172,7 +172,7 @@ mod unit_tests { TaskManager::add_task( dummy_setup_fn, - test_put_to_sleep_loop_fn, + test_put_to_sleep_task_1_loop_fn, dummy_condition_true, ); @@ -188,7 +188,7 @@ mod unit_tests { TaskManager::add_task( dummy_setup_fn, - test_put_to_sleep_loop_fn, + test_put_to_sleep_task_1_loop_fn, dummy_condition_true, ); assert_eq!(TaskManager::get_id_from_position(0, 1), 2); @@ -205,6 +205,64 @@ mod unit_tests { ); } + fn test_wake_up_task_1_loop_fn() { + TaskManager::wake_up(1); + } + + #[test] + #[sequential] + fn test_wake_up_sleeping_task() { + TaskManager::reset_task_manager(); + TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); + + let task_1 = TaskManager::get_task_from_id(1); + + assert_eq!(TaskManager::get_status(task_1), TaskManager::ready_status()); + + TaskManager::add_task( + dummy_setup_fn, + test_put_to_sleep_task_1_loop_fn, + dummy_condition_true, + ); + TaskManager::schedule(); + assert_eq!( + TaskManager::get_status(task_1), + TaskManager::sleeping_status() + ); + + TaskManager::add_task( + dummy_setup_fn, + test_wake_up_task_1_loop_fn, + dummy_condition_true, + ); + + TaskManager::schedule(); + + assert_eq!(TaskManager::get_status(task_1), TaskManager::ready_status()); + } + + #[test] + #[sequential] + #[should_panic(expected = "Error: wake_up_task: Task with this id is currently not sleeping.")] + fn test_wake_up_non_sleeping_task() { + TaskManager::reset_task_manager(); + TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); + + let task_1 = TaskManager::get_task_from_id(1); + + assert_eq!(TaskManager::get_status(task_1), TaskManager::ready_status()); + + TaskManager::add_task( + dummy_setup_fn, + test_wake_up_task_1_loop_fn, + dummy_condition_true, + ); + + TaskManager::schedule(); + + assert_eq!(TaskManager::get_status(task_1), TaskManager::ready_status()); + } + thread_local! { static EXEC_ORDER: RefCell> = RefCell::new(Vec::new()); } From 0b5db208d235d5355f15980e642f6315accf1ed4 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Thu, 19 Dec 2024 09:52:26 +0300 Subject: [PATCH 34/50] Refactor fn terminate task with current_task_id --- src/task_manager/cooperative.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index 28ace25..7dff991 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -206,12 +206,10 @@ impl CooperativeTaskManager { CooperativeTaskManager::delete_task(task); } - pub fn get_curr_task_id() -> TaskIdType { - unsafe { TASK_MANAGER.current_task_id } - } - pub fn terminate_curr_task() { - CooperativeTaskManager::terminate_task(CooperativeTaskManager::get_curr_task_id()); + unsafe { + CooperativeTaskManager::terminate_task(TASK_MANAGER.current_task_id); + } } pub fn wake_up_task(id: TaskIdType) { From 980376c35d9f86deca052d28d43b58ba5d795ba1 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Thu, 19 Dec 2024 10:28:22 +0300 Subject: [PATCH 35/50] Fix schedule fn (sleeping state) --- src/task_manager/cooperative.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index 7dff991..6441105 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -202,6 +202,9 @@ impl CooperativeTaskManager { /// Task can terminate and delete another task by ```id``` even if it executes. pub fn terminate_task(id: TaskIdType) { let task = CooperativeTaskManager::get_task_from_id(id); + if task.status == TaskStatusType::Terminated { + panic!("Error: terminate_task: Task with this id is currently terminated."); + } task.status = TaskStatusType::Terminated; CooperativeTaskManager::delete_task(task); } @@ -234,7 +237,13 @@ impl CooperativeTaskManager { task.status = TaskStatusType::Ready; } } - TaskStatusType::Running => {} + TaskStatusType::Running => { + if (task.core.stop_condition_fn)() { + task.status = TaskStatusType::Terminated; + } else { + task.status = TaskStatusType::Running; + } + } TaskStatusType::Sleeping => {} TaskStatusType::Terminated => { CooperativeTaskManager::delete_task(task); From 2baecc9d836394cbcbea52f6f7aeabea42d71366 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Thu, 19 Dec 2024 12:12:10 +0300 Subject: [PATCH 36/50] Remove terminate_curr_task fn --- src/task_manager/cooperative.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index 6441105..0409385 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -209,12 +209,6 @@ impl CooperativeTaskManager { CooperativeTaskManager::delete_task(task); } - pub fn terminate_curr_task() { - unsafe { - CooperativeTaskManager::terminate_task(TASK_MANAGER.current_task_id); - } - } - pub fn wake_up_task(id: TaskIdType) { let task = CooperativeTaskManager::get_task_from_id(id); if task.status != TaskStatusType::Sleeping { From 9c32884f9781139a833da1a2171576106474fd19 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Thu, 19 Dec 2024 12:13:00 +0300 Subject: [PATCH 37/50] Test terminate_task fn --- tests/unit_tests.rs | 57 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/tests/unit_tests.rs b/tests/unit_tests.rs index c79051b..df263a4 100644 --- a/tests/unit_tests.rs +++ b/tests/unit_tests.rs @@ -203,6 +203,8 @@ mod unit_tests { TaskManager::get_status(task_1), TaskManager::sleeping_status() ); + + assert_eq!(TaskManager::count_all_tasks(), 1); } fn test_wake_up_task_1_loop_fn() { @@ -263,6 +265,61 @@ mod unit_tests { assert_eq!(TaskManager::get_status(task_1), TaskManager::ready_status()); } + fn test_terminate_task_1_loop_fn() { + TaskManager::terminate_task(1); + } + + #[test] + #[sequential] + #[should_panic(expected = "Error: terminate_task: Task with this id is currently terminated.")] + fn test_terminate_terminated_task() { + TaskManager::reset_task_manager(); + TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); + + let task_1 = TaskManager::get_task_from_id(1); + + assert_eq!(TaskManager::get_status(task_1), TaskManager::ready_status()); + + TaskManager::schedule(); + + assert_eq!( + TaskManager::get_status(task_1), + TaskManager::terminated_status() + ); + + TaskManager::add_task( + dummy_setup_fn, + test_terminate_task_1_loop_fn, + dummy_condition_true, + ); + + TaskManager::test_start_task_manager(); + } + + fn infinite_loop_fn() { + loop {} + } + #[test] + #[sequential] + fn test_terminate_non_terminated_task() { + TaskManager::reset_task_manager(); + TaskManager::add_task(dummy_setup_fn, infinite_loop_fn, dummy_condition_true); + + let task_1 = TaskManager::get_task_from_id(1); + + assert_eq!(TaskManager::get_status(task_1), TaskManager::ready_status()); + + TaskManager::add_task( + dummy_setup_fn, + test_terminate_task_1_loop_fn, + dummy_condition_true, + ); + + TaskManager::test_start_task_manager(); + + assert_eq!(TaskManager::count_all_tasks(), 0); + } + thread_local! { static EXEC_ORDER: RefCell> = RefCell::new(Vec::new()); } From 63a906182e5c6246a1249896c6abdf0e629186a9 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Thu, 19 Dec 2024 17:55:49 +0300 Subject: [PATCH 38/50] Add rest of tests --- ...it_tests.rs => task_manager_unit_tests.rs} | 306 ++++++++---------- 1 file changed, 131 insertions(+), 175 deletions(-) rename tests/{unit_tests.rs => task_manager_unit_tests.rs} (79%) diff --git a/tests/unit_tests.rs b/tests/task_manager_unit_tests.rs similarity index 79% rename from tests/unit_tests.rs rename to tests/task_manager_unit_tests.rs index df263a4..2ff49f2 100644 --- a/tests/unit_tests.rs +++ b/tests/task_manager_unit_tests.rs @@ -1,13 +1,8 @@ // #[cfg(all(test, not(feature = "mips64_timer_tests")))] -mod unit_tests { +mod task_manager_unit_tests { use martos::task_manager::{TaskManager, TaskManagerTrait}; - use martos::timer::Timer; use sequential_test::sequential; - use std::cell::RefCell; - use std::{ - sync::atomic::{AtomicU32, Ordering}, - time::Duration, - }; + use std::sync::atomic::{AtomicU32, Ordering}; // TODO: refactor unit tests. They should check less. Separate tests for setup, loop and stop functions. // TODO: refactor unit tests. Task manager and timer tests should be in different files in one directory. @@ -17,6 +12,16 @@ mod unit_tests { true } + #[test] + #[sequential] + fn test_reset_task_manager() { + TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 3); + TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 5); + + TaskManager::reset_task_manager(); + assert_eq!(TaskManager::count_all_tasks(), 0); + } + #[test] #[sequential] #[should_panic( @@ -40,6 +45,7 @@ mod unit_tests { assert_eq!(TaskManager::count_tasks_with_priority(0), 2); assert_eq!(TaskManager::count_tasks_with_priority(1), 1); assert_eq!(TaskManager::count_all_tasks(), 3); + TaskManager::reset_task_manager(); } #[test] @@ -49,6 +55,7 @@ mod unit_tests { TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); assert_eq!(TaskManager::count_tasks_with_priority(0), 1); assert_eq!(TaskManager::count_all_tasks(), 1); + TaskManager::reset_task_manager(); } #[test] @@ -61,15 +68,17 @@ mod unit_tests { let found_task = TaskManager::get_task_from_id(id); assert_eq!(id, TaskManager::get_id_from_task(found_task)); + TaskManager::reset_task_manager(); } #[test] #[sequential] - #[should_panic(expected = "Error: get_task_from_id: Task with this id not found.")] + #[should_panic(expected = "Error: get_task_from_id: Task with id 2 not found.")] fn test_get_task_by_invalid_id() { TaskManager::reset_task_manager(); TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 10); let found_task = TaskManager::get_task_from_id(2); + TaskManager::reset_task_manager(); } #[test] @@ -81,6 +90,7 @@ mod unit_tests { let task_id = TaskManager::get_id_from_position(10, 0); assert_eq!(task_id, 1); + TaskManager::reset_task_manager(); } #[test] @@ -91,6 +101,7 @@ mod unit_tests { // ID of a first added task is 1. TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 10); let task_id = TaskManager::get_id_from_position(10, 1); + TaskManager::reset_task_manager(); } #[test] @@ -101,9 +112,10 @@ mod unit_tests { let task = TaskManager::get_task_from_id(1); assert_eq!(TaskManager::get_id_from_task(task), 1); + TaskManager::reset_task_manager(); } - fn test_put_to_sleep_task_1_loop_fn() { + fn test_put_to_sleep_running_task_loop_fn() { TaskManager::put_to_sleep(1); } @@ -114,69 +126,52 @@ mod unit_tests { TaskManager::reset_task_manager(); TaskManager::add_task( dummy_setup_fn, - test_put_to_sleep_task_1_loop_fn, + test_put_to_sleep_running_task_loop_fn, dummy_condition_true, ); + + assert_eq!(TaskManager::get_id_from_position(0, 0), 1); TaskManager::test_start_task_manager(); + TaskManager::reset_task_manager(); } + fn test_put_to_sleep_sleeping_task_loop_fn() { + TaskManager::put_to_sleep(2); + } #[test] #[sequential] #[should_panic(expected = "Error: put_to_sleep: Task with this id is currently sleeping.")] fn test_put_to_sleep_sleeping_task() { TaskManager::reset_task_manager(); - TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); - - let task_1 = TaskManager::get_task_from_id(1); - - assert_eq!(TaskManager::get_status(task_1), TaskManager::ready_status()); + // Change a task state with id = 2 to sleeping. TaskManager::add_task( dummy_setup_fn, - test_put_to_sleep_task_1_loop_fn, + test_put_to_sleep_sleeping_task_loop_fn, dummy_condition_true, ); + TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); + let task_2 = TaskManager::get_task_from_id(2); + assert_eq!(TaskManager::get_status(task_2), TaskManager::ready_status()); + TaskManager::schedule(); TaskManager::schedule(); assert_eq!( - TaskManager::get_status(task_1), + TaskManager::get_status(task_2), TaskManager::sleeping_status() ); + // Add a task that will put to a sleep sleeping task. TaskManager::add_task( dummy_setup_fn, - test_put_to_sleep_task_1_loop_fn, + test_put_to_sleep_sleeping_task_loop_fn, dummy_condition_true, ); TaskManager::test_start_task_manager(); - } - - #[test] - #[sequential] - #[should_panic( - expected = "Error: put_to_sleep: Task with this id is terminated and soon will be removed." - )] - fn test_put_to_sleep_terminated_task() { TaskManager::reset_task_manager(); - TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); - - let task_1 = TaskManager::get_task_from_id(1); - - assert_eq!(TaskManager::get_status(task_1), TaskManager::ready_status()); - - TaskManager::schedule(); - - assert_eq!( - TaskManager::get_status(task_1), - TaskManager::terminated_status() - ); - - TaskManager::add_task( - dummy_setup_fn, - test_put_to_sleep_task_1_loop_fn, - dummy_condition_true, - ); + } - TaskManager::test_start_task_manager(); + fn test_put_to_sleep_task_from_task_loop_fn() { + TaskManager::put_to_sleep(2); } #[test] @@ -184,63 +179,75 @@ mod unit_tests { fn test_put_to_sleep_task_from_task() { TaskManager::reset_task_manager(); TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); - assert_eq!(TaskManager::get_id_from_position(0, 0), 1); + let task_1 = TaskManager::get_task_from_id(1); + + TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); + let task_2 = TaskManager::get_task_from_id(2); + assert_eq!(TaskManager::get_status(task_2), TaskManager::ready_status()); TaskManager::add_task( dummy_setup_fn, - test_put_to_sleep_task_1_loop_fn, + test_put_to_sleep_task_from_task_loop_fn, dummy_condition_true, ); - assert_eq!(TaskManager::get_id_from_position(0, 1), 2); - - let task_1 = TaskManager::get_task_from_id(1); - - assert_eq!(TaskManager::get_status(task_1), TaskManager::ready_status()); TaskManager::test_start_task_manager(); assert_eq!( TaskManager::get_status(task_1), + TaskManager::terminated_status() + ); + assert_eq!( + TaskManager::get_status(task_2), TaskManager::sleeping_status() ); - - assert_eq!(TaskManager::count_all_tasks(), 1); + assert_eq!(TaskManager::count_all_tasks(), 2); } - fn test_wake_up_task_1_loop_fn() { - TaskManager::wake_up(1); + fn test_wake_up_sleeping_task_loop_fn() { + TaskManager::wake_up(2); + } + fn test_put_to_sleep_task_loop_fn() { + TaskManager::put_to_sleep(2); } #[test] #[sequential] fn test_wake_up_sleeping_task() { TaskManager::reset_task_manager(); - TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); - - let task_1 = TaskManager::get_task_from_id(1); - - assert_eq!(TaskManager::get_status(task_1), TaskManager::ready_status()); - TaskManager::add_task( dummy_setup_fn, - test_put_to_sleep_task_1_loop_fn, + test_put_to_sleep_task_loop_fn, dummy_condition_true, ); + TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); + + let task_2 = TaskManager::get_task_from_id(2); + + assert_eq!(TaskManager::get_status(task_2), TaskManager::ready_status()); + + TaskManager::schedule(); TaskManager::schedule(); assert_eq!( - TaskManager::get_status(task_1), + TaskManager::get_status(task_2), TaskManager::sleeping_status() ); TaskManager::add_task( dummy_setup_fn, - test_wake_up_task_1_loop_fn, + test_wake_up_sleeping_task_loop_fn, dummy_condition_true, ); + TaskManager::schedule(); + TaskManager::schedule(); TaskManager::schedule(); - assert_eq!(TaskManager::get_status(task_1), TaskManager::ready_status()); + assert_eq!(TaskManager::get_status(task_2), TaskManager::ready_status()); + } + + fn test_wake_up_non_sleeping_task_loop_fn() { + TaskManager::wake_up(2); } #[test] @@ -248,54 +255,27 @@ mod unit_tests { #[should_panic(expected = "Error: wake_up_task: Task with this id is currently not sleeping.")] fn test_wake_up_non_sleeping_task() { TaskManager::reset_task_manager(); - TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); - - let task_1 = TaskManager::get_task_from_id(1); - - assert_eq!(TaskManager::get_status(task_1), TaskManager::ready_status()); - TaskManager::add_task( dummy_setup_fn, - test_wake_up_task_1_loop_fn, + test_wake_up_non_sleeping_task_loop_fn, dummy_condition_true, ); - - TaskManager::schedule(); - - assert_eq!(TaskManager::get_status(task_1), TaskManager::ready_status()); - } - - fn test_terminate_task_1_loop_fn() { - TaskManager::terminate_task(1); - } - - #[test] - #[sequential] - #[should_panic(expected = "Error: terminate_task: Task with this id is currently terminated.")] - fn test_terminate_terminated_task() { - TaskManager::reset_task_manager(); TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); - let task_1 = TaskManager::get_task_from_id(1); - - assert_eq!(TaskManager::get_status(task_1), TaskManager::ready_status()); - - TaskManager::schedule(); - - assert_eq!( - TaskManager::get_status(task_1), - TaskManager::terminated_status() - ); + let task_2 = TaskManager::get_task_from_id(2); - TaskManager::add_task( - dummy_setup_fn, - test_terminate_task_1_loop_fn, - dummy_condition_true, - ); + assert_eq!(TaskManager::get_status(task_2), TaskManager::ready_status()); TaskManager::test_start_task_manager(); } + fn test_terminate_terminated_task_loop_fn() { + TaskManager::terminate_task(2); + } + + fn test_terminate_non_terminated_task_loop_fn() { + TaskManager::terminate_task(2); + } fn infinite_loop_fn() { loop {} } @@ -303,58 +283,59 @@ mod unit_tests { #[sequential] fn test_terminate_non_terminated_task() { TaskManager::reset_task_manager(); - TaskManager::add_task(dummy_setup_fn, infinite_loop_fn, dummy_condition_true); - - let task_1 = TaskManager::get_task_from_id(1); - - assert_eq!(TaskManager::get_status(task_1), TaskManager::ready_status()); - TaskManager::add_task( dummy_setup_fn, - test_terminate_task_1_loop_fn, + test_terminate_non_terminated_task_loop_fn, dummy_condition_true, ); - TaskManager::test_start_task_manager(); - - assert_eq!(TaskManager::count_all_tasks(), 0); - } - - thread_local! { - static EXEC_ORDER: RefCell> = RefCell::new(Vec::new()); - } - #[test] - #[sequential] - fn test_get_next_task_same_priority() { - TaskManager::reset_task_manager(); - fn first_task_loop_fn() { - EXEC_ORDER.with(|order| { - order.borrow_mut().push("first"); - }); - } + TaskManager::add_task(dummy_setup_fn, infinite_loop_fn, dummy_condition_true); - fn second_task_loop_fn() { - EXEC_ORDER.with(|order| { - order.borrow_mut().push("second"); - }); - } + let task_2 = TaskManager::get_task_from_id(2); - fn third_task_loop_fn() { - EXEC_ORDER.with(|order| { - order.borrow_mut().push("third"); - }); - } - TaskManager::add_task(dummy_setup_fn, first_task_loop_fn, dummy_condition_true); - TaskManager::add_task(dummy_setup_fn, second_task_loop_fn, dummy_condition_true); - TaskManager::add_task(dummy_setup_fn, third_task_loop_fn, dummy_condition_true); + assert_eq!(TaskManager::get_status(task_2), TaskManager::ready_status()); TaskManager::test_start_task_manager(); - EXEC_ORDER.with(|order| { - assert_eq!(*order.borrow(), ["third", "second", "first"]); - }); + assert_eq!(TaskManager::count_all_tasks(), 0); + TaskManager::reset_task_manager(); } + // thread_local! { + // static EXEC_ORDER: RefCell> = RefCell::new(Vec::new()); + // } + // #[test] + // #[sequential] + // fn test_get_next_task_same_priority() { + // TaskManager::reset_task_manager(); + // fn first_task_loop_fn() { + // EXEC_ORDER.with(|order| { + // order.borrow_mut().push("first"); + // }); + // } + // + // fn second_task_loop_fn() { + // EXEC_ORDER.with(|order| { + // order.borrow_mut().push("second"); + // }); + // } + // + // fn third_task_loop_fn() { + // EXEC_ORDER.with(|order| { + // order.borrow_mut().push("third"); + // }); + // } + // TaskManager::add_task(dummy_setup_fn, first_task_loop_fn, dummy_condition_true); + // TaskManager::add_task(dummy_setup_fn, second_task_loop_fn, dummy_condition_true); + // TaskManager::add_task(dummy_setup_fn, third_task_loop_fn, dummy_condition_true); + // + // TaskManager::test_start_task_manager(); + // + // EXEC_ORDER.with(|order| { + // assert_eq!(*order.borrow(), ["third", "second", "first"]); + // }); + // } + #[test] #[sequential] /// Tests if task manager without tasks works during some time. @@ -362,6 +343,7 @@ mod unit_tests { TaskManager::reset_task_manager(); TaskManager::test_start_task_manager(); assert!(TaskManager::has_no_tasks()); + TaskManager::reset_task_manager(); } /// Counter for a task for test_one_finite_task_task_manager. @@ -398,6 +380,7 @@ mod unit_tests { unsafe { TEST_ONE_FINITE_TASK_TASK_MANAGER_COUNTER.as_ptr().read() }, 50 ); + TaskManager::reset_task_manager(); } /// Counter for a task for test_one_infinite_task_task_manager. @@ -416,6 +399,7 @@ mod unit_tests { #[sequential] /// Tests if task manager with one infinite task works correctly during some time without panic. fn test_one_infinite_task_task_manager() { + TaskManager::reset_task_manager(); TaskManager::add_task( test_one_infinite_task_task_manager_setup_fn, test_one_infinite_task_task_manager_loop_fn, @@ -482,6 +466,7 @@ mod unit_tests { unsafe { TEST_TWO_FINITE_TASK_TASK_MANAGER_COUNTER2.as_ptr().read() }, 25 ); + TaskManager::reset_task_manager(); } /// Counter for a task for test_two_different_tasks_task_manager. @@ -541,6 +526,7 @@ mod unit_tests { }, 50 ); + TaskManager::reset_task_manager(); } /// Counter for a task for test_two_infinite_tasks_task_manager. @@ -583,6 +569,7 @@ mod unit_tests { test_two_infinite_tasks_task_manager_stop_condition_fn2, ); TaskManager::test_start_task_manager(); + TaskManager::reset_task_manager(); } /// Counter for a task for test_setup_task_manager. @@ -613,37 +600,6 @@ mod unit_tests { unsafe { TEST_SETUP_TASK_MANAGER_COUNTER.as_ptr().read() }, 42 ); - } - - #[test] - /// Tests setup timer function and getting counter value (bad unit test). - fn test_setup_timer() { - Timer::setup_timer(); - let timer = Timer::get_timer(0) - .expect("The timer is already active or a timer with this index does not exist."); - assert_eq!(timer.get_time().as_micros(), 0); - timer.release_timer(); - } - - #[test] - /// Tests loop timer function. - fn test_loop_timer() { - Timer::setup_timer(); - let mut timer = Timer::get_timer(0) - .expect("The timer is already active or a timer with this index does not exist."); - timer.loop_timer(); - assert_eq!(timer.get_time().as_micros(), 0); - timer.release_timer(); - } - - #[test] - /// Tests stop condition timer function. - fn test_stop_condition_timer() { - let timer = Timer::get_timer(0) - .expect("The timer is already active or a timer with this index does not exist."); - timer.change_period_timer(Duration::new(10, 0)); - timer.start_timer(); - assert!(!timer.stop_condition_timer()); - timer.release_timer(); + TaskManager::reset_task_manager(); } } From e5bc524f4e6cf7c5e77fb01bd9c38af21a4bcc33 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Thu, 19 Dec 2024 17:56:22 +0300 Subject: [PATCH 39/50] Fix code according to tests --- src/task_manager/cooperative.rs | 57 +++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index 0409385..ae32dc7 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -2,7 +2,7 @@ extern crate alloc; use crate::task_manager::{ task::{Task, TaskLoopFunctionType, TaskSetupFunctionType, TaskStopConditionFunctionType}, - TaskManagerTrait, TASK_MANAGER, + TaskManager, TaskManagerTrait, TASK_MANAGER, }; use alloc::vec::Vec; @@ -53,7 +53,7 @@ pub struct CooperativeTaskManager { pub(crate) tasks: [Vec; NUM_PRIORITIES], /// ```id``` of a task that will be created the next. The First task has id 1. pub(crate) next_task_id: TaskIdType, - pub(crate) current_task_id: TaskIdType, + pub(crate) exec_task_id: TaskIdType, } /// Cooperative implementation of ```TaskManagerTrait```. @@ -96,7 +96,7 @@ impl CooperativeTaskManager { CooperativeTaskManager { tasks, next_task_id: 0, - current_task_id: 0, + exec_task_id: 0, } } @@ -116,6 +116,12 @@ impl CooperativeTaskManager { CooperativeTaskManager::create_task(setup_fn, loop_fn, stop_condition_fn, priority); (new_task.core.setup_fn)(); CooperativeTaskManager::push_to_queue(new_task); + + unsafe { + if TASK_MANAGER.exec_task_id == 0 { + TASK_MANAGER.exec_task_id = TASK_MANAGER.next_task_id; + } + } } fn create_task( @@ -132,7 +138,7 @@ impl CooperativeTaskManager { // TODO: Handling of tasks' id overflow. unsafe { - TASK_MANAGER.next_task_id += 1; + TASK_MANAGER.next_task_id = TASK_MANAGER.next_task_id.wrapping_add(1); let task_id = TASK_MANAGER.next_task_id; CooperativeTask { core: task, @@ -153,7 +159,7 @@ impl CooperativeTaskManager { } } } - panic!("Error: get_task_from_id: Task with this id not found."); + panic!("Error: get_task_from_id: Task with id {} not found.", id); } } @@ -202,10 +208,6 @@ impl CooperativeTaskManager { /// Task can terminate and delete another task by ```id``` even if it executes. pub fn terminate_task(id: TaskIdType) { let task = CooperativeTaskManager::get_task_from_id(id); - if task.status == TaskStatusType::Terminated { - panic!("Error: terminate_task: Task with this id is currently terminated."); - } - task.status = TaskStatusType::Terminated; CooperativeTaskManager::delete_task(task); } @@ -220,29 +222,31 @@ impl CooperativeTaskManager { /// One task manager iteration. pub fn schedule() { if CooperativeTaskManager::has_tasks() { - let task = CooperativeTaskManager::get_next_task(); + let task_id = unsafe { TASK_MANAGER.exec_task_id }; + let task = CooperativeTaskManager::get_task_from_id(task_id); match task.status { TaskStatusType::Ready => { task.status = TaskStatusType::Running; - (task.core.loop_fn)(); - if (task.core.stop_condition_fn)() { - task.status = TaskStatusType::Terminated; - } else { - task.status = TaskStatusType::Ready; - } } TaskStatusType::Running => { + (task.core.loop_fn)(); if (task.core.stop_condition_fn)() { task.status = TaskStatusType::Terminated; - } else { - task.status = TaskStatusType::Running; } } TaskStatusType::Sleeping => {} TaskStatusType::Terminated => { - CooperativeTaskManager::delete_task(task); + CooperativeTaskManager::terminate_task(task_id); } } + if task.status != TaskStatusType::Running { + unsafe { + let Some(next_exec_id) = CooperativeTaskManager::get_next_task_id() else { + return; + }; + unsafe { TASK_MANAGER.exec_task_id = next_exec_id } + }; + } } } @@ -258,6 +262,8 @@ impl CooperativeTaskManager { let vec = &mut TASK_MANAGER.tasks[task.priority]; if let Some(pos) = vec.iter().position(|vec_task| vec_task.id == task.id) { vec.remove(pos); + } else { + panic!("Error: delete_task: Task with this id not found in the task list."); } } } @@ -273,16 +279,15 @@ impl CooperativeTaskManager { false } - fn get_next_task<'a>() -> &'a mut CooperativeTask { + fn get_next_task_id() -> Option { unsafe { - for vec in TASK_MANAGER.tasks.iter_mut() { + for vec in TASK_MANAGER.tasks.iter_mut().rev() { if let Some(task) = vec.last_mut() { - TASK_MANAGER.current_task_id = task.id; - return task; + return Some(task.id); } } } - panic!("Error: get_next_task: No tasks currently, waiting for new tasks."); + None } /// Starts task manager work. Returns after 1000 steps only for testing task_manager_step. @@ -293,6 +298,9 @@ impl CooperativeTaskManager { } pub fn count_tasks_with_priority(priority: TaskPriorityType) -> usize { + if priority >= NUM_PRIORITIES { + panic!("Error: count_tasks_with_priority: Task's priority is invalid. It must be between 0 and 11."); + } unsafe { TASK_MANAGER.tasks[priority].len() } } @@ -310,6 +318,7 @@ impl CooperativeTaskManager { vec.clear(); } TASK_MANAGER.next_task_id = 0; + TASK_MANAGER.exec_task_id = 0; } } From bf579400c0799c5d4fd4e80a9e340218603a8760 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Thu, 19 Dec 2024 17:57:20 +0300 Subject: [PATCH 40/50] Add timer_unit_tests to separate file --- tests/timer_unit_tests.rs | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 tests/timer_unit_tests.rs diff --git a/tests/timer_unit_tests.rs b/tests/timer_unit_tests.rs new file mode 100644 index 0000000..dd4121a --- /dev/null +++ b/tests/timer_unit_tests.rs @@ -0,0 +1,37 @@ +#[cfg(all(test, not(feature = "mips64_timer_tests")))] +mod timer_unit_tests { + use martos::timer::Timer; + use std::time::Duration; + + #[test] + /// Tests setup timer function and getting counter value (bad unit test). + fn test_setup_timer() { + Timer::setup_timer(); + let timer = Timer::get_timer(0) + .expect("The timer is already active or a timer with this index does not exist."); + assert_eq!(timer.get_time().as_micros(), 0); + timer.release_timer(); + } + + #[test] + /// Tests loop timer function. + fn test_loop_timer() { + Timer::setup_timer(); + let mut timer = Timer::get_timer(0) + .expect("The timer is already active or a timer with this index does not exist."); + timer.loop_timer(); + assert_eq!(timer.get_time().as_micros(), 0); + timer.release_timer(); + } + + #[test] + /// Tests stop condition timer function. + fn test_stop_condition_timer() { + let timer = Timer::get_timer(0) + .expect("The timer is already active or a timer with this index does not exist."); + timer.change_period_timer(Duration::new(10, 0)); + timer.start_timer(); + assert!(!timer.stop_condition_timer()); + timer.release_timer(); + } +} From f231a08717f32aea3e9e3141ad03563d432838ed Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Sun, 22 Dec 2024 12:22:20 +0300 Subject: [PATCH 41/50] Refactor tests, add more comments --- tests/task_manager_unit_tests.rs | 158 +++++++------------------------ 1 file changed, 35 insertions(+), 123 deletions(-) diff --git a/tests/task_manager_unit_tests.rs b/tests/task_manager_unit_tests.rs index 2ff49f2..513e293 100644 --- a/tests/task_manager_unit_tests.rs +++ b/tests/task_manager_unit_tests.rs @@ -1,16 +1,16 @@ -// #[cfg(all(test, not(feature = "mips64_timer_tests")))] mod task_manager_unit_tests { use martos::task_manager::{TaskManager, TaskManagerTrait}; use sequential_test::sequential; use std::sync::atomic::{AtomicU32, Ordering}; - // TODO: refactor unit tests. They should check less. Separate tests for setup, loop and stop functions. - // TODO: refactor unit tests. Task manager and timer tests should be in different files in one directory. fn dummy_setup_fn() {} fn dummy_loop_fn() {} fn dummy_condition_true() -> bool { true } + fn dummy_condition_false() -> bool { + false + } #[test] #[sequential] @@ -27,10 +27,10 @@ mod task_manager_unit_tests { #[should_panic( expected = "Error: add_task: Task's priority is invalid. It must be between 0 and 11." )] - /// Test add a task with nonexistent priority fn test_add_task_invalid_priority() { TaskManager::reset_task_manager(); TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 100); + TaskManager::test_start_task_manager(); } @@ -45,7 +45,6 @@ mod task_manager_unit_tests { assert_eq!(TaskManager::count_tasks_with_priority(0), 2); assert_eq!(TaskManager::count_tasks_with_priority(1), 1); assert_eq!(TaskManager::count_all_tasks(), 3); - TaskManager::reset_task_manager(); } #[test] @@ -55,7 +54,6 @@ mod task_manager_unit_tests { TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); assert_eq!(TaskManager::count_tasks_with_priority(0), 1); assert_eq!(TaskManager::count_all_tasks(), 1); - TaskManager::reset_task_manager(); } #[test] @@ -64,8 +62,7 @@ mod task_manager_unit_tests { TaskManager::reset_task_manager(); TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 10); let id = TaskManager::get_id_from_position(10, 0); - - let found_task = TaskManager::get_task_from_id(id); + let found_task = TaskManager::get_task_by_id(id); assert_eq!(id, TaskManager::get_id_from_task(found_task)); TaskManager::reset_task_manager(); @@ -77,7 +74,7 @@ mod task_manager_unit_tests { fn test_get_task_by_invalid_id() { TaskManager::reset_task_manager(); TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 10); - let found_task = TaskManager::get_task_from_id(2); + let found_task = TaskManager::get_task_by_id(2); TaskManager::reset_task_manager(); } @@ -110,15 +107,15 @@ mod task_manager_unit_tests { TaskManager::reset_task_manager(); TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); - let task = TaskManager::get_task_from_id(1); + let task = TaskManager::get_task_by_id(1); assert_eq!(TaskManager::get_id_from_task(task), 1); TaskManager::reset_task_manager(); } + /// Loop function for task for test_put_to_sleep_running_task_loop_fn. fn test_put_to_sleep_running_task_loop_fn() { TaskManager::put_to_sleep(1); } - #[test] #[sequential] #[should_panic(expected = "Error: put_to_sleep: Task with this id is currently running.")] @@ -135,6 +132,7 @@ mod task_manager_unit_tests { TaskManager::reset_task_manager(); } + /// Loop function for task for test_put_to_sleep_sleeping_task_loop_fn. fn test_put_to_sleep_sleeping_task_loop_fn() { TaskManager::put_to_sleep(2); } @@ -151,7 +149,7 @@ mod task_manager_unit_tests { dummy_condition_true, ); TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); - let task_2 = TaskManager::get_task_from_id(2); + let task_2 = TaskManager::get_task_by_id(2); assert_eq!(TaskManager::get_status(task_2), TaskManager::ready_status()); TaskManager::schedule(); TaskManager::schedule(); @@ -170,19 +168,19 @@ mod task_manager_unit_tests { TaskManager::reset_task_manager(); } + /// Loop function for task for test_put_to_sleep_task_from_task_loop_fn. fn test_put_to_sleep_task_from_task_loop_fn() { TaskManager::put_to_sleep(2); } - #[test] #[sequential] fn test_put_to_sleep_task_from_task() { TaskManager::reset_task_manager(); TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); - let task_1 = TaskManager::get_task_from_id(1); + let task_1 = TaskManager::get_task_by_id(1); TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); - let task_2 = TaskManager::get_task_from_id(2); + let task_2 = TaskManager::get_task_by_id(2); assert_eq!(TaskManager::get_status(task_2), TaskManager::ready_status()); TaskManager::add_task( @@ -190,7 +188,6 @@ mod task_manager_unit_tests { test_put_to_sleep_task_from_task_loop_fn, dummy_condition_true, ); - TaskManager::test_start_task_manager(); assert_eq!( @@ -204,13 +201,13 @@ mod task_manager_unit_tests { assert_eq!(TaskManager::count_all_tasks(), 2); } + /// Loop functions for task for test_wake_up_sleeping_task. fn test_wake_up_sleeping_task_loop_fn() { TaskManager::wake_up(2); } fn test_put_to_sleep_task_loop_fn() { TaskManager::put_to_sleep(2); } - #[test] #[sequential] fn test_wake_up_sleeping_task() { @@ -221,13 +218,13 @@ mod task_manager_unit_tests { dummy_condition_true, ); TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); - - let task_2 = TaskManager::get_task_from_id(2); + let task_2 = TaskManager::get_task_by_id(2); assert_eq!(TaskManager::get_status(task_2), TaskManager::ready_status()); TaskManager::schedule(); TaskManager::schedule(); + assert_eq!( TaskManager::get_status(task_2), TaskManager::sleeping_status() @@ -238,7 +235,6 @@ mod task_manager_unit_tests { test_wake_up_sleeping_task_loop_fn, dummy_condition_true, ); - TaskManager::schedule(); TaskManager::schedule(); TaskManager::schedule(); @@ -246,10 +242,10 @@ mod task_manager_unit_tests { assert_eq!(TaskManager::get_status(task_2), TaskManager::ready_status()); } + /// Loop functions for task for test_wake_up_non_sleeping_task_loop_fn. fn test_wake_up_non_sleeping_task_loop_fn() { TaskManager::wake_up(2); } - #[test] #[sequential] #[should_panic(expected = "Error: wake_up_task: Task with this id is currently not sleeping.")] @@ -261,18 +257,13 @@ mod task_manager_unit_tests { dummy_condition_true, ); TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); - - let task_2 = TaskManager::get_task_from_id(2); + let task_2 = TaskManager::get_task_by_id(2); assert_eq!(TaskManager::get_status(task_2), TaskManager::ready_status()); - TaskManager::test_start_task_manager(); } - fn test_terminate_terminated_task_loop_fn() { - TaskManager::terminate_task(2); - } - + /// Loop functions for task for test_terminate_non_terminated_task. fn test_terminate_non_terminated_task_loop_fn() { TaskManager::terminate_task(2); } @@ -288,54 +279,14 @@ mod task_manager_unit_tests { test_terminate_non_terminated_task_loop_fn, dummy_condition_true, ); - TaskManager::add_task(dummy_setup_fn, infinite_loop_fn, dummy_condition_true); - - let task_2 = TaskManager::get_task_from_id(2); + let task_2 = TaskManager::get_task_by_id(2); assert_eq!(TaskManager::get_status(task_2), TaskManager::ready_status()); - TaskManager::test_start_task_manager(); - assert_eq!(TaskManager::count_all_tasks(), 0); - TaskManager::reset_task_manager(); } - // thread_local! { - // static EXEC_ORDER: RefCell> = RefCell::new(Vec::new()); - // } - // #[test] - // #[sequential] - // fn test_get_next_task_same_priority() { - // TaskManager::reset_task_manager(); - // fn first_task_loop_fn() { - // EXEC_ORDER.with(|order| { - // order.borrow_mut().push("first"); - // }); - // } - // - // fn second_task_loop_fn() { - // EXEC_ORDER.with(|order| { - // order.borrow_mut().push("second"); - // }); - // } - // - // fn third_task_loop_fn() { - // EXEC_ORDER.with(|order| { - // order.borrow_mut().push("third"); - // }); - // } - // TaskManager::add_task(dummy_setup_fn, first_task_loop_fn, dummy_condition_true); - // TaskManager::add_task(dummy_setup_fn, second_task_loop_fn, dummy_condition_true); - // TaskManager::add_task(dummy_setup_fn, third_task_loop_fn, dummy_condition_true); - // - // TaskManager::test_start_task_manager(); - // - // EXEC_ORDER.with(|order| { - // assert_eq!(*order.borrow(), ["third", "second", "first"]); - // }); - // } - #[test] #[sequential] /// Tests if task manager without tasks works during some time. @@ -343,13 +294,10 @@ mod task_manager_unit_tests { TaskManager::reset_task_manager(); TaskManager::test_start_task_manager(); assert!(TaskManager::has_no_tasks()); - TaskManager::reset_task_manager(); } /// Counter for a task for test_one_finite_task_task_manager. static TEST_ONE_FINITE_TASK_TASK_MANAGER_COUNTER: AtomicU32 = AtomicU32::new(1); - /// Setup function for task for test_one_finite_task_task_manager. - fn test_one_finite_task_task_manager_setup_fn() {} /// Loop function for task for test_one_finite_task_task_manager. fn test_one_finite_task_task_manager_loop_fn() { TEST_ONE_FINITE_TASK_TASK_MANAGER_COUNTER.fetch_add(1, Ordering::Relaxed); @@ -370,7 +318,7 @@ mod task_manager_unit_tests { fn test_one_finite_task_task_manager() { TaskManager::reset_task_manager(); TaskManager::add_task( - test_one_finite_task_task_manager_setup_fn, + dummy_setup_fn, test_one_finite_task_task_manager_loop_fn, test_one_finite_task_task_manager_stop_condition_fn, ); @@ -380,13 +328,10 @@ mod task_manager_unit_tests { unsafe { TEST_ONE_FINITE_TASK_TASK_MANAGER_COUNTER.as_ptr().read() }, 50 ); - TaskManager::reset_task_manager(); } /// Counter for a task for test_one_infinite_task_task_manager. static TEST_ONE_INFINITE_TASK_TASK_MANAGER_COUNTER: AtomicU32 = AtomicU32::new(1); - /// Setup function for task for test_one_infinite_task_task_manager. - fn test_one_infinite_task_task_manager_setup_fn() {} /// Loop function for task for test_one_infinite_task_task_manager. fn test_one_infinite_task_task_manager_loop_fn() { TEST_ONE_INFINITE_TASK_TASK_MANAGER_COUNTER.fetch_add(1, Ordering::Relaxed); @@ -401,18 +346,15 @@ mod task_manager_unit_tests { fn test_one_infinite_task_task_manager() { TaskManager::reset_task_manager(); TaskManager::add_task( - test_one_infinite_task_task_manager_setup_fn, + dummy_setup_fn, test_one_infinite_task_task_manager_loop_fn, test_one_infinite_task_task_manager_stop_condition_fn, ); TaskManager::test_start_task_manager(); - TaskManager::reset_task_manager(); } /// Counter for a task for test_two_finite_tasks_task_manager. static TEST_TWO_FINITE_TASK_TASK_MANAGER_COUNTER1: AtomicU32 = AtomicU32::new(1); - /// Setup function for task for test_two_finite_tasks_task_manager. - fn test_two_finite_tasks_task_manager_setup_fn1() {} /// Loop function for task for test_two_finite_tasks_task_manager. fn test_two_finite_tasks_task_manager_loop_fn1() { TEST_TWO_FINITE_TASK_TASK_MANAGER_COUNTER1.fetch_add(1, Ordering::Relaxed); @@ -427,8 +369,6 @@ mod task_manager_unit_tests { } /// Counter for a task for test_two_finite_tasks_task_manager. static TEST_TWO_FINITE_TASK_TASK_MANAGER_COUNTER2: AtomicU32 = AtomicU32::new(1); - /// Setup function for task for test_two_finite_tasks_task_manager. - fn test_two_finite_tasks_task_manager_setup_fn2() {} /// Loop function for task for test_two_finite_tasks_task_manager. fn test_two_finite_tasks_task_manager_loop_fn2() { TEST_TWO_FINITE_TASK_TASK_MANAGER_COUNTER2.fetch_add(1, Ordering::Relaxed); @@ -447,12 +387,12 @@ mod task_manager_unit_tests { fn test_two_finite_tasks_task_manager() { TaskManager::reset_task_manager(); TaskManager::add_task( - test_two_finite_tasks_task_manager_setup_fn1, + dummy_setup_fn, test_two_finite_tasks_task_manager_loop_fn1, test_two_finite_tasks_task_manager_stop_condition_fn1, ); TaskManager::add_task( - test_two_finite_tasks_task_manager_setup_fn2, + dummy_setup_fn, test_two_finite_tasks_task_manager_loop_fn2, test_two_finite_tasks_task_manager_stop_condition_fn2, ); @@ -466,13 +406,10 @@ mod task_manager_unit_tests { unsafe { TEST_TWO_FINITE_TASK_TASK_MANAGER_COUNTER2.as_ptr().read() }, 25 ); - TaskManager::reset_task_manager(); } /// Counter for a task for test_two_different_tasks_task_manager. static TEST_TWO_DIFFERENT_TASK_TASK_MANAGER_COUNTER1: AtomicU32 = AtomicU32::new(1); - /// Setup function for task for test_two_different_tasks_task_manager. - fn test_two_different_tasks_task_manager_setup_fn1() {} /// Loop function for task for test_two_different_tasks_task_manager. fn test_two_different_tasks_task_manager_loop_fn1() { TEST_TWO_DIFFERENT_TASK_TASK_MANAGER_COUNTER1.fetch_add(1, Ordering::Relaxed); @@ -491,30 +428,24 @@ mod task_manager_unit_tests { } /// Counter for a task for test_two_different_tasks_task_manager. static TEST_TWO_DIFFERENT_TASK_TASK_MANAGER_COUNTER2: AtomicU32 = AtomicU32::new(1); - /// Setup function for task for test_two_different_tasks_task_manager. - fn test_two_different_tasks_task_manager_setup_fn2() {} /// Loop function for task for test_two_different_tasks_task_manager. fn test_two_different_tasks_task_manager_loop_fn2() { TEST_TWO_DIFFERENT_TASK_TASK_MANAGER_COUNTER2.fetch_add(1, Ordering::Relaxed); } - /// Stop function for a task for test_two_different_tasks_task_manager. - fn test_two_different_tasks_task_manager_stop_condition_fn2() -> bool { - false - } #[test] #[sequential] /// Tests if task manager with two different (finite and infinite) tasks works correctly during some time without panic. fn test_two_different_tasks_task_manager() { TaskManager::reset_task_manager(); TaskManager::add_task( - test_two_different_tasks_task_manager_setup_fn1, + dummy_setup_fn, test_two_different_tasks_task_manager_loop_fn1, test_two_different_tasks_task_manager_stop_condition_fn1, ); TaskManager::add_task( - test_two_different_tasks_task_manager_setup_fn2, + dummy_setup_fn, test_two_different_tasks_task_manager_loop_fn2, - test_two_different_tasks_task_manager_stop_condition_fn2, + dummy_condition_false, ); TaskManager::test_start_task_manager(); @@ -526,50 +457,38 @@ mod task_manager_unit_tests { }, 50 ); - TaskManager::reset_task_manager(); } /// Counter for a task for test_two_infinite_tasks_task_manager. static TEST_TWO_INFINITE_TASK_TASK_MANAGER_COUNTER1: AtomicU32 = AtomicU32::new(1); - /// Setup function for task for test_two_infinite_tasks_task_manager. - fn test_two_infinite_tasks_task_manager_setup_fn1() {} /// Loop function for task for test_two_infinite_tasks_task_manager. fn test_two_infinite_tasks_task_manager_loop_fn1() { TEST_TWO_INFINITE_TASK_TASK_MANAGER_COUNTER1.fetch_add(1, Ordering::Relaxed); } - /// Stop function for a task for test_two_infinite_tasks_task_manager. - fn test_two_infinite_tasks_task_manager_stop_condition_fn1() -> bool { - false - } /// Counter for a task for test_two_infinite_tasks_task_manager. static TEST_TWO_INFINITE_TASK_TASK_MANAGER_COUNTER2: AtomicU32 = AtomicU32::new(1); - /// Setup function for task for test_two_infinite_tasks_task_manager. - fn test_two_infinite_tasks_task_manager_setup_fn2() {} /// Loop function for task for test_two_infinite_tasks_task_manager. fn test_two_infinite_tasks_task_manager_loop_fn2() { TEST_TWO_INFINITE_TASK_TASK_MANAGER_COUNTER2.fetch_add(1, Ordering::Relaxed); } - /// Stop function for a task for test_two_infinite_tasks_task_manager. - fn test_two_infinite_tasks_task_manager_stop_condition_fn2() -> bool { - false - } #[test] #[sequential] /// Tests if task manager with two infinite tasks works correctly during some without panic. fn test_two_infinite_tasks_task_manager() { TaskManager::reset_task_manager(); TaskManager::add_task( - test_two_infinite_tasks_task_manager_setup_fn1, + dummy_setup_fn, test_two_infinite_tasks_task_manager_loop_fn1, - test_two_infinite_tasks_task_manager_stop_condition_fn1, + dummy_condition_false, ); TaskManager::add_task( - test_two_infinite_tasks_task_manager_setup_fn2, + dummy_setup_fn, test_two_infinite_tasks_task_manager_loop_fn2, - test_two_infinite_tasks_task_manager_stop_condition_fn2, + dummy_condition_false, ); TaskManager::test_start_task_manager(); - TaskManager::reset_task_manager(); + + assert_eq!(TaskManager::count_all_tasks(), 2); } /// Counter for a task for test_setup_task_manager. @@ -578,12 +497,6 @@ mod task_manager_unit_tests { fn test_setup_task_manager_setup_fn() { TEST_SETUP_TASK_MANAGER_COUNTER.store(42, Ordering::Relaxed); } - /// Loop function for task for test_setup_task_manager. - fn test_setup_task_manager_loop_fn() {} - /// Stop function for task for test_setup_task_manager. - fn test_setup_task_manager_stop_condition_fn() -> bool { - false - } #[test] #[sequential] /// Tests if task manager works correctly with setup function during some time without panic. @@ -591,8 +504,8 @@ mod task_manager_unit_tests { TaskManager::reset_task_manager(); TaskManager::add_task( test_setup_task_manager_setup_fn, - test_setup_task_manager_loop_fn, - test_setup_task_manager_stop_condition_fn, + dummy_loop_fn, + dummy_condition_false, ); TaskManager::test_start_task_manager(); @@ -600,6 +513,5 @@ mod task_manager_unit_tests { unsafe { TEST_SETUP_TASK_MANAGER_COUNTER.as_ptr().read() }, 42 ); - TaskManager::reset_task_manager(); } } From 7790516398733df0943fbe4640609c90b4311b06 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Mon, 23 Dec 2024 15:08:23 +0300 Subject: [PATCH 42/50] Add comments, refactor and change fn new --- src/task_manager/cooperative.rs | 280 ++++++++++++++++++-------------- 1 file changed, 158 insertions(+), 122 deletions(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index ae32dc7..35f38d0 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -2,7 +2,7 @@ extern crate alloc; use crate::task_manager::{ task::{Task, TaskLoopFunctionType, TaskSetupFunctionType, TaskStopConditionFunctionType}, - TaskManager, TaskManagerTrait, TASK_MANAGER, + TaskManagerTrait, TASK_MANAGER, }; use alloc::vec::Vec; @@ -24,9 +24,8 @@ pub enum TaskStatusType { /// Task status when it is sleeping. After waking up, a task again starts loop_fn. Sleeping, /// Task status when it terminated. - /// It can be in both cases - /// when a task is finished and when the other task called ```terminate_task``` function - /// with id of a task that will be terminated. + /// It can be in both cases when a task is finished and when the other task called + /// ```terminate_task``` function with id of a task that will be terminated. Terminated, } @@ -50,16 +49,16 @@ pub struct CooperativeTask { #[repr(C)] pub struct CooperativeTaskManager { /// Array of vectors with ```CooperativeTask``` to execute. - pub(crate) tasks: [Vec; NUM_PRIORITIES], + pub(crate) tasks: [Option>; NUM_PRIORITIES], /// ```id``` of a task that will be created the next. The First task has id 1. pub(crate) next_task_id: TaskIdType, + /// ```id``` of executing task. pub(crate) exec_task_id: TaskIdType, } /// Cooperative implementation of ```TaskManagerTrait```. impl TaskManagerTrait for CooperativeTaskManager { - /// Add a task to task manager. - /// It should pass setup, loop, and condition functions. + /// Add a task to task manager. It should pass setup, loop, and condition functions. /// Task added with this function has ```priority``` 0. fn add_task( setup_fn: TaskSetupFunctionType, @@ -69,7 +68,7 @@ impl TaskManagerTrait for CooperativeTaskManager { CooperativeTaskManager::add_priority_task(setup_fn, loop_fn, stop_condition_fn, 0); } - /// Starts task manager work. + /// Start task manager work. fn start_task_manager() -> ! { loop { CooperativeTaskManager::schedule(); @@ -78,30 +77,16 @@ impl TaskManagerTrait for CooperativeTaskManager { } impl CooperativeTaskManager { - /// Creates new task manager. + /// Create new task manager. pub(crate) const fn new() -> CooperativeTaskManager { - let tasks = [ - Vec::new(), - Vec::new(), - Vec::new(), - Vec::new(), - Vec::new(), - Vec::new(), - Vec::new(), - Vec::new(), - Vec::new(), - Vec::new(), - Vec::new(), - ]; CooperativeTaskManager { - tasks, + tasks: [None; NUM_PRIORITIES], next_task_id: 0, exec_task_id: 0, } } - /// Add a task to task manager. - /// It should pass setup, loop, and condition functions. + /// Add a task to task manager. It should pass setup, loop, and condition functions. /// Task added with this function has given priority. pub fn add_priority_task( setup_fn: TaskSetupFunctionType, @@ -110,8 +95,9 @@ impl CooperativeTaskManager { priority: TaskPriorityType, ) { if priority >= NUM_PRIORITIES { - panic!("Error: add_task: Task's priority is invalid. It must be between 0 and 11."); + panic!("Error: add_priority_task: Task's priority {} is invalid. It must be between 0 and {}.", priority, NUM_PRIORITIES); } + let new_task = CooperativeTaskManager::create_task(setup_fn, loop_fn, stop_condition_fn, priority); (new_task.core.setup_fn)(); @@ -124,6 +110,7 @@ impl CooperativeTaskManager { } } + /// Helper function for ```add_priority_task```. fn create_task( setup_fn: TaskSetupFunctionType, loop_fn: TaskLoopFunctionType, @@ -136,7 +123,6 @@ impl CooperativeTaskManager { stop_condition_fn, }; - // TODO: Handling of tasks' id overflow. unsafe { TASK_MANAGER.next_task_id = TASK_MANAGER.next_task_id.wrapping_add(1); let task_id = TASK_MANAGER.next_task_id; @@ -149,36 +135,9 @@ impl CooperativeTaskManager { } } - /// Find a task by ```id``` and return it. - pub fn get_task_from_id<'a>(id: TaskIdType) -> &'a mut CooperativeTask { - unsafe { - for vec in TASK_MANAGER.tasks.iter_mut() { - for task in vec.iter_mut() { - if task.id == id { - return task; - } - } - } - panic!("Error: get_task_from_id: Task with id {} not found.", id); - } - } - - pub fn get_id_from_position(priority: TaskPriorityType, position: usize) -> TaskIdType { - unsafe { - TASK_MANAGER.tasks[priority] - .get(position) - .unwrap_or_else(|| panic!("Error: get_id_from_position: Position out of bounds.")) - .id - } - } - - pub fn get_id_from_task(task: &mut CooperativeTask) -> TaskIdType { - task.id - } - - /// Task can put to sleep another task by ```id```. + /// Task can put to sleep another task in ```Ready``` state by its ```id```. pub fn put_to_sleep(id: TaskIdType) { - let task = CooperativeTaskManager::get_task_from_id(id); + let task = CooperativeTaskManager::get_task_by_id(id); match task.status { TaskStatusType::Running => { panic!("Error: put_to_sleep: Task with this id is currently running."); @@ -188,42 +147,121 @@ impl CooperativeTaskManager { } TaskStatusType::Terminated => { panic!( - "Error: put_to_sleep: Task with this id is terminated and soon will be removed." - ); + "Error: put_to_sleep: Task with this id is terminated and soon will be removed." + ); } TaskStatusType::Ready => { - task.status = TaskStatusType::Sleeping; // Need wake up function? + task.status = TaskStatusType::Sleeping; } } } - pub fn wake_up(id: TaskIdType) { - let task = CooperativeTaskManager::get_task_from_id(id); - if task.status != TaskStatusType::Sleeping { - panic!("Error: wake_up_task: Task with this id is currently not sleeping."); - } - task.status = TaskStatusType::Ready; - } - - /// Task can terminate and delete another task by ```id``` even if it executes. + /// Task can terminate and delete another task by ```id```.ы pub fn terminate_task(id: TaskIdType) { - let task = CooperativeTaskManager::get_task_from_id(id); + let task = CooperativeTaskManager::get_task_by_id(id); CooperativeTaskManager::delete_task(task); } + /// Wake up task in ```Sleeping``` state. Otherwise, panic. pub fn wake_up_task(id: TaskIdType) { - let task = CooperativeTaskManager::get_task_from_id(id); + let task = CooperativeTaskManager::get_task_by_id(id); if task.status != TaskStatusType::Sleeping { - panic!("Error: wake_up_task: Task with this id is currently not sleeping."); + panic!( + "Error: wake_up_task: Task with id {} is currently not sleeping.", + id + ); } task.status = TaskStatusType::Ready; } + /// Remove task from ```tasks``` queue. + fn delete_task(task: &mut CooperativeTask) { + unsafe { + if let Some(vec) = TASK_MANAGER.tasks[task.priority].as_mut() { + if let Some(pos) = vec.iter().position(|vec_task| vec_task.id == task.id) { + vec.remove(pos); + } else { + panic!( + "Error: delete_task: Task with id {} not found in the task list.", + task.id + ); + } + } + } + } + + /// Get a task by ```id``` and return it. + pub fn get_task_by_id<'a>(id: TaskIdType) -> &'a mut CooperativeTask { + unsafe { + for vec_opt in TASK_MANAGER.tasks.iter_mut() { + if let Some(vec) = vec_opt { + for task in vec.iter_mut() { + if task.id == id { + return task; + } + } + } + } + panic!("Error: get_task_by_id: Task with id {} not found.", id); + } + } + + /// Get task ```id``` by its position in ```tasks``` vector. + pub fn get_id_by_position(priority: TaskPriorityType, position: usize) -> TaskIdType { + if priority >= NUM_PRIORITIES { + panic!("Error: get_id_by_priorities: Task's priority {} is invalid. It must be between 0 and {}.", priority, NUM_PRIORITIES); + } + unsafe { + if TASK_MANAGER.tasks[priority].is_none() { + panic!( + "Error: get_id_by_position: No tasks found for priority {}.", + priority + ); + } + TASK_MANAGER.tasks[priority] + .as_ref() + .unwrap() + .get(position) + .unwrap() + .id + } + } + + /// Push task to the queue. + fn push_to_queue(task: CooperativeTask) { + unsafe { + let priority = task.priority; + while TASK_MANAGER.tasks.len() <= priority { + TASK_MANAGER.tasks.push(None); + } + + if TASK_MANAGER.tasks[priority].is_none() { + TASK_MANAGER.tasks[priority] = Some(Vec::new()); + } + + TASK_MANAGER.tasks[priority].as_mut().unwrap().push(task); + } + } + + /// Get id of task to be executed next. + fn get_next_task_id() -> Option { + unsafe { + for opt_vec in TASK_MANAGER.tasks.iter_mut().rev() { + if let Some(vec) = opt_vec { + if let Some(task) = vec.last_mut() { + return Some(task.id); + } + } + } + } + None + } + /// One task manager iteration. pub fn schedule() { - if CooperativeTaskManager::has_tasks() { + if CooperativeTaskManager::is_empty() { let task_id = unsafe { TASK_MANAGER.exec_task_id }; - let task = CooperativeTaskManager::get_task_from_id(task_id); + let task = CooperativeTaskManager::get_task_by_id(task_id); match task.status { TaskStatusType::Ready => { task.status = TaskStatusType::Running; @@ -234,7 +272,9 @@ impl CooperativeTaskManager { task.status = TaskStatusType::Terminated; } } - TaskStatusType::Sleeping => {} + TaskStatusType::Sleeping => { + // TODO: push_task_to_the_end_of_queue. + } TaskStatusType::Terminated => { CooperativeTaskManager::terminate_task(task_id); } @@ -250,94 +290,90 @@ impl CooperativeTaskManager { } } - fn push_to_queue(task: CooperativeTask) { - unsafe { - let vec = &mut TASK_MANAGER.tasks[task.priority]; - vec.push(task); - } - } - - fn delete_task(task: &mut CooperativeTask) { - unsafe { - let vec = &mut TASK_MANAGER.tasks[task.priority]; - if let Some(pos) = vec.iter().position(|vec_task| vec_task.id == task.id) { - vec.remove(pos); - } else { - panic!("Error: delete_task: Task with this id not found in the task list."); - } + /// Starts task manager work. Returns after 1000 steps only for testing task_manager_step. + pub fn test_start_task_manager() { + for _n in 1..=1000 { + CooperativeTaskManager::schedule(); } } - fn has_tasks() -> bool { + /// Reset task manager to default state. + pub fn reset_task_manager() { unsafe { - for vec in TASK_MANAGER.tasks.iter() { - if !vec.is_empty() { - return true; - } + for vec_opt in TASK_MANAGER.tasks.iter_mut() { + let Some(vec) = vec_opt; + vec.clear(); } + TASK_MANAGER.next_task_id = 0; + TASK_MANAGER.exec_task_id = 0; } - false } - fn get_next_task_id() -> Option { + /// Check if the task manager is empty. + fn is_empty() -> bool { unsafe { - for vec in TASK_MANAGER.tasks.iter_mut().rev() { - if let Some(task) = vec.last_mut() { - return Some(task.id); + TASK_MANAGER.tasks.iter().any(|opt_vec| { + if let Some(vec) = opt_vec { + !vec.is_empty() + } else { + false } - } - } - None - } - - /// Starts task manager work. Returns after 1000 steps only for testing task_manager_step. - pub fn test_start_task_manager() { - for _n in 1..=1000 { - CooperativeTaskManager::schedule(); + }) } } + /// Count tasks of the specified priority. pub fn count_tasks_with_priority(priority: TaskPriorityType) -> usize { if priority >= NUM_PRIORITIES { - panic!("Error: count_tasks_with_priority: Task's priority is invalid. It must be between 0 and 11."); + panic!("Error: count_tasks_with_priority: Task's priority {} is invalid. It must be between 0 and {}.", priority, NUM_PRIORITIES); + } + unsafe { + if let Some(vec) = TASK_MANAGER.tasks[priority].as_ref() { + vec.len() + } else { + 0 + } } - unsafe { TASK_MANAGER.tasks[priority].len() } - } - - pub fn has_no_tasks() -> bool { - unsafe { TASK_MANAGER.tasks.iter().all(|vec| vec.is_empty()) } } + /// Count all tasks in task manager. pub fn count_all_tasks() -> usize { - unsafe { TASK_MANAGER.tasks.iter().map(|vec| vec.len()).sum() } - } - - pub fn reset_task_manager() { + let mut sum: usize = 0; unsafe { - for vec in TASK_MANAGER.tasks.iter_mut() { - vec.clear(); + for vec_opt in TASK_MANAGER.tasks.iter() { + let Some(vec) = vec_opt; + sum += vec.len(); } - TASK_MANAGER.next_task_id = 0; - TASK_MANAGER.exec_task_id = 0; } + sum + } + + /// Get task ```id```. + pub fn get_id_from_task(task: &mut CooperativeTask) -> TaskIdType { + task.id } + /// Get task's state. pub fn get_status(task: &mut CooperativeTask) -> TaskStatusType { task.status } + /// Get state ```Ready```. pub fn ready_status() -> TaskStatusType { TaskStatusType::Ready } + /// Get state ```Sleeping```. pub fn sleeping_status() -> TaskStatusType { TaskStatusType::Sleeping } + /// Get state ```Terminate```. pub fn terminated_status() -> TaskStatusType { TaskStatusType::Terminated } + /// Get state ```Running```. pub fn running_status() -> TaskStatusType { TaskStatusType::Running } From af6d517edba5c191518110eb59449fcd77370e11 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Mon, 23 Dec 2024 19:47:13 +0300 Subject: [PATCH 43/50] Fix tests and bugs --- src/task_manager/cooperative.rs | 188 ++++++++++++++++++------------- src/task_manager/task.rs | 1 + tests/task_manager_unit_tests.rs | 89 ++++++++------- 3 files changed, 163 insertions(+), 115 deletions(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index 35f38d0..e53554b 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -31,7 +31,9 @@ pub enum TaskStatusType { /// The main structure for a cooperative task. /// Shell for ```Task```, the same for both cooperative and preemptive task managers. +/// #[repr(C)] +#[derive(Clone)] pub struct CooperativeTask { /// Contains 3 functions for task execution inherited from the ```Task```: ```setup_fn```, /// ```loop_fn``` and ```stop_condition_fn```. @@ -50,10 +52,10 @@ pub struct CooperativeTask { pub struct CooperativeTaskManager { /// Array of vectors with ```CooperativeTask``` to execute. pub(crate) tasks: [Option>; NUM_PRIORITIES], - /// ```id``` of a task that will be created the next. The First task has id 1. + /// ```id``` of a task that will be created the next. The first created task has id 1. pub(crate) next_task_id: TaskIdType, /// ```id``` of executing task. - pub(crate) exec_task_id: TaskIdType, + pub(crate) exec_task_id: Option, } /// Cooperative implementation of ```TaskManagerTrait```. @@ -80,9 +82,11 @@ impl CooperativeTaskManager { /// Create new task manager. pub(crate) const fn new() -> CooperativeTaskManager { CooperativeTaskManager { - tasks: [None; NUM_PRIORITIES], + tasks: [ + None, None, None, None, None, None, None, None, None, None, None, + ], next_task_id: 0, - exec_task_id: 0, + exec_task_id: None, } } @@ -104,8 +108,8 @@ impl CooperativeTaskManager { CooperativeTaskManager::push_to_queue(new_task); unsafe { - if TASK_MANAGER.exec_task_id == 0 { - TASK_MANAGER.exec_task_id = TASK_MANAGER.next_task_id; + if TASK_MANAGER.exec_task_id.is_none() { + TASK_MANAGER.exec_task_id = Some(TASK_MANAGER.next_task_id); } } } @@ -124,7 +128,8 @@ impl CooperativeTaskManager { }; unsafe { - TASK_MANAGER.next_task_id = TASK_MANAGER.next_task_id.wrapping_add(1); + // TODO: handling id overflow + TASK_MANAGER.next_task_id += 1; let task_id = TASK_MANAGER.next_task_id; CooperativeTask { core: task, @@ -137,17 +142,26 @@ impl CooperativeTaskManager { /// Task can put to sleep another task in ```Ready``` state by its ```id```. pub fn put_to_sleep(id: TaskIdType) { - let task = CooperativeTaskManager::get_task_by_id(id); + let Some(task) = CooperativeTaskManager::get_task_by_id(id) else { + panic!("Error: put_to_sleep: Task with id {} not found.", id); + }; match task.status { TaskStatusType::Running => { - panic!("Error: put_to_sleep: Task with this id is currently running."); + panic!( + "Error: put_to_sleep: Task with id {} is currently running.", + id + ); } TaskStatusType::Sleeping => { - panic!("Error: put_to_sleep: Task with this id is currently sleeping."); + panic!( + "Error: put_to_sleep: Task with id {} is currently sleeping.", + id + ); } TaskStatusType::Terminated => { panic!( - "Error: put_to_sleep: Task with this id is terminated and soon will be removed." + "Error: put_to_sleep: Task with id {} is terminated and will be removed soon.", + id ); } TaskStatusType::Ready => { @@ -156,15 +170,19 @@ impl CooperativeTaskManager { } } - /// Task can terminate and delete another task by ```id```.ы + /// Task can terminate and delete another task by ```id```. pub fn terminate_task(id: TaskIdType) { - let task = CooperativeTaskManager::get_task_by_id(id); - CooperativeTaskManager::delete_task(task); + let Some(task) = CooperativeTaskManager::get_task_by_id(id) else { + panic!("Error: terminate_task: Task with id {} not found.", id); + }; + CooperativeTaskManager::delete_task(id, task.priority); } /// Wake up task in ```Sleeping``` state. Otherwise, panic. pub fn wake_up_task(id: TaskIdType) { - let task = CooperativeTaskManager::get_task_by_id(id); + let Some(task) = CooperativeTaskManager::get_task_by_id(id) else { + panic!("Error: wake_up_task: Task with id {} not found.", id); + }; if task.status != TaskStatusType::Sleeping { panic!( "Error: wake_up_task: Task with id {} is currently not sleeping.", @@ -175,34 +193,39 @@ impl CooperativeTaskManager { } /// Remove task from ```tasks``` queue. - fn delete_task(task: &mut CooperativeTask) { + fn delete_task(task_id: TaskIdType, priority: TaskPriorityType) { unsafe { - if let Some(vec) = TASK_MANAGER.tasks[task.priority].as_mut() { - if let Some(pos) = vec.iter().position(|vec_task| vec_task.id == task.id) { - vec.remove(pos); - } else { - panic!( - "Error: delete_task: Task with id {} not found in the task list.", - task.id - ); - } + let Some(vec) = TASK_MANAGER.tasks[priority].as_mut() else { + panic!( + "Error:delete_task: Task with id {} does not exist in priority {}.", + task_id, priority + ); + }; + if let Some(task_index) = vec.iter().position(|task_vec| task_id == task_vec.id) { + vec.remove(task_index); + } else { + panic!( + "Error: delete_task: Task with id {} not found in the task list.", + task_id + ); } } } /// Get a task by ```id``` and return it. - pub fn get_task_by_id<'a>(id: TaskIdType) -> &'a mut CooperativeTask { + pub fn get_task_by_id<'a>(id: TaskIdType) -> Option<&'a mut CooperativeTask> { unsafe { for vec_opt in TASK_MANAGER.tasks.iter_mut() { if let Some(vec) = vec_opt { for task in vec.iter_mut() { if task.id == id { - return task; + return Some(task); } } } } - panic!("Error: get_task_by_id: Task with id {} not found.", id); + None + // panic!("Error: get_task_by_id: Task with id {} not found.", id); } } @@ -214,10 +237,16 @@ impl CooperativeTaskManager { unsafe { if TASK_MANAGER.tasks[priority].is_none() { panic!( - "Error: get_id_by_position: No tasks found for priority {}.", + "Error: get_id_by_position: No tasks found with priority {}.", priority ); } + if TASK_MANAGER.tasks[priority].as_ref().unwrap().len() - 1 < position { + panic!( + "Error: get_id_by_position: No tasks found for task on position {}.", + position + ); + } TASK_MANAGER.tasks[priority] .as_ref() .unwrap() @@ -231,9 +260,6 @@ impl CooperativeTaskManager { fn push_to_queue(task: CooperativeTask) { unsafe { let priority = task.priority; - while TASK_MANAGER.tasks.len() <= priority { - TASK_MANAGER.tasks.push(None); - } if TASK_MANAGER.tasks[priority].is_none() { TASK_MANAGER.tasks[priority] = Some(Vec::new()); @@ -246,47 +272,54 @@ impl CooperativeTaskManager { /// Get id of task to be executed next. fn get_next_task_id() -> Option { unsafe { - for opt_vec in TASK_MANAGER.tasks.iter_mut().rev() { - if let Some(vec) = opt_vec { - if let Some(task) = vec.last_mut() { + for vec_opt in TASK_MANAGER.tasks.iter_mut().rev() { + if let Some(vec) = vec_opt { + for task in vec { return Some(task.id); } } } } - None + None // In case when task manager has not tasks. + } + + /// Push task to the other queue end. + fn push_to_end(task: &mut CooperativeTask) { + let task_copy = task.clone(); + CooperativeTaskManager::terminate_task(task.id); + CooperativeTaskManager::push_to_queue(task_copy); } /// One task manager iteration. pub fn schedule() { - if CooperativeTaskManager::is_empty() { - let task_id = unsafe { TASK_MANAGER.exec_task_id }; - let task = CooperativeTaskManager::get_task_by_id(task_id); - match task.status { - TaskStatusType::Ready => { - task.status = TaskStatusType::Running; - } - TaskStatusType::Running => { - (task.core.loop_fn)(); - if (task.core.stop_condition_fn)() { - task.status = TaskStatusType::Terminated; + if !CooperativeTaskManager::is_empty() { + if let Some(exec_task_id) = unsafe { TASK_MANAGER.exec_task_id } { + let Some(exec_task) = CooperativeTaskManager::get_task_by_id(exec_task_id) else { + panic!("Error: schedule: Task with id {} not found.", exec_task_id); + }; + match exec_task.status { + TaskStatusType::Ready => { + exec_task.status = TaskStatusType::Running; + } + TaskStatusType::Running => { + (exec_task.core.loop_fn)(); + if (exec_task.core.stop_condition_fn)() { + exec_task.status = TaskStatusType::Terminated; + } + } + TaskStatusType::Sleeping => { + CooperativeTaskManager::push_to_end(exec_task); + } + TaskStatusType::Terminated => { + CooperativeTaskManager::terminate_task(exec_task_id); } } - TaskStatusType::Sleeping => { - // TODO: push_task_to_the_end_of_queue. - } - TaskStatusType::Terminated => { - CooperativeTaskManager::terminate_task(task_id); + if exec_task.status != TaskStatusType::Running { + unsafe { + TASK_MANAGER.exec_task_id = CooperativeTaskManager::get_next_task_id() + } } } - if task.status != TaskStatusType::Running { - unsafe { - let Some(next_exec_id) = CooperativeTaskManager::get_next_task_id() else { - return; - }; - unsafe { TASK_MANAGER.exec_task_id = next_exec_id } - }; - } } } @@ -300,25 +333,26 @@ impl CooperativeTaskManager { /// Reset task manager to default state. pub fn reset_task_manager() { unsafe { - for vec_opt in TASK_MANAGER.tasks.iter_mut() { - let Some(vec) = vec_opt; - vec.clear(); + for priority in 0..NUM_PRIORITIES { + if let Some(vec) = TASK_MANAGER.tasks[priority].as_mut() { + vec.clear(); + TASK_MANAGER.tasks[priority] = None; + } } TASK_MANAGER.next_task_id = 0; - TASK_MANAGER.exec_task_id = 0; + TASK_MANAGER.exec_task_id = None; } } /// Check if the task manager is empty. - fn is_empty() -> bool { + pub fn is_empty() -> bool { unsafe { - TASK_MANAGER.tasks.iter().any(|opt_vec| { - if let Some(vec) = opt_vec { - !vec.is_empty() - } else { - false + for vec_opt in TASK_MANAGER.tasks.iter() { + if let Some(_) = vec_opt { + return false; } - }) + } + true } } @@ -338,14 +372,14 @@ impl CooperativeTaskManager { /// Count all tasks in task manager. pub fn count_all_tasks() -> usize { - let mut sum: usize = 0; unsafe { - for vec_opt in TASK_MANAGER.tasks.iter() { - let Some(vec) = vec_opt; - sum += vec.len(); - } + TASK_MANAGER + .tasks + .iter() + .flatten() // Skip None + .map(|vec| vec.len()) + .sum() } - sum } /// Get task ```id```. diff --git a/src/task_manager/task.rs b/src/task_manager/task.rs index 58af77d..4c5a55e 100644 --- a/src/task_manager/task.rs +++ b/src/task_manager/task.rs @@ -20,6 +20,7 @@ pub type TaskStopConditionFunctionType = extern "C" fn() -> bool; #[repr(C)] /// Task representation for task manager. +#[derive(Clone)] pub struct Task { /// Setup function, that is called once at the beginning of task. pub(crate) setup_fn: TaskSetupFunctionType, diff --git a/tests/task_manager_unit_tests.rs b/tests/task_manager_unit_tests.rs index 513e293..20011e4 100644 --- a/tests/task_manager_unit_tests.rs +++ b/tests/task_manager_unit_tests.rs @@ -25,7 +25,7 @@ mod task_manager_unit_tests { #[test] #[sequential] #[should_panic( - expected = "Error: add_task: Task's priority is invalid. It must be between 0 and 11." + expected = "Error: add_priority_task: Task's priority 100 is invalid. It must be between 0 and 11." )] fn test_add_task_invalid_priority() { TaskManager::reset_task_manager(); @@ -61,8 +61,9 @@ mod task_manager_unit_tests { fn test_get_task_by_id() { TaskManager::reset_task_manager(); TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 10); - let id = TaskManager::get_id_from_position(10, 0); - let found_task = TaskManager::get_task_by_id(id); + let id = TaskManager::get_id_by_position(10, 0); + let found_task = TaskManager::get_task_by_id(id) + .unwrap_or_else(|| panic!("Task not found for id {}", id)); assert_eq!(id, TaskManager::get_id_from_task(found_task)); TaskManager::reset_task_manager(); @@ -70,12 +71,12 @@ mod task_manager_unit_tests { #[test] #[sequential] - #[should_panic(expected = "Error: get_task_from_id: Task with id 2 not found.")] + #[should_panic(expected = "Error: get_task_by_id: Task with id 2 not found.")] fn test_get_task_by_invalid_id() { TaskManager::reset_task_manager(); TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 10); - let found_task = TaskManager::get_task_by_id(2); - TaskManager::reset_task_manager(); + let found_task = TaskManager::get_task_by_id(2) + .unwrap_or_else(|| panic!("Error: get_task_by_id: Task with id 2 not found.")); } #[test] @@ -85,19 +86,19 @@ mod task_manager_unit_tests { // ID of a first added task is 1. TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 10); - let task_id = TaskManager::get_id_from_position(10, 0); + let task_id = TaskManager::get_id_by_position(10, 0); assert_eq!(task_id, 1); TaskManager::reset_task_manager(); } #[test] #[sequential] - #[should_panic(expected = "Error: get_id_from_position: Position out of bounds.")] + #[should_panic(expected = "Error: get_id_by_position: No tasks found for task on position 1.")] fn test_get_id_from_invalid_position() { TaskManager::reset_task_manager(); - // ID of a first added task is 1. + // id of first added task is 1. TaskManager::add_priority_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true, 10); - let task_id = TaskManager::get_id_from_position(10, 1); + let task_id = TaskManager::get_id_by_position(10, 1); TaskManager::reset_task_manager(); } @@ -107,7 +108,9 @@ mod task_manager_unit_tests { TaskManager::reset_task_manager(); TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); - let task = TaskManager::get_task_by_id(1); + let task = + TaskManager::get_task_by_id(1).unwrap_or_else(|| panic!("Task not found for id 1")); + assert_eq!(TaskManager::get_id_from_task(task), 1); TaskManager::reset_task_manager(); } @@ -118,7 +121,7 @@ mod task_manager_unit_tests { } #[test] #[sequential] - #[should_panic(expected = "Error: put_to_sleep: Task with this id is currently running.")] + #[should_panic(expected = "Error: put_to_sleep: Task with id 1 is currently running.")] fn test_put_to_sleep_running_task() { TaskManager::reset_task_manager(); TaskManager::add_task( @@ -127,7 +130,7 @@ mod task_manager_unit_tests { dummy_condition_true, ); - assert_eq!(TaskManager::get_id_from_position(0, 0), 1); + assert_eq!(TaskManager::get_id_by_position(0, 0), 1); TaskManager::test_start_task_manager(); TaskManager::reset_task_manager(); } @@ -138,72 +141,78 @@ mod task_manager_unit_tests { } #[test] #[sequential] - #[should_panic(expected = "Error: put_to_sleep: Task with this id is currently sleeping.")] + #[should_panic(expected = "Error: put_to_sleep: Task with id 2 is currently sleeping.")] fn test_put_to_sleep_sleeping_task() { TaskManager::reset_task_manager(); - // Change a task state with id = 2 to sleeping. + // Change a task state with id 2 to sleeping. TaskManager::add_task( dummy_setup_fn, test_put_to_sleep_sleeping_task_loop_fn, dummy_condition_true, ); TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); - let task_2 = TaskManager::get_task_by_id(2); + + let task_2 = + TaskManager::get_task_by_id(2).unwrap_or_else(|| panic!("Task not found for id 2")); assert_eq!(TaskManager::get_status(task_2), TaskManager::ready_status()); TaskManager::schedule(); TaskManager::schedule(); + assert_eq!( TaskManager::get_status(task_2), TaskManager::sleeping_status() ); - // Add a task that will put to a sleep sleeping task. TaskManager::add_task( dummy_setup_fn, test_put_to_sleep_sleeping_task_loop_fn, dummy_condition_true, ); + + // Add a task that will put to a sleep sleeping task. TaskManager::test_start_task_manager(); - TaskManager::reset_task_manager(); + + assert_eq!(TaskManager::count_all_tasks(), 1); } /// Loop function for task for test_put_to_sleep_task_from_task_loop_fn. fn test_put_to_sleep_task_from_task_loop_fn() { - TaskManager::put_to_sleep(2); + TaskManager::put_to_sleep(3); } #[test] #[sequential] fn test_put_to_sleep_task_from_task() { TaskManager::reset_task_manager(); - TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); - let task_1 = TaskManager::get_task_by_id(1); - - TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); - let task_2 = TaskManager::get_task_by_id(2); - assert_eq!(TaskManager::get_status(task_2), TaskManager::ready_status()); TaskManager::add_task( dummy_setup_fn, test_put_to_sleep_task_from_task_loop_fn, dummy_condition_true, ); + + TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); + let task_2 = + TaskManager::get_task_by_id(2).unwrap_or_else(|| panic!("Task not found for id 2")); + + TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); + let task_3 = + TaskManager::get_task_by_id(3).unwrap_or_else(|| panic!("Task not found for id 3")); + + assert_eq!(TaskManager::get_status(task_3), TaskManager::ready_status()); + TaskManager::test_start_task_manager(); assert_eq!( - TaskManager::get_status(task_1), - TaskManager::terminated_status() - ); - assert_eq!( - TaskManager::get_status(task_2), + TaskManager::get_status(task_3), TaskManager::sleeping_status() ); - assert_eq!(TaskManager::count_all_tasks(), 2); + assert_eq!(TaskManager::count_all_tasks(), 1); } /// Loop functions for task for test_wake_up_sleeping_task. fn test_wake_up_sleeping_task_loop_fn() { - TaskManager::wake_up(2); + TaskManager::wake_up_task(2); } fn test_put_to_sleep_task_loop_fn() { TaskManager::put_to_sleep(2); @@ -218,7 +227,8 @@ mod task_manager_unit_tests { dummy_condition_true, ); TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); - let task_2 = TaskManager::get_task_by_id(2); + let task_2 = + TaskManager::get_task_by_id(2).unwrap_or_else(|| panic!("Task not found for id 2")); assert_eq!(TaskManager::get_status(task_2), TaskManager::ready_status()); @@ -238,17 +248,18 @@ mod task_manager_unit_tests { TaskManager::schedule(); TaskManager::schedule(); TaskManager::schedule(); + TaskManager::schedule(); assert_eq!(TaskManager::get_status(task_2), TaskManager::ready_status()); } /// Loop functions for task for test_wake_up_non_sleeping_task_loop_fn. fn test_wake_up_non_sleeping_task_loop_fn() { - TaskManager::wake_up(2); + TaskManager::wake_up_task(2); } #[test] #[sequential] - #[should_panic(expected = "Error: wake_up_task: Task with this id is currently not sleeping.")] + #[should_panic(expected = "Error: wake_up_task: Task with id 2 is currently not sleeping.")] fn test_wake_up_non_sleeping_task() { TaskManager::reset_task_manager(); TaskManager::add_task( @@ -257,7 +268,8 @@ mod task_manager_unit_tests { dummy_condition_true, ); TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); - let task_2 = TaskManager::get_task_by_id(2); + let task_2 = + TaskManager::get_task_by_id(2).unwrap_or_else(|| panic!("Task not found for id 2")); assert_eq!(TaskManager::get_status(task_2), TaskManager::ready_status()); TaskManager::test_start_task_manager(); @@ -280,7 +292,8 @@ mod task_manager_unit_tests { dummy_condition_true, ); TaskManager::add_task(dummy_setup_fn, infinite_loop_fn, dummy_condition_true); - let task_2 = TaskManager::get_task_by_id(2); + let task_2 = + TaskManager::get_task_by_id(2).unwrap_or_else(|| panic!("Task not found for id 2")); assert_eq!(TaskManager::get_status(task_2), TaskManager::ready_status()); TaskManager::test_start_task_manager(); @@ -293,7 +306,7 @@ mod task_manager_unit_tests { fn test_empty_task_manager() { TaskManager::reset_task_manager(); TaskManager::test_start_task_manager(); - assert!(TaskManager::has_no_tasks()); + assert!(TaskManager::is_empty()); } /// Counter for a task for test_one_finite_task_task_manager. From b7390b9c9e25231b0f23f167bc3bb38bfcd34fbd Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Mon, 23 Dec 2024 21:11:47 +0300 Subject: [PATCH 44/50] Fix according to clippy --- src/task_manager/cooperative.rs | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/task_manager/cooperative.rs b/src/task_manager/cooperative.rs index e53554b..250f5b1 100644 --- a/src/task_manager/cooperative.rs +++ b/src/task_manager/cooperative.rs @@ -215,18 +215,16 @@ impl CooperativeTaskManager { /// Get a task by ```id``` and return it. pub fn get_task_by_id<'a>(id: TaskIdType) -> Option<&'a mut CooperativeTask> { unsafe { - for vec_opt in TASK_MANAGER.tasks.iter_mut() { - if let Some(vec) = vec_opt { - for task in vec.iter_mut() { - if task.id == id { - return Some(task); - } + for vec in TASK_MANAGER.tasks.iter_mut().flatten() { + for task in vec.iter_mut() { + if task.id == id { + return Some(task); } } } - None - // panic!("Error: get_task_by_id: Task with id {} not found.", id); } + None + // panic!("Error: get_task_by_id: Task with id {} not found.", id); } /// Get task ```id``` by its position in ```tasks``` vector. @@ -272,11 +270,9 @@ impl CooperativeTaskManager { /// Get id of task to be executed next. fn get_next_task_id() -> Option { unsafe { - for vec_opt in TASK_MANAGER.tasks.iter_mut().rev() { - if let Some(vec) = vec_opt { - for task in vec { - return Some(task.id); - } + for vec in TASK_MANAGER.tasks.iter_mut().rev().flatten() { + if let Some(task) = vec.iter().next() { + return Some(task.id); } } } @@ -348,7 +344,7 @@ impl CooperativeTaskManager { pub fn is_empty() -> bool { unsafe { for vec_opt in TASK_MANAGER.tasks.iter() { - if let Some(_) = vec_opt { + if vec_opt.is_some() { return false; } } From e37ceb522942133610d76d32524ecb131ac11d9d Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Tue, 24 Dec 2024 03:05:05 +0300 Subject: [PATCH 45/50] Add examples for coop sched --- .../scheduler/cooperative/.cargo/config.toml | 13 ++++ .../mips64/scheduler/cooperative/Cargo.toml | 14 ++++ .../mips64/scheduler/cooperative/README.md | 38 ++++++++++ .../scheduler/cooperative/rust-toolchain.toml | 2 + .../mips64/scheduler/cooperative/src/main.rs | 63 ++++++++++++++++ .../{ => cooperative}/.cargo/config.toml | 0 .../scheduler/{ => cooperative}/Cargo.toml | 4 +- .../scheduler/cooperative/README.md | 45 ++++++++++++ .../{ => cooperative}/rust-toolchain.toml | 0 .../scheduler/cooperative/src/main.rs | 71 +++++++++++++++++++ .../risc-v-esp32-c6/scheduler/src/main.rs | 49 ------------- .../{ => cooperative}/.cargo/config.toml | 0 .../scheduler/cooperative/Cargo.toml | 19 +++++ .../scheduler/cooperative/README.md | 45 ++++++++++++ .../{ => cooperative}/rust-toolchain.toml | 0 .../scheduler/cooperative/src/main.rs | 71 +++++++++++++++++++ .../scheduler/preemptive/.cargo/config.toml | 13 ++++ .../scheduler/{ => preemptive}/Cargo.toml | 2 +- .../scheduler/preemptive/README.md | 43 +++++++++++ .../scheduler/preemptive/rust-toolchain.toml | 2 + .../scheduler/{ => preemptive}/src/main.rs | 0 21 files changed, 442 insertions(+), 52 deletions(-) create mode 100644 examples/rust-examples/mips64/scheduler/cooperative/.cargo/config.toml create mode 100644 examples/rust-examples/mips64/scheduler/cooperative/Cargo.toml create mode 100644 examples/rust-examples/mips64/scheduler/cooperative/README.md create mode 100644 examples/rust-examples/mips64/scheduler/cooperative/rust-toolchain.toml create mode 100644 examples/rust-examples/mips64/scheduler/cooperative/src/main.rs rename examples/rust-examples/risc-v-esp32-c6/scheduler/{ => cooperative}/.cargo/config.toml (100%) rename examples/rust-examples/risc-v-esp32-c6/scheduler/{ => cooperative}/Cargo.toml (79%) create mode 100644 examples/rust-examples/risc-v-esp32-c6/scheduler/cooperative/README.md rename examples/rust-examples/risc-v-esp32-c6/scheduler/{ => cooperative}/rust-toolchain.toml (100%) create mode 100644 examples/rust-examples/risc-v-esp32-c6/scheduler/cooperative/src/main.rs delete mode 100644 examples/rust-examples/risc-v-esp32-c6/scheduler/src/main.rs rename examples/rust-examples/xtensa-esp32/scheduler/{ => cooperative}/.cargo/config.toml (100%) create mode 100644 examples/rust-examples/xtensa-esp32/scheduler/cooperative/Cargo.toml create mode 100644 examples/rust-examples/xtensa-esp32/scheduler/cooperative/README.md rename examples/rust-examples/xtensa-esp32/scheduler/{ => cooperative}/rust-toolchain.toml (100%) create mode 100644 examples/rust-examples/xtensa-esp32/scheduler/cooperative/src/main.rs create mode 100644 examples/rust-examples/xtensa-esp32/scheduler/preemptive/.cargo/config.toml rename examples/rust-examples/xtensa-esp32/scheduler/{ => preemptive}/Cargo.toml (88%) create mode 100644 examples/rust-examples/xtensa-esp32/scheduler/preemptive/README.md create mode 100644 examples/rust-examples/xtensa-esp32/scheduler/preemptive/rust-toolchain.toml rename examples/rust-examples/xtensa-esp32/scheduler/{ => preemptive}/src/main.rs (100%) diff --git a/examples/rust-examples/mips64/scheduler/cooperative/.cargo/config.toml b/examples/rust-examples/mips64/scheduler/cooperative/.cargo/config.toml new file mode 100644 index 0000000..4ee6110 --- /dev/null +++ b/examples/rust-examples/mips64/scheduler/cooperative/.cargo/config.toml @@ -0,0 +1,13 @@ +[build] +rustflags = [ + "-C", "link-arg=-Ttext=0x80010000", + "-C", "link-arg=-emain", +] + +target = "mips64el-unknown-linux-gnuabi64" + +[unstable] +build-std = ["core", "alloc"] + +[target.mips64el-unknown-linux-gnuabi64] +linker = "lld" diff --git a/examples/rust-examples/mips64/scheduler/cooperative/Cargo.toml b/examples/rust-examples/mips64/scheduler/cooperative/Cargo.toml new file mode 100644 index 0000000..c4b9af9 --- /dev/null +++ b/examples/rust-examples/mips64/scheduler/cooperative/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "example_mips64_cooperative_scheduler" +version = "0.4.0" +edition = "2021" + +[profile.release] +panic = "abort" +debug = true + +[dependencies] +# Specifying Martos version +#martos = "0.4.0" +# Specifying current Martos version path for ci +martos = { path = "../../../../../", features = ["cooperative"] } diff --git a/examples/rust-examples/mips64/scheduler/cooperative/README.md b/examples/rust-examples/mips64/scheduler/cooperative/README.md new file mode 100644 index 0000000..7aa61cd --- /dev/null +++ b/examples/rust-examples/mips64/scheduler/cooperative/README.md @@ -0,0 +1,38 @@ +# Rust example for mips64 architecture + +Presented here is a straightforward Rust example utilizing Martos with a cooperative scheduler. + +The program begins with a main task that increments a shared counter on each iteration. +Once the counter reaches the value of 25, the main task dynamically adds an inner task to the task manager. +The inner task also increments the shared counter on each iteration and stops execution when the counter becomes +divisible by 10. This setup showcases Martos' flexibility in managing tasks, including adding new tasks dynamically +during execution. + +## How to install dependencies + +Below is an illustrative example demonstrating the installation of building toolchains on a Linux (Ubuntu/Debian): + +``` +apt update && apt install curl build-essential lld +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y +rustup toolchain install nightly +rustup default 1.71 +rustup target add mips64el-unknown-linux-gnuabi64 +rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu +``` + +## How to build the example + +Below, you will find an illustrative example showcasing the building process on a Linux system (Ubuntu/Debian): + +``` +cargo +nightly build --release +``` + +## How to run the example + +Below, you will find an illustrative example showcasing the running on a Linux system (Ubuntu/Debian): + +``` +cargo +nightly run +``` diff --git a/examples/rust-examples/mips64/scheduler/cooperative/rust-toolchain.toml b/examples/rust-examples/mips64/scheduler/cooperative/rust-toolchain.toml new file mode 100644 index 0000000..5d56faf --- /dev/null +++ b/examples/rust-examples/mips64/scheduler/cooperative/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/examples/rust-examples/mips64/scheduler/cooperative/src/main.rs b/examples/rust-examples/mips64/scheduler/cooperative/src/main.rs new file mode 100644 index 0000000..bc24a3a --- /dev/null +++ b/examples/rust-examples/mips64/scheduler/cooperative/src/main.rs @@ -0,0 +1,63 @@ +#![no_std] +#![no_main] + +use core::sync::atomic::{AtomicU32, Ordering}; +use martos::{ + init_system, + task_manager::{TaskManager, TaskManagerTrait}, +}; + +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} + +static COUNTER: AtomicU32 = AtomicU32::new(1); + +/// Setup function for the main task. +fn main_task_setup_fn() {} + +/// Loop function for the main task. +fn main_task_loop_fn() { + let count = COUNTER.fetch_add(1, Ordering::Relaxed); + if count == 25 { + TaskManager::add_task( + inner_task_setup_fn, + inner_task_loop_fn, + inner_task_stop_condition_fn, + ); + } +} + +/// Stop condition for the main task. +fn main_task_stop_condition_fn() -> bool { + false +} + +/// Setup function for the inner task. +fn inner_task_setup_fn() {} + +/// Loop function for the inner task. +fn inner_task_loop_fn() { + COUNTER.fetch_add(1, Ordering::Relaxed); +} + +/// Stop condition for the inner task. +fn inner_task_stop_condition_fn() -> bool { + let value = unsafe { COUNTER.as_ptr().read() }; + value % 10 == 0 +} + +#[no_mangle] +pub extern "C" fn __start() -> ! { + // Initialize Martos. + init_system(); + // Add task to execute. + TaskManager::add_task( + main_task_setup_fn, + main_task_loop_fn, + main_task_stop_condition_fn, + ); + // Start task manager. + TaskManager::start_task_manager(); +} diff --git a/examples/rust-examples/risc-v-esp32-c6/scheduler/.cargo/config.toml b/examples/rust-examples/risc-v-esp32-c6/scheduler/cooperative/.cargo/config.toml similarity index 100% rename from examples/rust-examples/risc-v-esp32-c6/scheduler/.cargo/config.toml rename to examples/rust-examples/risc-v-esp32-c6/scheduler/cooperative/.cargo/config.toml diff --git a/examples/rust-examples/risc-v-esp32-c6/scheduler/Cargo.toml b/examples/rust-examples/risc-v-esp32-c6/scheduler/cooperative/Cargo.toml similarity index 79% rename from examples/rust-examples/risc-v-esp32-c6/scheduler/Cargo.toml rename to examples/rust-examples/risc-v-esp32-c6/scheduler/cooperative/Cargo.toml index 1246f4b..9aeb81a 100644 --- a/examples/rust-examples/risc-v-esp32-c6/scheduler/Cargo.toml +++ b/examples/rust-examples/risc-v-esp32-c6/scheduler/cooperative/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "example_risc_v_esp32c6_scheduler" +name = "example_risc_v_esp32c6_cooperative_scheduler" version = "0.3.0" edition = "2021" @@ -10,7 +10,7 @@ debug = true # Specifying Martos version #martos = "0.3.0" # Specifying current Martos version path for ci -martos = { path = "../../../../", features = ["preemptive"]} +martos = { path = "../../../../../", features = ["cooperative"] } esp-hal = "0.21.1" esp-backtrace = { version = "0.14.1", features = ["esp32c6", "panic-handler", "exception-handler", "println"] } esp-println = { version = "0.11.0", features = ["esp32c6"] } diff --git a/examples/rust-examples/risc-v-esp32-c6/scheduler/cooperative/README.md b/examples/rust-examples/risc-v-esp32-c6/scheduler/cooperative/README.md new file mode 100644 index 0000000..51293bc --- /dev/null +++ b/examples/rust-examples/risc-v-esp32-c6/scheduler/cooperative/README.md @@ -0,0 +1,45 @@ +# Rust example for risc-v esp32c6 architecture + +Presented here is a straightforward Rust example utilizing Martos with a cooperative scheduler. + +The example begins with a main task that handles a counter, incrementing it by 1 and printing the updated value. +An inner task is dynamically added once the counter reaches 25, and it increments the counter by 1. The inner task +periodically terminates itself when the counter is a multiple of 10, showcasing dynamic task creation and cooperative +task switching. + +## How to install dependencies + +For comprehensive guidance on installing the necessary dependencies for developing applications targeting the RISC-V +ESP32-C6 architecture, +please refer to [the official website](https://docs.esp-rs.org/book/installation/riscv-and-xtensa.html). +Below is an illustrative example demonstrating the installation of building toolchains on a Linux (Ubuntu/Debian): + +``` +apt-get -qq update +apt-get install -y -q build-essential curl +curl https://sh.rustup.rs -sSf | sh -s -- -y +cargo install espup +espup install +``` + +## How to build the example + +For a thorough guide on developing projects for the RISC-V ESP32-C6 architecture across various operating systems, +we recommend +consulting [the official website](https://docs.esp-rs.org/book/installation/riscv-and-xtensa.html#3-set-up-the-environment-variables). +Below, you will find an illustrative example showcasing the building process on a Linux system (Ubuntu/Debian): + +``` +. $HOME/export-esp.sh +cargo build +``` + +## How to run the example + +For detailed instructions on running projects for the RISC-V ESP32-C6 architecture across various operating systems, +we recommend consulting [the official website](https://docs.esp-rs.org/book/tooling/espflash.html). +Below, you will find an illustrative example showcasing the running on a Linux system (Ubuntu/Debian): + +``` +cargo run +``` diff --git a/examples/rust-examples/risc-v-esp32-c6/scheduler/rust-toolchain.toml b/examples/rust-examples/risc-v-esp32-c6/scheduler/cooperative/rust-toolchain.toml similarity index 100% rename from examples/rust-examples/risc-v-esp32-c6/scheduler/rust-toolchain.toml rename to examples/rust-examples/risc-v-esp32-c6/scheduler/cooperative/rust-toolchain.toml diff --git a/examples/rust-examples/risc-v-esp32-c6/scheduler/cooperative/src/main.rs b/examples/rust-examples/risc-v-esp32-c6/scheduler/cooperative/src/main.rs new file mode 100644 index 0000000..c721a30 --- /dev/null +++ b/examples/rust-examples/risc-v-esp32-c6/scheduler/cooperative/src/main.rs @@ -0,0 +1,71 @@ +#![no_std] +#![no_main] + +use core::sync::atomic::{AtomicU32, Ordering}; +use esp_hal::entry; +use esp_println::println; +use martos::{ + init_system, + task_manager::{TaskManager, TaskManagerTrait}, +}; + +/// Counter to work with in loop. +static COUNTER: AtomicU32 = AtomicU32::new(1); + +/// Setup function for the main task. +fn main_task_setup_fn() { + println!("Main task setup.\n"); +} + +/// Loop function for the main task. +fn main_task_loop_fn() { + let count = COUNTER.fetch_add(1, Ordering::Relaxed); + println!("Main task loop: Counter = {}.\n", unsafe { + COUNTER.as_ptr().read() + }); + if count == 25 { + TaskManager::add_task( + inner_task_setup_fn, + inner_task_loop_fn, + inner_task_stop_condition_fn, + ); + } +} + +/// Stop condition for the main task. +fn main_task_stop_condition_fn() -> bool { + false +} + +/// Setup function for the inner task. +fn inner_task_setup_fn() { + println!("Inner task setup.\n"); +} + +/// Loop function for the inner task. +fn inner_task_loop_fn() { + COUNTER.fetch_add(1, Ordering::Relaxed); + println!("Inner task loop: Counter = {}.\n", unsafe { + COUNTER.as_ptr().read() + }); +} + +/// Stop condition for the inner task. +fn inner_task_stop_condition_fn() -> bool { + let value = unsafe { COUNTER.as_ptr().read() }; + value % 10 == 0 +} + +#[entry] +fn main() -> ! { + // Initialize Martos. + init_system(); + // Add task to execute. + TaskManager::add_task( + main_task_setup_fn, + main_task_loop_fn, + main_task_stop_condition_fn, + ); + // Start task manager. + TaskManager::start_task_manager(); +} diff --git a/examples/rust-examples/risc-v-esp32-c6/scheduler/src/main.rs b/examples/rust-examples/risc-v-esp32-c6/scheduler/src/main.rs deleted file mode 100644 index c9da27f..0000000 --- a/examples/rust-examples/risc-v-esp32-c6/scheduler/src/main.rs +++ /dev/null @@ -1,49 +0,0 @@ -#![no_std] -#![no_main] - -use core::sync::atomic::{AtomicU32, Ordering}; -use esp_backtrace as _; -use esp_hal::{delay::Delay, entry, prelude::*}; -use esp_println::println; -use martos::{ - init_system, - task_manager::{TaskManager, TaskManagerTrait}, -}; - -/// Counter to work with in loop. -static COUNTER: AtomicU32 = AtomicU32::new(1); - -/// Loop function for task to execute. -fn loop_fn_1() { - let old = COUNTER.fetch_add(1, Ordering::Relaxed); - println!("Loop 0; Counter = {}", old); - Delay::new().delay(500u64.millis()); -} - -fn loop_fn_2() { - let old = COUNTER.fetch_add(1, Ordering::Relaxed); - println!("Loop 1; Counter = {}", old); - Delay::new().delay(500u64.millis()); -} - -fn setup() { - println!("Setup") -} -fn stop() -> bool { - if COUNTER.fetch_add(0, Ordering::Relaxed) > 20 { - true - } else { - false - } -} - -#[entry] -fn main() -> ! { - // Initialize Martos. - init_system(); - // Add task to execute. - TaskManager::add_task(setup, loop_fn_1, stop); - TaskManager::add_task(setup, loop_fn_2, stop); - // Start task manager. - TaskManager::start_task_manager(); -} diff --git a/examples/rust-examples/xtensa-esp32/scheduler/.cargo/config.toml b/examples/rust-examples/xtensa-esp32/scheduler/cooperative/.cargo/config.toml similarity index 100% rename from examples/rust-examples/xtensa-esp32/scheduler/.cargo/config.toml rename to examples/rust-examples/xtensa-esp32/scheduler/cooperative/.cargo/config.toml diff --git a/examples/rust-examples/xtensa-esp32/scheduler/cooperative/Cargo.toml b/examples/rust-examples/xtensa-esp32/scheduler/cooperative/Cargo.toml new file mode 100644 index 0000000..0ad1446 --- /dev/null +++ b/examples/rust-examples/xtensa-esp32/scheduler/cooperative/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "example_xtensa_esp32_cooperative_scheduler" +version = "0.3.0" +edition = "2021" + +[profile.release] +debug = true + +[dependencies] +# Specifying Martos version +#martos = "0.3.0" +# Specifying current Martos version path for ci +martos = { path = "../../../../../", features = ["cooperative"] } +esp-hal = "0.21.1" +esp-backtrace = { version = "0.14.1", features = ["esp32", "panic-handler", "exception-handler", "println"] } +esp-println = { version = "0.11.0", features = ["esp32"] } + +[features] +default = ["esp-hal/esp32", "esp-backtrace/esp32", "esp-println/esp32"] diff --git a/examples/rust-examples/xtensa-esp32/scheduler/cooperative/README.md b/examples/rust-examples/xtensa-esp32/scheduler/cooperative/README.md new file mode 100644 index 0000000..9319028 --- /dev/null +++ b/examples/rust-examples/xtensa-esp32/scheduler/cooperative/README.md @@ -0,0 +1,45 @@ +# Rust example for xtensa esp32 architecture + +Presented here is a straightforward Rust example utilizing Martos with a cooperative scheduler. + +The example begins with a main task that handles a counter, incrementing it by 1 and printing the updated value. +An inner task is dynamically added once the counter reaches 25, and it increments the counter by 1. The inner task +periodically terminates itself when the counter is a multiple of 10, showcasing dynamic task creation and cooperative +task switching. + +## How to install dependencies + +For comprehensive guidance on installing the necessary dependencies for developing applications targeting the Xtensa +ESP32 architecture, +please refer to [the official website](https://docs.esp-rs.org/book/installation/riscv-and-xtensa.html). +Below is an illustrative example demonstrating the installation of building toolchains on a Linux (Ubuntu/Debian): + +``` +apt-get -qq update +apt-get install -y -q build-essential curl +curl https://sh.rustup.rs -sSf | sh -s -- -y +cargo install espup +espup install +``` + +## How to build the example + +For a thorough guide on developing projects for the Xtensa ESP32 architecture across various operating systems, +we recommend +consulting [the official website](https://docs.esp-rs.org/book/installation/riscv-and-xtensa.html#3-set-up-the-environment-variables). +Below, you will find an illustrative example showcasing the building process on a Linux system (Ubuntu/Debian): + +``` +. $HOME/export-esp.sh +cargo build --release +``` + +## How to run the example + +For detailed instructions on running projects for the Xtensa ESP32 architecture across various operating systems, +we recommend consulting [the official website](https://docs.esp-rs.org/book/tooling/espflash.html). +Below, you will find an illustrative example showcasing the running on a Linux system (Ubuntu/Debian): + +``` +cargo run +``` diff --git a/examples/rust-examples/xtensa-esp32/scheduler/rust-toolchain.toml b/examples/rust-examples/xtensa-esp32/scheduler/cooperative/rust-toolchain.toml similarity index 100% rename from examples/rust-examples/xtensa-esp32/scheduler/rust-toolchain.toml rename to examples/rust-examples/xtensa-esp32/scheduler/cooperative/rust-toolchain.toml diff --git a/examples/rust-examples/xtensa-esp32/scheduler/cooperative/src/main.rs b/examples/rust-examples/xtensa-esp32/scheduler/cooperative/src/main.rs new file mode 100644 index 0000000..c721a30 --- /dev/null +++ b/examples/rust-examples/xtensa-esp32/scheduler/cooperative/src/main.rs @@ -0,0 +1,71 @@ +#![no_std] +#![no_main] + +use core::sync::atomic::{AtomicU32, Ordering}; +use esp_hal::entry; +use esp_println::println; +use martos::{ + init_system, + task_manager::{TaskManager, TaskManagerTrait}, +}; + +/// Counter to work with in loop. +static COUNTER: AtomicU32 = AtomicU32::new(1); + +/// Setup function for the main task. +fn main_task_setup_fn() { + println!("Main task setup.\n"); +} + +/// Loop function for the main task. +fn main_task_loop_fn() { + let count = COUNTER.fetch_add(1, Ordering::Relaxed); + println!("Main task loop: Counter = {}.\n", unsafe { + COUNTER.as_ptr().read() + }); + if count == 25 { + TaskManager::add_task( + inner_task_setup_fn, + inner_task_loop_fn, + inner_task_stop_condition_fn, + ); + } +} + +/// Stop condition for the main task. +fn main_task_stop_condition_fn() -> bool { + false +} + +/// Setup function for the inner task. +fn inner_task_setup_fn() { + println!("Inner task setup.\n"); +} + +/// Loop function for the inner task. +fn inner_task_loop_fn() { + COUNTER.fetch_add(1, Ordering::Relaxed); + println!("Inner task loop: Counter = {}.\n", unsafe { + COUNTER.as_ptr().read() + }); +} + +/// Stop condition for the inner task. +fn inner_task_stop_condition_fn() -> bool { + let value = unsafe { COUNTER.as_ptr().read() }; + value % 10 == 0 +} + +#[entry] +fn main() -> ! { + // Initialize Martos. + init_system(); + // Add task to execute. + TaskManager::add_task( + main_task_setup_fn, + main_task_loop_fn, + main_task_stop_condition_fn, + ); + // Start task manager. + TaskManager::start_task_manager(); +} diff --git a/examples/rust-examples/xtensa-esp32/scheduler/preemptive/.cargo/config.toml b/examples/rust-examples/xtensa-esp32/scheduler/preemptive/.cargo/config.toml new file mode 100644 index 0000000..4a7232a --- /dev/null +++ b/examples/rust-examples/xtensa-esp32/scheduler/preemptive/.cargo/config.toml @@ -0,0 +1,13 @@ +[build] +rustflags = [ + "-C", "link-arg=-Tlinkall.x", + "-C", "link-arg=-nostartfiles", +] + +target = "xtensa-esp32-none-elf" + +[unstable] +build-std = ["core", "alloc"] + +[target.'cfg(any(target_arch = "riscv32", target_arch = "xtensa"))'] +runner = "espflash flash --monitor" diff --git a/examples/rust-examples/xtensa-esp32/scheduler/Cargo.toml b/examples/rust-examples/xtensa-esp32/scheduler/preemptive/Cargo.toml similarity index 88% rename from examples/rust-examples/xtensa-esp32/scheduler/Cargo.toml rename to examples/rust-examples/xtensa-esp32/scheduler/preemptive/Cargo.toml index e1acf3a..bca2100 100644 --- a/examples/rust-examples/xtensa-esp32/scheduler/Cargo.toml +++ b/examples/rust-examples/xtensa-esp32/scheduler/preemptive/Cargo.toml @@ -10,7 +10,7 @@ debug = true # Specifying Martos version #martos = "0.3.0" # Specifying current Martos version path for ci -martos = { path = "../../../../", features = ["preemptive"]} +martos = { path = "../../../../../", features = ["preemptive"] } esp-hal = "0.21.1" esp-backtrace = { version = "0.14.1", features = ["esp32", "panic-handler", "exception-handler", "println"] } esp-println = { version = "0.11.0", features = ["esp32"] } diff --git a/examples/rust-examples/xtensa-esp32/scheduler/preemptive/README.md b/examples/rust-examples/xtensa-esp32/scheduler/preemptive/README.md new file mode 100644 index 0000000..b2e1e2c --- /dev/null +++ b/examples/rust-examples/xtensa-esp32/scheduler/preemptive/README.md @@ -0,0 +1,43 @@ +# Rust example for xtensa esp32 architecture + +Presented here is a straightforward Rust example utilizing Martos with preemptive scheduler. + +Two tasks are created. They take turns increasing the counter value and printing it out until it reaches 20. +Periodically, one preempts the other + +## How to install dependencies + +For comprehensive guidance on installing the necessary dependencies for developing applications targeting the Xtensa +ESP32 architecture, +please refer to [the official website](https://docs.esp-rs.org/book/installation/riscv-and-xtensa.html). +Below is an illustrative example demonstrating the installation of building toolchains on a Linux (Ubuntu/Debian): + +``` +apt-get -qq update +apt-get install -y -q build-essential curl +curl https://sh.rustup.rs -sSf | sh -s -- -y +cargo install espup +espup install +``` + +## How to build the example + +For a thorough guide on developing projects for the Xtensa ESP32 architecture across various operating systems, +we recommend +consulting [the official website](https://docs.esp-rs.org/book/installation/riscv-and-xtensa.html#3-set-up-the-environment-variables). +Below, you will find an illustrative example showcasing the building process on a Linux system (Ubuntu/Debian): + +``` +. $HOME/export-esp.sh +cargo build --release +``` + +## How to run the example + +For detailed instructions on running projects for the Xtensa ESP32 architecture across various operating systems, +we recommend consulting [the official website](https://docs.esp-rs.org/book/tooling/espflash.html). +Below, you will find an illustrative example showcasing the running on a Linux system (Ubuntu/Debian): + +``` +cargo run +``` diff --git a/examples/rust-examples/xtensa-esp32/scheduler/preemptive/rust-toolchain.toml b/examples/rust-examples/xtensa-esp32/scheduler/preemptive/rust-toolchain.toml new file mode 100644 index 0000000..a2f5ab5 --- /dev/null +++ b/examples/rust-examples/xtensa-esp32/scheduler/preemptive/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "esp" diff --git a/examples/rust-examples/xtensa-esp32/scheduler/src/main.rs b/examples/rust-examples/xtensa-esp32/scheduler/preemptive/src/main.rs similarity index 100% rename from examples/rust-examples/xtensa-esp32/scheduler/src/main.rs rename to examples/rust-examples/xtensa-esp32/scheduler/preemptive/src/main.rs From 520b3444770769e6a68400872c85a51eff8c0896 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Thu, 26 Dec 2024 20:55:09 +0300 Subject: [PATCH 46/50] Fix linker scripts according to ci errors --- examples/c-examples/risc-v-esp32c6/ld/esp32c6.ld | 4 ++-- examples/c-examples/xtensa-esp32/ld/esp32.ld | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/c-examples/risc-v-esp32c6/ld/esp32c6.ld b/examples/c-examples/risc-v-esp32c6/ld/esp32c6.ld index c6d0408..9e1283d 100644 --- a/examples/c-examples/risc-v-esp32c6/ld/esp32c6.ld +++ b/examples/c-examples/risc-v-esp32c6/ld/esp32c6.ld @@ -22,9 +22,9 @@ /* These lengths can be adjusted, if necessary: */ bootloader_usable_dram_end = 0x4087c610; bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */ -bootloader_dram_seg_len = 0xD270; +bootloader_dram_seg_len = 0xD338; bootloader_iram_loader_seg_len = 0x7000; -bootloader_iram_seg_len = 0x4000; +bootloader_iram_seg_len = 0x4212; /* Start of the lower region is determined by region size and the end of the higher region */ bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead; diff --git a/examples/c-examples/xtensa-esp32/ld/esp32.ld b/examples/c-examples/xtensa-esp32/ld/esp32.ld index f2c5b3e..8888fad 100644 --- a/examples/c-examples/xtensa-esp32/ld/esp32.ld +++ b/examples/c-examples/xtensa-esp32/ld/esp32.ld @@ -15,7 +15,7 @@ MEMORY /* TODO: Use human-readable lengths */ /* TODO: Use the full memory map - this is just a test */ iram_seg ( RX ) : ORIGIN = 0x40080400, len = 0xFC00 - dram_seg ( RW ) : ORIGIN = 0x3FFF0000, len = 0x100A8 + dram_seg ( RW ) : ORIGIN = 0x3FFF0000, len = 0x10120 } /* Define output sections */ From 8c99ca9ea07f78e3725c7d3cf0288b661bb8809a Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Thu, 26 Dec 2024 22:54:11 +0300 Subject: [PATCH 47/50] Fix linker script for esp32c6 --- examples/c-examples/risc-v-esp32c6/ld/esp32c6.ld | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/c-examples/risc-v-esp32c6/ld/esp32c6.ld b/examples/c-examples/risc-v-esp32c6/ld/esp32c6.ld index 9e1283d..d446813 100644 --- a/examples/c-examples/risc-v-esp32c6/ld/esp32c6.ld +++ b/examples/c-examples/risc-v-esp32c6/ld/esp32c6.ld @@ -24,7 +24,7 @@ bootloader_usable_dram_end = 0x4087c610; bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */ bootloader_dram_seg_len = 0xD338; bootloader_iram_loader_seg_len = 0x7000; -bootloader_iram_seg_len = 0x4212; +bootloader_iram_seg_len = 0x421C; /* Start of the lower region is determined by region size and the end of the higher region */ bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead; From 899cb669af78c08da96db3385b18ef04193476e6 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Sun, 29 Dec 2024 15:11:12 +0300 Subject: [PATCH 48/50] Fix wake up test --- tests/task_manager_unit_tests.rs | 34 ++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/tests/task_manager_unit_tests.rs b/tests/task_manager_unit_tests.rs index 20011e4..f6a563b 100644 --- a/tests/task_manager_unit_tests.rs +++ b/tests/task_manager_unit_tests.rs @@ -212,10 +212,10 @@ mod task_manager_unit_tests { /// Loop functions for task for test_wake_up_sleeping_task. fn test_wake_up_sleeping_task_loop_fn() { - TaskManager::wake_up_task(2); + TaskManager::wake_up_task(3); } fn test_put_to_sleep_task_loop_fn() { - TaskManager::put_to_sleep(2); + TaskManager::put_to_sleep(3); } #[test] #[sequential] @@ -226,31 +226,39 @@ mod task_manager_unit_tests { test_put_to_sleep_task_loop_fn, dummy_condition_true, ); + TaskManager::add_task( + dummy_setup_fn, + test_wake_up_sleeping_task_loop_fn, + dummy_condition_true, + ); TaskManager::add_task(dummy_setup_fn, dummy_loop_fn, dummy_condition_true); - let task_2 = - TaskManager::get_task_by_id(2).unwrap_or_else(|| panic!("Task not found for id 2")); - assert_eq!(TaskManager::get_status(task_2), TaskManager::ready_status()); + let mut task_3 = + TaskManager::get_task_by_id(3).unwrap_or_else(|| panic!("Task not found for id 3")); + + assert_eq!(TaskManager::get_status(task_3), TaskManager::ready_status()); TaskManager::schedule(); TaskManager::schedule(); + task_3 = + TaskManager::get_task_by_id(3).unwrap_or_else(|| panic!("Task not found for id 3")); + assert_eq!( - TaskManager::get_status(task_2), + TaskManager::get_status(task_3), TaskManager::sleeping_status() ); - TaskManager::add_task( - dummy_setup_fn, - test_wake_up_sleeping_task_loop_fn, - dummy_condition_true, - ); - TaskManager::schedule(); TaskManager::schedule(); TaskManager::schedule(); TaskManager::schedule(); + task_3 = + TaskManager::get_task_by_id(3).unwrap_or_else(|| panic!("Task not found for id 3")); - assert_eq!(TaskManager::get_status(task_2), TaskManager::ready_status()); + assert_eq!(TaskManager::get_status(task_3), TaskManager::ready_status()); + + TaskManager::test_start_task_manager(); + assert_eq!(TaskManager::count_all_tasks(), 0); } /// Loop functions for task for test_wake_up_non_sleeping_task_loop_fn. From 9ce3a1cb0f2013c706376c47f8201d86d06dfd30 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Sun, 29 Dec 2024 18:31:59 +0300 Subject: [PATCH 49/50] Add ci to local repo --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 411ed28..3b170af 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -2,7 +2,7 @@ name: Martos ci workflow on: push: - branches: [ "main" ] + branches: [ "main", "sync/preemp" ] pull_request: branches: [ "main" ] From f013647d7296c693720f9c57e8dbf9ccfa05a059 Mon Sep 17 00:00:00 2001 From: Lutsyuk Victoria Date: Sun, 29 Dec 2024 23:29:52 +0300 Subject: [PATCH 50/50] Fix ld/esp32c6.ld --- examples/c-examples/risc-v-esp32c6/ld/esp32c6.ld | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/c-examples/risc-v-esp32c6/ld/esp32c6.ld b/examples/c-examples/risc-v-esp32c6/ld/esp32c6.ld index d446813..2166bb3 100644 --- a/examples/c-examples/risc-v-esp32c6/ld/esp32c6.ld +++ b/examples/c-examples/risc-v-esp32c6/ld/esp32c6.ld @@ -45,7 +45,7 @@ MEMORY * 2. Update the value in this assert. * 3. Update SRAM_DRAM_END in components/esp_system/ld/esp32c6/memory.ld.in to the same value. */ -ASSERT(bootloader_iram_loader_seg_start == 0x408663A0, "bootloader_iram_loader_seg_start inconsistent with SRAM_DRAM_END"); +ASSERT(bootloader_iram_loader_seg_start == 0x408662D8, "bootloader_iram_loader_seg_start inconsistent with SRAM_DRAM_END"); /* Default entry point: */ ENTRY(call_start_cpu0);