diff --git a/framework/aster-frame/src/boot/mod.rs b/framework/aster-frame/src/boot/mod.rs index 35382211..2f1c5a01 100644 --- a/framework/aster-frame/src/boot/mod.rs +++ b/framework/aster-frame/src/boot/mod.rs @@ -119,13 +119,26 @@ pub fn call_aster_main() -> ! { } #[cfg(ktest)] unsafe { + use alloc::boxed::Box; + + use crate::task::{set_scheduler, FifoScheduler, Scheduler, TaskOptions}; + crate::init(); // The whitelists that will be generated by OSDK runner as static consts. extern "Rust" { static KTEST_TEST_WHITELIST: Option<&'static [&'static str]>; static KTEST_CRATE_WHITELIST: Option<&'static [&'static str]>; } - run_ktests(KTEST_TEST_WHITELIST, KTEST_CRATE_WHITELIST); + // Set the global scheduler a FIFO scheduler. + let simple_scheduler = Box::new(FifoScheduler::new()); + let static_scheduler: &'static dyn Scheduler = Box::leak(simple_scheduler); + set_scheduler(static_scheduler); + + let test_task = move || { + run_ktests(KTEST_TEST_WHITELIST, KTEST_CRATE_WHITELIST); + }; + let _ = TaskOptions::new(test_task).data(()).spawn(); + unreachable!("The spawn method will NOT return in the boot context") } } diff --git a/framework/aster-frame/src/task/mod.rs b/framework/aster-frame/src/task/mod.rs index f986e223..7ed56593 100644 --- a/framework/aster-frame/src/task/mod.rs +++ b/framework/aster-frame/src/task/mod.rs @@ -11,6 +11,6 @@ mod task; pub use self::{ priority::Priority, processor::{current_task, disable_preempt, preempt, schedule, DisablePreemptGuard}, - scheduler::{add_task, set_scheduler, Scheduler}, + scheduler::{add_task, set_scheduler, FifoScheduler, Scheduler}, task::{Task, TaskAdapter, TaskOptions, TaskStatus}, }; diff --git a/framework/aster-frame/src/task/scheduler.rs b/framework/aster-frame/src/task/scheduler.rs index c9518b13..a7e515ce 100644 --- a/framework/aster-frame/src/task/scheduler.rs +++ b/framework/aster-frame/src/task/scheduler.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 +use alloc::collections::VecDeque; + use lazy_static::lazy_static; use crate::{prelude::*, sync::SpinLock, task::Task}; @@ -60,3 +62,40 @@ pub fn fetch_task() -> Option> { pub fn add_task(task: Arc) { GLOBAL_SCHEDULER.lock_irq_disabled().enqueue(task); } + +/// A simple FIFO (First-In-First-Out) task scheduler. +pub struct FifoScheduler { + /// A thread-safe queue to hold tasks waiting to be executed. + task_queue: SpinLock>>, +} + +impl FifoScheduler { + /// Creates a new instance of `FifoScheduler`. + pub const fn new() -> Self { + FifoScheduler { + task_queue: SpinLock::new(VecDeque::new()), + } + } +} + +impl Default for FifoScheduler { + fn default() -> Self { + Self::new() + } +} + +impl Scheduler for FifoScheduler { + /// Enqueues a task to the end of the queue. + fn enqueue(&self, task: Arc) { + self.task_queue.lock_irq_disabled().push_back(task); + } + /// Dequeues a task from the front of the queue, if any. + fn dequeue(&self) -> Option> { + self.task_queue.lock_irq_disabled().pop_front() + } + /// In this simple implementation, task preemption is not supported. + /// Once a task starts running, it will continue to run until completion. + fn should_preempt(&self, _task: &Arc) -> bool { + false + } +} diff --git a/framework/aster-frame/src/task/task.rs b/framework/aster-frame/src/task/task.rs index 1171858c..8e789106 100644 --- a/framework/aster-frame/src/task/task.rs +++ b/framework/aster-frame/src/task/task.rs @@ -303,3 +303,26 @@ impl TaskOptions { Ok(task) } } + +#[cfg(ktest)] +mod test { + #[ktest] + fn create_task() { + let task = || { + assert_eq!(1, 1); + }; + let task_option = crate::task::TaskOptions::new(task) + .data(()) + .build() + .unwrap(); + task_option.run(); + } + + #[ktest] + fn spawn_task() { + let task = || { + assert_eq!(1, 1); + }; + let _ = crate::task::TaskOptions::new(task).data(()).spawn(); + } +} diff --git a/kernel/aster-nix/src/sched/priority_scheduler.rs b/kernel/aster-nix/src/sched/priority_scheduler.rs index 2c4479ca..1ee3628d 100644 --- a/kernel/aster-nix/src/sched/priority_scheduler.rs +++ b/kernel/aster-nix/src/sched/priority_scheduler.rs @@ -36,13 +36,9 @@ impl PreemptScheduler { impl Scheduler for PreemptScheduler { fn enqueue(&self, task: Arc) { if task.is_real_time() { - self.real_time_tasks - .lock_irq_disabled() - .push_back(task.clone()); + self.real_time_tasks.lock_irq_disabled().push_back(task); } else { - self.normal_tasks - .lock_irq_disabled() - .push_back(task.clone()); + self.normal_tasks.lock_irq_disabled().push_back(task); } }