Enable kernel mode unit tests in kernel threads

This commit is contained in:
Fabing Li 2024-04-18 11:00:36 +08:00 committed by Tate, Hongliang Tian
parent 57cb922253
commit c335873d12
5 changed files with 79 additions and 8 deletions

View File

@ -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")
}
}

View File

@ -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},
};

View File

@ -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<Arc<Task>> {
pub fn add_task(task: Arc<Task>) {
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<VecDeque<Arc<Task>>>,
}
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<Task>) {
self.task_queue.lock_irq_disabled().push_back(task);
}
/// Dequeues a task from the front of the queue, if any.
fn dequeue(&self) -> Option<Arc<Task>> {
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<Task>) -> bool {
false
}
}

View File

@ -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();
}
}

View File

@ -36,13 +36,9 @@ impl PreemptScheduler {
impl Scheduler for PreemptScheduler {
fn enqueue(&self, task: Arc<Task>) {
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);
}
}