diff --git a/src/constance/src/kernel.rs b/src/constance/src/kernel.rs index 4f54121aa2..90c1f814fb 100644 --- a/src/constance/src/kernel.rs +++ b/src/constance/src/kernel.rs @@ -1,8 +1,8 @@ //! The RTOS kernel use atomic_ref::AtomicRef; -use core::{fmt, mem::forget, num::NonZeroUsize, sync::atomic::Ordering}; +use core::{borrow::BorrowMut, fmt, mem::forget, num::NonZeroUsize, sync::atomic::Ordering}; -use crate::utils::{BinUInteger, Init, PrioBitmap}; +use crate::utils::{intrusive_list::StaticListHead, BinUInteger, Init, PrioBitmap}; #[macro_use] mod cfg; @@ -218,6 +218,8 @@ pub unsafe trait KernelCfg2: Port + Sized { type TaskReadyBitmap: PrioBitmap; + type TaskReadyQueue: BorrowMut<[StaticListHead>]> + Init + 'static; + /// Access the kernel's global state. fn state() -> &'static State; @@ -239,6 +241,7 @@ pub struct State< System: KernelCfg2, PortTaskState: 'static = ::PortTaskState, TaskReadyBitmap: PrioBitmap = ::TaskReadyBitmap, + TaskReadyQueue: 'static = ::TaskReadyQueue, TaskPriority: 'static = ::TaskPriority, > { // TODO: Make `running_task` non-null to simplify runtime code @@ -248,18 +251,24 @@ pub struct State< /// The task ready bitmap, in which each bit indicates whether the /// task ready queue corresponding to that bit contains a task or not. task_ready_bitmap: utils::CpuLockCell, + + /// The task ready queues, in which each queue represents the list of + /// runnable task at the corresponding priority level. + task_ready_queue: utils::CpuLockCell, } impl< System: KernelCfg2, PortTaskState: 'static, TaskReadyBitmap: PrioBitmap, + TaskReadyQueue: 'static + Init, TaskPriority: 'static, - > Init for State + > Init for State { const INIT: Self = Self { running_task: AtomicRef::new(None), task_ready_bitmap: Init::INIT, + task_ready_queue: Init::INIT, }; } @@ -267,19 +276,26 @@ impl< System: Kernel, PortTaskState: 'static + fmt::Debug, TaskReadyBitmap: PrioBitmap, + TaskReadyQueue: 'static + fmt::Debug, TaskPriority: 'static, - > fmt::Debug for State + > fmt::Debug for State { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("State") .field("running_task", &self.running_task) .field("task_ready_bitmap", &self.task_ready_bitmap) + .field("task_ready_queue", &self.task_ready_queue) .finish() } } -impl - State +impl< + System: KernelCfg2, + PortTaskState: 'static, + TaskReadyBitmap: PrioBitmap, + TaskReadyQueue: BorrowMut<[StaticListHead>]> + Init + 'static, + TaskPriority, + > State { /// Get the currently running task. pub fn running_task(&self) -> Option<&'static TaskCb> { diff --git a/src/constance/src/kernel/cfg.rs b/src/constance/src/kernel/cfg.rs index 9e456417d6..bba6e29fd8 100644 --- a/src/constance/src/kernel/cfg.rs +++ b/src/constance/src/kernel/cfg.rs @@ -152,7 +152,10 @@ macro_rules! build { CfgBuilder, HunkAttr, HunkInitAttr, KernelCfg1, KernelCfg2, Port, State, TaskAttr, TaskCb, }, - utils::{AlignedStorage, FixedPrioBitmap, Init, RawCell, UIntegerWithBound}, + utils::{ + intrusive_list::StaticListHead, AlignedStorage, FixedPrioBitmap, Init, RawCell, + UIntegerWithBound, + }, }; // `$configure` produces two values: a `CfgBuilder` and an ID map @@ -205,6 +208,7 @@ macro_rules! build { // Safety: We are `build!`, so it's okay to `impl` this unsafe impl KernelCfg2 for $sys { type TaskReadyBitmap = TaskReadyBitmap; + type TaskReadyQueue = [StaticListHead>; CFG.num_task_priority_levels]; fn state() -> &'static KernelState { &KERNEL_STATE diff --git a/src/constance/src/utils.rs b/src/constance/src/utils.rs index f37d90e2d3..e5a4ecce24 100644 --- a/src/constance/src/utils.rs +++ b/src/constance/src/utils.rs @@ -17,7 +17,7 @@ macro_rules! If { mod aligned_storage; mod init; mod int; -pub(crate) mod intrusive_list; +pub mod intrusive_list; mod prio_bitmap; mod rawcell; mod zeroinit; diff --git a/src/constance_port_std/src/lib.rs b/src/constance_port_std/src/lib.rs index c593ad736c..3120f15c41 100644 --- a/src/constance_port_std/src/lib.rs +++ b/src/constance_port_std/src/lib.rs @@ -1,7 +1,7 @@ #![feature(unsafe_block_in_unsafe_fn)] // `unsafe fn` doesn't imply `unsafe {}` #![deny(unsafe_op_in_unsafe_fn)] use atomic_ref::AtomicRef; -use constance::prelude::*; +use constance::{prelude::*, utils::intrusive_list::StaticListHead}; use parking_lot::{lock_api::RawMutex, Mutex}; use std::{ mem::ManuallyDrop, @@ -121,6 +121,8 @@ impl State { pub unsafe fn dispatch_first_task(&'static self) -> ! where System: Port, + // FIXME: Work-around for + System::TaskReadyQueue: std::borrow::BorrowMut<[StaticListHead>]>, { log::trace!("dispatch_first_task"); assert!(self.is_cpu_lock_active()); @@ -197,6 +199,8 @@ impl State { pub unsafe fn yield_cpu(&self) where System: Port, + // FIXME: Work-around for + System::TaskReadyQueue: std::borrow::BorrowMut<[StaticListHead>]>, { log::trace!("yield_cpu"); assert!(!self.is_cpu_lock_active()); @@ -208,6 +212,8 @@ impl State { pub unsafe fn exit_and_dispatch(&self) -> ! where System: Port, + // Work-around + System::TaskReadyQueue: std::borrow::BorrowMut<[StaticListHead>]>, { log::trace!("exit_and_dispatch"); assert!(self.is_cpu_lock_active());