diff --git a/applications/tests/test_multi_prioritized_scheduler/Cargo.toml b/applications/tests/test_multi_prioritized_scheduler/Cargo.toml new file mode 100644 index 000000000..07fbc1f3c --- /dev/null +++ b/applications/tests/test_multi_prioritized_scheduler/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "test_multi_prioritized_scheduler" +version = "0.1.0" +edition = "2021" + +[dependencies] +log = "0.4" + +[dependencies.awkernel_async_lib] +path = "../../../awkernel_async_lib" +default-features = false + +[dependencies.awkernel_lib] +path = "../../../awkernel_lib" +default-features = false diff --git a/applications/tests/test_multi_prioritized_scheduler/src/lib.rs b/applications/tests/test_multi_prioritized_scheduler/src/lib.rs new file mode 100644 index 000000000..349788884 --- /dev/null +++ b/applications/tests/test_multi_prioritized_scheduler/src/lib.rs @@ -0,0 +1,51 @@ +#![no_std] + +extern crate alloc; + +use awkernel_async_lib::{scheduler::SchedulerType, spawn}; +use awkernel_lib::{cpu::num_cpu, delay::wait_millisec}; + +pub async fn run() { + wait_millisec(1000); + for i in 1..num_cpu() { + let sched_type = if i % 3 == 0 { + SchedulerType::PrioritizedFIFO(0) + } else if i % 3 == 1 { + SchedulerType::PrioritizedRR(0) + } else { + SchedulerType::GEDF(1000) + }; + + spawn( + "low_priority".into(), + async move { + log::debug!("low priority task {i} started. sched_type = {sched_type:?}"); + wait_millisec(1000); + log::debug!("low priority task {i} finished. sched_type = {sched_type:?}"); + }, + sched_type, + ) + .await; + } + + for i in 1..num_cpu() { + let sched_type = if i % 3 == 0 { + SchedulerType::PrioritizedFIFO(1) + } else if i % 3 == 1 { + SchedulerType::PrioritizedRR(1) + } else { + SchedulerType::GEDF(500) + }; + + spawn( + "high_priority".into(), + async move { + log::debug!("high priority task {i} started. sched_type = {sched_type:?}"); + wait_millisec(100); + log::debug!("high priority task {i} finished. sched_type = {sched_type:?}"); + }, + sched_type, + ) + .await; + } +} diff --git a/awkernel_async_lib/src/scheduler.rs b/awkernel_async_lib/src/scheduler.rs index b85f8b50a..9371dd7ea 100644 --- a/awkernel_async_lib/src/scheduler.rs +++ b/awkernel_async_lib/src/scheduler.rs @@ -116,6 +116,11 @@ static PRIORITY_LIST: [SchedulerType; 4] = [ SchedulerType::Panicked, ]; +/// For exclusion execution of `wake_task` and `get_next` across all schedulers. +/// In order to resolve priority inversion in multiple priority-based schedulers, +/// the decision to preempt, dequeuing, enqueuing, and updating of RUNNING must be executed exclusively. +static GLOBAL_WAKE_GET_MUTEX: Mutex<()> = Mutex::new(()); + pub(crate) trait Scheduler { /// Enqueue an executable task. /// The enqueued task will be taken by `get_next()`. @@ -134,6 +139,9 @@ pub(crate) trait Scheduler { /// Get the next executable task. #[inline] pub(crate) fn get_next_task(execution_ensured: bool) -> Option> { + let mut node = MCSNode::new(); + let _guard = GLOBAL_WAKE_GET_MUTEX.lock(&mut node); + let task = PRIORITY_LIST .iter() .find_map(|&scheduler_type| get_scheduler(scheduler_type).get_next(execution_ensured)); diff --git a/awkernel_async_lib/src/scheduler/gedf.rs b/awkernel_async_lib/src/scheduler/gedf.rs index 82bacdde2..09ec0d4f3 100644 --- a/awkernel_async_lib/src/scheduler/gedf.rs +++ b/awkernel_async_lib/src/scheduler/gedf.rs @@ -5,6 +5,7 @@ use core::cmp::max; use super::{Scheduler, SchedulerType, Task}; use crate::{ dag::{get_dag, get_dag_absolute_deadline, set_dag_absolute_deadline, to_node_index}, + scheduler::GLOBAL_WAKE_GET_MUTEX, scheduler::{get_priority, peek_preemption_pending, push_preemption_pending}, task::{ get_task, get_tasks_running, set_current_task, set_need_preemption, DagInfo, State, @@ -62,13 +63,6 @@ impl GEDFData { impl Scheduler for GEDFScheduler { fn wake_task(&self, task: Arc) { - let mut node = MCSNode::new(); - // The reason for acquiring this lock before invoke_preemption() is to prevent priority inversion from occurring - // when invoke_preemption() is executed between the time the next task is determined and the RUNNING is updated - // within the scheduler's get_next(). - let mut data = self.data.lock(&mut node); - let internal_data = data.get_or_insert_with(GEDFData::new); - let (wake_time, absolute_deadline) = { let mut node_inner = MCSNode::new(); let mut info = task.info.lock(&mut node_inner); @@ -94,7 +88,12 @@ impl Scheduler for GEDFScheduler { } }; + let mut node = MCSNode::new(); + let _guard = GLOBAL_WAKE_GET_MUTEX.lock(&mut node); if !self.invoke_preemption(task.clone()) { + let mut node_inner = MCSNode::new(); + let mut data = self.data.lock(&mut node_inner); + let internal_data = data.get_or_insert_with(GEDFData::new); internal_data.queue.push(GEDFTask { task: task.clone(), absolute_deadline, diff --git a/awkernel_async_lib/src/scheduler/prioritized_fifo.rs b/awkernel_async_lib/src/scheduler/prioritized_fifo.rs index 2f387249f..da125cf3b 100644 --- a/awkernel_async_lib/src/scheduler/prioritized_fifo.rs +++ b/awkernel_async_lib/src/scheduler/prioritized_fifo.rs @@ -3,7 +3,7 @@ use core::cmp::max; use super::{Scheduler, SchedulerType, Task}; -use crate::scheduler::{peek_preemption_pending, push_preemption_pending}; +use crate::scheduler::{peek_preemption_pending, push_preemption_pending, GLOBAL_WAKE_GET_MUTEX}; use crate::task::{get_task, get_tasks_running, set_current_task, set_need_preemption}; use crate::{scheduler::get_priority, task::State}; use alloc::sync::Arc; @@ -35,12 +35,6 @@ impl PrioritizedFIFOData { impl Scheduler for PrioritizedFIFOScheduler { fn wake_task(&self, task: Arc) { - let mut node = MCSNode::new(); - // The reason for acquiring this lock before invoke_preemption() is to prevent priority inversion from occurring - // when invoke_preemption() is executed between the time the next task is determined and the RUNNING is updated - // within the scheduler's get_next(). - let mut data = self.data.lock(&mut node); - let internal_data = data.get_or_insert_with(PrioritizedFIFOData::new); let priority = { let mut node_inner = MCSNode::new(); let info = task.info.lock(&mut node_inner); @@ -50,7 +44,12 @@ impl Scheduler for PrioritizedFIFOScheduler { } }; + let mut node = MCSNode::new(); + let _guard = GLOBAL_WAKE_GET_MUTEX.lock(&mut node); if !self.invoke_preemption(task.clone()) { + let mut node_inner = MCSNode::new(); + let mut data = self.data.lock(&mut node_inner); + let internal_data = data.get_or_insert_with(PrioritizedFIFOData::new); internal_data.queue.push( priority, PrioritizedFIFOTask { diff --git a/awkernel_async_lib/src/scheduler/prioritized_rr.rs b/awkernel_async_lib/src/scheduler/prioritized_rr.rs index c109cea26..d06b3fe63 100644 --- a/awkernel_async_lib/src/scheduler/prioritized_rr.rs +++ b/awkernel_async_lib/src/scheduler/prioritized_rr.rs @@ -4,7 +4,10 @@ use core::cmp::max; use super::{Scheduler, SchedulerType, Task}; use crate::{ - scheduler::{get_next_task, get_priority, peek_preemption_pending, push_preemption_pending}, + scheduler::{ + get_next_task, get_priority, peek_preemption_pending, push_preemption_pending, + GLOBAL_WAKE_GET_MUTEX, + }, task::{ get_last_executed_by_task_id, get_task, get_tasks_running, set_current_task, set_need_preemption, State, @@ -40,12 +43,6 @@ impl PrioritizedRRData { impl Scheduler for PrioritizedRRScheduler { fn wake_task(&self, task: Arc) { - let mut node = MCSNode::new(); - // The reason for acquiring this lock before invoke_preemption() is to prevent priority inversion from occurring - // when invoke_preemption() is executed between the time the next task is determined and the RUNNING is updated - // within the scheduler's get_next(). - let mut data = self.data.lock(&mut node); - let internal_data = data.get_or_insert_with(PrioritizedRRData::new); let priority = { let mut node_inner = MCSNode::new(); let info = task.info.lock(&mut node_inner); @@ -55,7 +52,12 @@ impl Scheduler for PrioritizedRRScheduler { } }; + let mut node = MCSNode::new(); + let _guard = GLOBAL_WAKE_GET_MUTEX.lock(&mut node); if !self.invoke_preemption_wake(task.clone()) { + let mut node_inner = MCSNode::new(); + let mut data = self.data.lock(&mut node_inner); + let internal_data = data.get_or_insert_with(PrioritizedRRData::new); internal_data.queue.push( priority, PrioritizedRRTask { diff --git a/specification/awkernel_async_lib/src/task/preemptive_spin/README.md b/specification/awkernel_async_lib/src/task/preemptive_spin/README.md index d4d2171de..6a96dc29f 100644 --- a/specification/awkernel_async_lib/src/task/preemptive_spin/README.md +++ b/specification/awkernel_async_lib/src/task/preemptive_spin/README.md @@ -185,7 +185,7 @@ To keep the model less complex, please note the following abstractions compared - For priority comparison, we use the simple priority value (`TaskInfo.id`) as before, rather than `combine_priority`. - This is ensured by guaranteeing that tasks with larger ids are never assigned to scheduler types with higher priority. -### Results +### First Results (The errors are found) [Used Version](https://github.com/tier4/awkernel/commit/8ee41ca90485ed3360e4e4c0345d9882833be7cb) @@ -306,3 +306,586 @@ spin: _spin_nvr.tmp:21, Error: assertion violated spin: text of failed assertion: assert(!(!((!(((((((((((((((waking[0]==0)&&(waking[1]==0))&&(waking[2]==0))&&(waking[3]==0))&&(len(ipi_requests[0])==0))&&(RUNNING[0]!=-(1)))&&(RUNNING[0]!=runnable_preempted_highest_priority))&&(len(ipi_requests[1])==0))&&(RUNNING[1]!=-(1)))&&(RUNNING[1]!=runnable_preempted_highest_priority))&&!(handling_interrupt[0]))&&!(handling_interrupt[1]))&&!(handling_interrupt[2]))&&!(handling_interrupt[3])))||(running_lowest_priority ((num_terminated==4)) +ltl eventually_prerequisites: [] (<> (((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((len(ipi_requests[1])==0))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) +ltl ensure_priority: [] ((! (((((((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((RUNNING[0]!=-(1)))) && ((RUNNING[0]!=runnable_preempted_highest_priority))) && ((len(ipi_requests[1])==0))) && ((RUNNING[1]!=-(1)))) && ((RUNNING[1]!=runnable_preempted_highest_priority))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) || ((running_lowest_priority ((num_terminated==4)) +ltl eventually_prerequisites: [] (<> (((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((len(ipi_requests[1])==0))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) +ltl ensure_priority: [] ((! (((((((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((RUNNING[0]!=-(1)))) && ((RUNNING[0]!=runnable_preempted_highest_priority))) && ((len(ipi_requests[1])==0))) && ((RUNNING[1]!=-(1)))) && ((RUNNING[1]!=runnable_preempted_highest_priority))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) || ((running_lowest_priority ((num_terminated==4)) +ltl eventually_prerequisites: [] (<> (((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((len(ipi_requests[1])==0))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) +ltl ensure_priority: [] ((! (((((((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((RUNNING[0]!=-(1)))) && ((RUNNING[0]!=runnable_preempted_highest_priority))) && ((len(ipi_requests[1])==0))) && ((RUNNING[1]!=-(1)))) && ((RUNNING[1]!=runnable_preempted_highest_priority))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) || ((running_lowest_priority ((num_terminated==4)) +ltl eventually_prerequisites: [] (<> (((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((len(ipi_requests[1])==0))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) +ltl ensure_priority: [] ((! (((((((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((RUNNING[0]!=-(1)))) && ((RUNNING[0]!=runnable_preempted_highest_priority))) && ((len(ipi_requests[1])==0))) && ((RUNNING[1]!=-(1)))) && ((RUNNING[1]!=runnable_preempted_highest_priority))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) || ((running_lowest_priority ((num_terminated==4)) +ltl eventually_prerequisites: [] (<> (((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((len(ipi_requests[1])==0))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) +ltl ensure_priority: [] ((! (((((((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((RUNNING[0]!=-(1)))) && ((RUNNING[0]!=runnable_preempted_highest_priority))) && ((len(ipi_requests[1])==0))) && ((RUNNING[1]!=-(1)))) && ((RUNNING[1]!=runnable_preempted_highest_priority))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) || ((running_lowest_priority ((num_terminated==4)) +ltl eventually_prerequisites: [] (<> (((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((len(ipi_requests[1])==0))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) +ltl ensure_priority: [] ((! (((((((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((RUNNING[0]!=-(1)))) && ((RUNNING[0]!=runnable_preempted_highest_priority))) && ((len(ipi_requests[1])==0))) && ((RUNNING[1]!=-(1)))) && ((RUNNING[1]!=runnable_preempted_highest_priority))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) || ((running_lowest_priority ((num_terminated==4)) +ltl eventually_prerequisites: [] (<> (((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((len(ipi_requests[1])==0))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) +ltl ensure_priority: [] ((! (((((((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((RUNNING[0]!=-(1)))) && ((RUNNING[0]!=runnable_preempted_highest_priority))) && ((len(ipi_requests[1])==0))) && ((RUNNING[1]!=-(1)))) && ((RUNNING[1]!=runnable_preempted_highest_priority))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) || ((running_lowest_priority ((num_terminated==4)) +ltl eventually_prerequisites: [] (<> (((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((len(ipi_requests[1])==0))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) +ltl ensure_priority: [] ((! (((((((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((RUNNING[0]!=-(1)))) && ((RUNNING[0]!=runnable_preempted_highest_priority))) && ((len(ipi_requests[1])==0))) && ((RUNNING[1]!=-(1)))) && ((RUNNING[1]!=runnable_preempted_highest_priority))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) || ((running_lowest_priority ((num_terminated==4)) +ltl eventually_prerequisites: [] (<> (((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((len(ipi_requests[1])==0))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) +ltl ensure_priority: [] ((! (((((((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((RUNNING[0]!=-(1)))) && ((RUNNING[0]!=runnable_preempted_highest_priority))) && ((len(ipi_requests[1])==0))) && ((RUNNING[1]!=-(1)))) && ((RUNNING[1]!=runnable_preempted_highest_priority))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) || ((running_lowest_priority ((num_terminated==4)) +ltl eventually_prerequisites: [] (<> (((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((len(ipi_requests[1])==0))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) +ltl ensure_priority: [] ((! (((((((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((RUNNING[0]!=-(1)))) && ((RUNNING[0]!=runnable_preempted_highest_priority))) && ((len(ipi_requests[1])==0))) && ((RUNNING[1]!=-(1)))) && ((RUNNING[1]!=runnable_preempted_highest_priority))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) || ((running_lowest_priority ((num_terminated==4)) +ltl eventually_prerequisites: [] (<> (((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((len(ipi_requests[1])==0))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) +ltl ensure_priority: [] ((! (((((((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((RUNNING[0]!=-(1)))) && ((RUNNING[0]!=runnable_preempted_highest_priority))) && ((len(ipi_requests[1])==0))) && ((RUNNING[1]!=-(1)))) && ((RUNNING[1]!=runnable_preempted_highest_priority))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) || ((running_lowest_priority ((num_terminated==4)) +ltl eventually_prerequisites: [] (<> (((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((len(ipi_requests[1])==0))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) +ltl ensure_priority: [] ((! (((((((((((((((waking[0]==0)) && ((waking[1]==0))) && ((waking[2]==0))) && ((waking[3]==0))) && ((len(ipi_requests[0])==0))) && ((RUNNING[0]!=-(1)))) && ((RUNNING[0]!=runnable_preempted_highest_priority))) && ((len(ipi_requests[1])==0))) && ((RUNNING[1]!=-(1)))) && ((RUNNING[1]!=runnable_preempted_highest_priority))) && (! (handling_interrupt[0]))) && (! (handling_interrupt[1]))) && (! (handling_interrupt[2]))) && (! (handling_interrupt[3])))) || ((running_lowest_priority + lock(tid,lock_queue[tasks[task].scheduler_type]); d_step{ printf("wake_task(): push to queue: tid = %d,task = %d\n",tid,task); queue[tasks[task].scheduler_type]!!task } + unlock(tid,lock_queue[tasks[task].scheduler_type]); :: else fi - unlock(tid,lock_queue[tasks[task].scheduler_type]); + unlock(tid,lock_global_wake_get_mutex); d_step { assert(waking[task] > 0); waking[task]-- @@ -167,16 +169,17 @@ inline get_next_each_scheduler(tid,ret,sched_type) { } unlock(tid,lock_info[head]); - unlock(tid,lock_queue[sched_type]); ret = head :: else -> - unlock(tid,lock_queue[sched_type]); ret = - 1 fi + + unlock(tid,lock_queue[sched_type]); } /* awkernel_async_lib::task::scheduler::get_next_task() */ inline scheduler_get_next(tid,ret) { + lock(tid,lock_global_wake_get_mutex); byte sched_i; for (sched_i : 0 .. SCHEDULER_TYPE_NUM - 1) { get_next_each_scheduler(tid,ret,sched_i); @@ -185,6 +188,7 @@ inline scheduler_get_next(tid,ret) { :: else fi } + unlock(tid,lock_global_wake_get_mutex); } /* awkernel_async_lib::task::preempt::get_next_task()*/ diff --git a/userland/Cargo.toml b/userland/Cargo.toml index 96e582732..664ec35f3 100644 --- a/userland/Cargo.toml +++ b/userland/Cargo.toml @@ -38,6 +38,10 @@ optional = true path = "../applications/tests/test_prioritized_fifo" optional = true +[dependencies.test_multi_prioritized_scheduler] +path = "../applications/tests/test_multi_prioritized_scheduler" +optional = true + [dependencies.test_prioritized_rr] path = "../applications/tests/test_prioritized_rr" optional = true diff --git a/userland/src/lib.rs b/userland/src/lib.rs index 60123208c..01a66fe18 100644 --- a/userland/src/lib.rs +++ b/userland/src/lib.rs @@ -25,6 +25,9 @@ pub async fn main() -> Result<(), Cow<'static, str>> { #[cfg(feature = "test_prioritized_fifo")] test_prioritized_fifo::run().await; // test for prioritized_fifo + #[cfg(feature = "test_multi_prioritized_scheduler")] + test_multi_prioritized_scheduler::run().await; // test for multi prioritized scheduler + #[cfg(feature = "test_prioritized_rr")] test_prioritized_rr::run().await; // test for prioritized_rr