diff --git a/framework/aster-frame/src/arch/mod.rs b/framework/aster-frame/src/arch/mod.rs index bd52ba441..123b08be3 100644 --- a/framework/aster-frame/src/arch/mod.rs +++ b/framework/aster-frame/src/arch/mod.rs @@ -1,5 +1,9 @@ // SPDX-License-Identifier: MPL-2.0 +//! Platform-specific code. +//! +//! Each architecture that Asterinas supports may contain a submodule here. + #[cfg(target_arch = "x86_64")] pub mod x86; diff --git a/framework/aster-frame/src/arch/x86/console.rs b/framework/aster-frame/src/arch/x86/console.rs index 5f2360a28..034b39a7b 100644 --- a/framework/aster-frame/src/arch/x86/console.rs +++ b/framework/aster-frame/src/arch/x86/console.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 +//! The console I/O. + #![allow(dead_code)] #![allow(unused_variables)] @@ -13,13 +15,16 @@ use trapframe::TrapFrame; use super::{device::serial::SerialPort, kernel::IO_APIC}; use crate::{sync::SpinLock, trap::IrqLine}; +/// Prints the formatted arguments to the standard output. #[inline] pub fn print(args: fmt::Arguments) { Stdout.write_fmt(args).unwrap(); } +/// The callback function for console input. pub type InputCallback = dyn Fn(u8) + Send + Sync + 'static; +/// Registers a callback function to be called when there is console input. pub fn register_console_input_callback(f: &'static InputCallback) { SERIAL_INPUT_CALLBACKS.lock_irq_disabled().push(Arc::new(f)); } diff --git a/framework/aster-frame/src/arch/x86/cpu.rs b/framework/aster-frame/src/arch/x86/cpu.rs index 78200cdca..efffc099f 100644 --- a/framework/aster-frame/src/arch/x86/cpu.rs +++ b/framework/aster-frame/src/arch/x86/cpu.rs @@ -38,12 +38,14 @@ pub fn this_cpu() -> u32 { 0 } +/// A set of CPUs. #[derive(Default)] pub struct CpuSet { bitset: BitVec, } impl CpuSet { + /// Creates a new `CpuSet` with all CPUs included. pub fn new_full() -> Self { let num_cpus = num_cpus(); let mut bitset = BitVec::with_capacity(num_cpus as usize); @@ -51,6 +53,7 @@ impl CpuSet { Self { bitset } } + /// Creates a new `CpuSet` with no CPUs included. pub fn new_empty() -> Self { let num_cpus = num_cpus(); let mut bitset = BitVec::with_capacity(num_cpus as usize); @@ -58,38 +61,46 @@ impl CpuSet { Self { bitset } } + /// Adds a CPU with identifier `cpu_id` to the `CpuSet`. pub fn add(&mut self, cpu_id: u32) { self.bitset.set(cpu_id as usize, true); } + /// Adds multiple CPUs from a vector to the `CpuSet`. pub fn add_from_vec(&mut self, cpu_ids: Vec) { for cpu_id in cpu_ids { self.add(cpu_id) } } + /// Adds all available CPUs to the `CpuSet`. pub fn add_all(&mut self) { self.bitset.fill(true); } + /// Removes a CPU with identifier `cpu_id` from the `CpuSet`. pub fn remove(&mut self, cpu_id: u32) { self.bitset.set(cpu_id as usize, false); } + /// Removes multiple CPUs from a vector from the `CpuSet`. pub fn remove_from_vec(&mut self, cpu_ids: Vec) { for cpu_id in cpu_ids { self.remove(cpu_id); } } + /// Clears the `CpuSet`, removing all CPUs. pub fn clear(&mut self) { self.bitset.fill(false); } + /// Checks if the `CpuSet` contains a specific CPU. pub fn contains(&self, cpu_id: u32) -> bool { self.bitset.get(cpu_id as usize).as_deref() == Some(&true) } + /// Returns an iterator over the set CPUs. pub fn iter(&self) -> IterOnes<'_, usize, Lsb0> { self.bitset.iter_ones() } @@ -104,11 +115,15 @@ pub struct UserContext { cpu_exception_info: CpuExceptionInfo, } +/// CPU exception information. #[derive(Clone, Default, Copy, Debug)] #[repr(C)] pub struct CpuExceptionInfo { + /// The ID of the exception. pub id: usize, + /// The error code associated with the exception. pub error_code: usize, + /// The virtual address where a page fault occurred. pub page_fault_addr: usize, } @@ -212,6 +227,7 @@ impl TdxTrapFrame for GeneralRegs { } } +/// User Preemption. pub struct UserPreemption { count: u32, } @@ -219,10 +235,12 @@ pub struct UserPreemption { impl UserPreemption { const PREEMPTION_INTERVAL: u32 = 100; + /// Creates a new instance of `UserPreemption`. pub const fn new() -> Self { UserPreemption { count: 0 } } + /// Checks if preemption might occur and takes necessary actions. pub fn might_preempt(&mut self) { self.count = (self.count + 1) % Self::PREEMPTION_INTERVAL; @@ -235,22 +253,27 @@ impl UserPreemption { } impl UserContext { + /// Returns a reference to the general registers. pub fn general_regs(&self) -> &GeneralRegs { &self.user_context.general } + /// Returns a mutable reference to the general registers pub fn general_regs_mut(&mut self) -> &mut GeneralRegs { &mut self.user_context.general } + /// Returns the trap information. pub fn trap_information(&self) -> &CpuExceptionInfo { &self.cpu_exception_info } + /// Returns a reference to the floating point registers pub fn fp_regs(&self) -> &FpRegs { &self.fp_regs } + /// Returns a mutable reference to the floating point registers pub fn fp_regs_mut(&mut self) -> &mut FpRegs { &mut self.fp_regs } @@ -358,17 +381,26 @@ impl UserContextApiInternal for UserContext { /// So here we also define FaultOrTrap and Interrupt #[derive(PartialEq, Eq, Debug)] pub enum CpuExceptionType { + /// CPU faults. Faults can be corrected, and the program may continue as if nothing happened. Fault, + /// CPU traps. Traps are reported immediately after the execution of the trapping instruction Trap, + /// Faults or traps FaultOrTrap, + /// CPU interrupts Interrupt, + /// Some severe unrecoverable error Abort, + /// Reserved for future use Reserved, } +/// CPU exception. #[derive(Debug, Eq, PartialEq)] pub struct CpuException { + /// The ID of the CPU exception. pub number: u16, + /// The type of the CPU exception. pub typ: CpuExceptionType, } @@ -390,6 +422,7 @@ macro_rules! define_cpu_exception { $($name,)* ]; $( + #[doc = concat!("The ", stringify!($name), " exception")] pub const $name : CpuException = CpuException{ number: $exception_num, typ: CpuExceptionType::$exception_type, @@ -462,10 +495,12 @@ bitflags! { } impl CpuException { + /// Checks if the given `trap_num` is a valid CPU exception. pub fn is_cpu_exception(trap_num: u16) -> bool { trap_num < EXCEPTION_LIST.len() as u16 } + /// Maps a `trap_num` to its corresponding CPU exception. pub fn to_cpu_exception(trap_num: u16) -> Option<&'static CpuException> { EXCEPTION_LIST.get(trap_num as usize) } @@ -501,11 +536,13 @@ macro_rules! cpu_context_impl_getter_setter { ( $( [ $field: ident, $setter_name: ident] ),*) => { impl UserContext { $( + #[doc = concat!("Gets the value of ", stringify!($field))] #[inline(always)] pub fn $field(&self) -> usize { self.user_context.general.$field } + #[doc = concat!("Sets the value of ", stringify!(field))] #[inline(always)] pub fn $setter_name(&mut self, $field: usize) { self.user_context.general.$field = $field; diff --git a/framework/aster-frame/src/arch/x86/device/mod.rs b/framework/aster-frame/src/arch/x86/device/mod.rs index d588d790a..5b900f240 100644 --- a/framework/aster-frame/src/arch/x86/device/mod.rs +++ b/framework/aster-frame/src/arch/x86/device/mod.rs @@ -3,6 +3,9 @@ //! Device-related APIs. //! This module mainly contains the APIs that should exposed to the device driver like PCI, RTC +// FIXME: remove this lint when the documentation of this module is extensively added. +#![allow(missing_docs)] + pub mod cmos; pub mod io_port; pub mod serial; diff --git a/framework/aster-frame/src/arch/x86/iommu/mod.rs b/framework/aster-frame/src/arch/x86/iommu/mod.rs index 1e7fa3dae..cd771084e 100644 --- a/framework/aster-frame/src/arch/x86/iommu/mod.rs +++ b/framework/aster-frame/src/arch/x86/iommu/mod.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 +//! The IOMMU support. + mod context_table; mod fault; mod remapping; @@ -17,9 +19,12 @@ use crate::{ sync::Mutex, }; +/// An enumeration representing possible errors related to IOMMU. #[derive(Debug)] pub enum IommuError { + /// No IOMMU is available. NoIommu, + /// Error encountered during modification of the page table. ModificationError(PageTableError), } diff --git a/framework/aster-frame/src/arch/x86/irq.rs b/framework/aster-frame/src/arch/x86/irq.rs index 1d9fd05a7..4448d9a33 100644 --- a/framework/aster-frame/src/arch/x86/irq.rs +++ b/framework/aster-frame/src/arch/x86/irq.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 +//! Interrupts. + #![allow(dead_code)] use alloc::{boxed::Box, fmt::Debug, sync::Arc, vec::Vec}; diff --git a/framework/aster-frame/src/arch/x86/mod.rs b/framework/aster-frame/src/arch/x86/mod.rs index bac0e3e42..f17998ce2 100644 --- a/framework/aster-frame/src/arch/x86/mod.rs +++ b/framework/aster-frame/src/arch/x86/mod.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 +//! Platform-specific code for the x86 platform. + pub mod boot; pub mod console; pub(crate) mod cpu; diff --git a/framework/aster-frame/src/arch/x86/qemu.rs b/framework/aster-frame/src/arch/x86/qemu.rs index 5cfceb758..28231f2e9 100644 --- a/framework/aster-frame/src/arch/x86/qemu.rs +++ b/framework/aster-frame/src/arch/x86/qemu.rs @@ -10,7 +10,9 @@ #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u32)] pub enum QemuExitCode { + /// The code that indicates a successful exit. Success = 0x10, + /// The code that indicates a failed exit. Failed = 0x20, } diff --git a/framework/aster-frame/src/arch/x86/task/mod.rs b/framework/aster-frame/src/arch/x86/task/mod.rs index ba67ff917..d36604cfc 100644 --- a/framework/aster-frame/src/arch/x86/task/mod.rs +++ b/framework/aster-frame/src/arch/x86/task/mod.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 +//! The architecture support of context switch. + use crate::task::TaskContextApi; core::arch::global_asm!(include_str!("switch.S")); @@ -23,12 +25,19 @@ impl TaskContext { #[derive(Debug, Default, Clone, Copy)] #[repr(C)] pub struct CalleeRegs { + /// RSP pub rsp: u64, + /// RBX pub rbx: u64, + /// RBP pub rbp: u64, + /// R12 pub r12: u64, + /// R13 pub r13: u64, + /// R14 pub r14: u64, + /// R15 pub r15: u64, } diff --git a/framework/aster-frame/src/arch/x86/timer/mod.rs b/framework/aster-frame/src/arch/x86/timer/mod.rs index 592a14570..f44e71bf2 100644 --- a/framework/aster-frame/src/arch/x86/timer/mod.rs +++ b/framework/aster-frame/src/arch/x86/timer/mod.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 +//! The timer support. + mod apic; mod hpet; mod jiffies; diff --git a/framework/aster-frame/src/boot/kcmdline.rs b/framework/aster-frame/src/boot/kcmdline.rs index 3a172ccda..9cd794f54 100644 --- a/framework/aster-frame/src/boot/kcmdline.rs +++ b/framework/aster-frame/src/boot/kcmdline.rs @@ -27,9 +27,12 @@ struct InitprocArgs { envp: Vec, } +/// Kernel module arguments #[derive(PartialEq, Debug, Clone)] pub enum ModuleArg { + /// A string argument Arg(CString), + /// A key-value argument KeyVal(CString, CString), } diff --git a/framework/aster-frame/src/boot/memory_region.rs b/framework/aster-frame/src/boot/memory_region.rs index e36a7844d..0694b78d2 100644 --- a/framework/aster-frame/src/boot/memory_region.rs +++ b/framework/aster-frame/src/boot/memory_region.rs @@ -71,6 +71,7 @@ impl MemoryRegion { self.len } + /// Checks whether the region is empty pub fn is_empty(&self) -> bool { self.len == 0 } diff --git a/framework/aster-frame/src/boot/mod.rs b/framework/aster-frame/src/boot/mod.rs index 45f4d87ad..2e81acf1d 100644 --- a/framework/aster-frame/src/boot/mod.rs +++ b/framework/aster-frame/src/boot/mod.rs @@ -36,8 +36,11 @@ pub enum BootloaderAcpiArg { /// The framebuffer arguments. #[derive(Copy, Clone, Debug)] pub struct BootloaderFramebufferArg { + /// The address of the buffer. pub address: usize, + /// The width of the buffer. pub width: usize, + /// The height of the buffer. pub height: usize, /// Bits per pixel of the buffer. pub bpp: usize, diff --git a/framework/aster-frame/src/bus/mod.rs b/framework/aster-frame/src/bus/mod.rs index 3654081ec..ebc8dfc43 100644 --- a/framework/aster-frame/src/bus/mod.rs +++ b/framework/aster-frame/src/bus/mod.rs @@ -1,14 +1,23 @@ // SPDX-License-Identifier: MPL-2.0 +//! Bus operations + +// FIXME: remove this lint when the docs of the whole bus module are added. +#![allow(missing_docs)] + pub mod mmio; pub mod pci; +/// An error that occurs during bus probing. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum BusProbeError { + /// The device does not match the expected criteria. DeviceNotMatch, + /// An error in accessing the configuration space of the device. ConfigurationSpaceError, } +/// Initializes the bus pub fn init() { pci::init(); mmio::init(); diff --git a/framework/aster-frame/src/console.rs b/framework/aster-frame/src/console.rs index 265dd94c3..4c34fd1bb 100644 --- a/framework/aster-frame/src/console.rs +++ b/framework/aster-frame/src/console.rs @@ -1,11 +1,15 @@ // SPDX-License-Identifier: MPL-2.0 +//! Console output. + use core::fmt::Arguments; +/// Prints formatted arguments to the console. pub fn print(args: Arguments) { crate::arch::console::print(args); } +/// Prints to the console. #[macro_export] macro_rules! early_print { ($fmt: literal $(, $($arg: tt)+)?) => { @@ -13,6 +17,7 @@ macro_rules! early_print { } } +/// Prints to the console, with a newline. #[macro_export] macro_rules! early_println { () => { $crate::early_print!("\n") }; diff --git a/framework/aster-frame/src/error.rs b/framework/aster-frame/src/error.rs index 2cb0725bf..01d10a0e6 100644 --- a/framework/aster-frame/src/error.rs +++ b/framework/aster-frame/src/error.rs @@ -5,13 +5,21 @@ use crate::mm::page_table::PageTableError; /// The error type which is returned from the APIs of this crate. #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum Error { + /// Invalid arguments provided. InvalidArgs, + /// Insufficient memory available. NoMemory, + /// Page fault occurred. PageFault, + /// Access to a resource is denied. AccessDenied, + /// Input/output error. IoError, + /// Insufficient system resources. NotEnoughResources, + /// Arithmetic Overflow occurred. Overflow, + /// Memory mapping already exists for the given virtual address. MapAlreadyMappedVaddr, } diff --git a/framework/aster-frame/src/io_mem.rs b/framework/aster-frame/src/io_mem.rs index bf4b4bbf5..249204fec 100644 --- a/framework/aster-frame/src/io_mem.rs +++ b/framework/aster-frame/src/io_mem.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 +//! I/O memory. + use core::{mem::size_of, ops::Range}; use pod::Pod; @@ -9,6 +11,7 @@ use crate::{ Error, Result, }; +/// I/O memory. #[derive(Debug, Clone)] pub struct IoMem { virtual_address: Vaddr, @@ -59,6 +62,8 @@ impl HasPaddr for IoMem { } impl IoMem { + /// Creates a new `IoMem`. + /// /// # Safety /// /// User must ensure the given physical range is in the I/O memory region. @@ -69,14 +74,21 @@ impl IoMem { } } + /// Returns the physical address of the I/O memory. pub fn paddr(&self) -> Paddr { self.virtual_address - LINEAR_MAPPING_BASE_VADDR } + /// Returns the length of the I/O memory region. pub fn length(&self) -> usize { self.limit } + /// Resizes the I/O memory region to the new `range`. + /// + /// # Errors + /// + /// Returns an error if the new `range` is not within the current range. pub fn resize(&mut self, range: Range) -> Result<()> { let start_vaddr = paddr_to_vaddr(range.start); let virtual_end = self diff --git a/framework/aster-frame/src/lib.rs b/framework/aster-frame/src/lib.rs index c8a34e0bc..1f2c7bcfc 100644 --- a/framework/aster-frame/src/lib.rs +++ b/framework/aster-frame/src/lib.rs @@ -20,6 +20,7 @@ // const generic implementation. We are using this feature in a conservative manner. #![allow(incomplete_features)] #![no_std] +#![warn(missing_docs)] extern crate alloc; #[cfg(ktest)] diff --git a/framework/aster-frame/src/logger.rs b/framework/aster-frame/src/logger.rs index 12510d9a1..dc6eb9110 100644 --- a/framework/aster-frame/src/logger.rs +++ b/framework/aster-frame/src/logger.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 +//! Logging support. + use log::{Level, Metadata, Record}; use crate::early_println; diff --git a/framework/aster-frame/src/mm/dma/dma_stream.rs b/framework/aster-frame/src/mm/dma/dma_stream.rs index 96f337900..6063bfcb8 100644 --- a/framework/aster-frame/src/mm/dma/dma_stream.rs +++ b/framework/aster-frame/src/mm/dma/dma_stream.rs @@ -40,13 +40,16 @@ struct DmaStreamInner { /// prevents users from reading and writing to `DmaStream` unexpectedly. #[derive(Debug, PartialEq, Clone, Copy)] pub enum DmaDirection { + /// Data flows to the device ToDevice, + /// Data flows form the device FromDevice, + /// Data flows both from and to the device Bidirectional, } impl DmaStream { - /// Establish DMA stream mapping for a given `Segment`. + /// Establishes DMA stream mapping for a given [`Segment`]. /// /// The method fails if the segment already belongs to a DMA mapping. pub fn map( @@ -98,7 +101,7 @@ impl DmaStream { }) } - /// Get the underlying VM segment. + /// Get the underlying [`VmSegment`]. /// /// Usually, the CPU side should not access the memory /// after the DMA mapping is established because @@ -108,10 +111,12 @@ impl DmaStream { &self.inner.vm_segment } + /// Returns the number of frames pub fn nframes(&self) -> usize { self.inner.vm_segment.nframes() } + /// Returns the number of bytes pub fn nbytes(&self) -> usize { self.inner.vm_segment.nbytes() } @@ -120,10 +125,13 @@ impl DmaStream { /// /// This method should be called under one of the two conditions: /// 1. The data of the stream DMA mapping has been updated by the device side. - /// The CPU side needs to call the `sync` method before reading data (e.g., using `read_bytes`). + /// The CPU side needs to call the `sync` method before reading data (e.g., using [`read_bytes`]). /// 2. The data of the stream DMA mapping has been updated by the CPU side - /// (e.g., using `write_bytes`). + /// (e.g., using [`write_bytes`]). /// Before the CPU side notifies the device side to read, it must call the `sync` method first. + /// + /// [`read_bytes`]: Self::read_bytes + /// [`write_bytes`]: Self::write_bytes pub fn sync(&self, byte_range: Range) -> Result<(), Error> { if byte_range.end > self.nbytes() { return Err(Error::InvalidArgs); diff --git a/framework/aster-frame/src/mm/dma/mod.rs b/framework/aster-frame/src/mm/dma/mod.rs index 73ebc6cfc..f6c8088e7 100644 --- a/framework/aster-frame/src/mm/dma/mod.rs +++ b/framework/aster-frame/src/mm/dma/mod.rs @@ -31,6 +31,7 @@ pub enum DmaError { AlreadyMapped, } +/// Has mapped address in the device address space. pub trait HasDaddr { /// Get the base address of the mapping in the /// device address space. diff --git a/framework/aster-frame/src/mm/mod.rs b/framework/aster-frame/src/mm/mod.rs index d09d26530..82836da36 100644 --- a/framework/aster-frame/src/mm/mod.rs +++ b/framework/aster-frame/src/mm/mod.rs @@ -107,13 +107,16 @@ pub(crate) const KERNEL_VADDR_RANGE: Range = 0xffff_8000_0000_0000..0xfff /// Get physical address trait pub trait HasPaddr { + /// Returns the physical address. fn paddr(&self) -> Paddr; } +/// Checks if the given address is page-aligned. pub const fn is_page_aligned(p: usize) -> bool { (p & (PAGE_SIZE - 1)) == 0 } +/// Memory regions used for frame buffer. pub static FRAMEBUFFER_REGIONS: Once> = Once::new(); pub(crate) fn misc_init() { diff --git a/framework/aster-frame/src/mm/page_prop.rs b/framework/aster-frame/src/mm/page_prop.rs index 996925be5..948ada120 100644 --- a/framework/aster-frame/src/mm/page_prop.rs +++ b/framework/aster-frame/src/mm/page_prop.rs @@ -9,7 +9,9 @@ use bitflags::bitflags; /// The property of a mapped virtual memory page. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct PageProperty { + /// The flags associated with the page, pub flags: PageFlags, + /// The cache policy for the page. pub cache: CachePolicy, pub(crate) priv_flags: PrivilegedPageFlags, } diff --git a/framework/aster-frame/src/mm/space.rs b/framework/aster-frame/src/mm/space.rs index 090b72a84..5804591a6 100644 --- a/framework/aster-frame/src/mm/space.rs +++ b/framework/aster-frame/src/mm/space.rs @@ -127,7 +127,7 @@ impl VmSpace { /// Query about the mapping information about a byte in virtual memory. /// This is more handy than [`query_range`], but less efficient if you want /// to query in a batch. - /// + /// /// [`query_range`]: VmSpace::query_range pub fn query(&self, vaddr: Vaddr) -> Result> { if !(0..MAX_USERSPACE_VADDR).contains(&vaddr) { diff --git a/framework/aster-frame/src/panicking.rs b/framework/aster-frame/src/panicking.rs index ed2a6a59a..22ab8189f 100644 --- a/framework/aster-frame/src/panicking.rs +++ b/framework/aster-frame/src/panicking.rs @@ -46,7 +46,7 @@ pub fn panic_handler(info: &core::panic::PanicInfo) -> ! { abort(); } -// Aborts the QEMU +/// Aborts the QEMU pub fn abort() -> ! { exit_qemu(QemuExitCode::Failed); } diff --git a/framework/aster-frame/src/prelude.rs b/framework/aster-frame/src/prelude.rs index 3f2bab9db..9a808c64d 100644 --- a/framework/aster-frame/src/prelude.rs +++ b/framework/aster-frame/src/prelude.rs @@ -2,6 +2,7 @@ //! The prelude. +/// A specialized [`core::result::Result``] type for this crate. pub type Result = core::result::Result; pub(crate) use alloc::{boxed::Box, sync::Arc, vec::Vec}; diff --git a/framework/aster-frame/src/sync/mod.rs b/framework/aster-frame/src/sync/mod.rs index a76f10b69..b72a1aa44 100644 --- a/framework/aster-frame/src/sync/mod.rs +++ b/framework/aster-frame/src/sync/mod.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 +//! Useful synchronization primitives. + mod atomic_bits; mod mutex; // TODO: refactor this rcu implementation diff --git a/framework/aster-frame/src/sync/mutex.rs b/framework/aster-frame/src/sync/mutex.rs index 7770ed8fa..64a5e5ba4 100644 --- a/framework/aster-frame/src/sync/mutex.rs +++ b/framework/aster-frame/src/sync/mutex.rs @@ -92,7 +92,10 @@ pub struct MutexGuard_>> { mutex: R, } +/// A guard that provides exclusive access to the data protected by a [`Mutex`]. pub type MutexGuard<'a, T> = MutexGuard_>; + +/// An guard that provides exclusive access to the data protected by a [`Arc`]. pub type ArcMutexGuard = MutexGuard_>>; impl>> Deref for MutexGuard_ { diff --git a/framework/aster-frame/src/sync/rwlock.rs b/framework/aster-frame/src/sync/rwlock.rs index 7576adf31..b51247ae6 100644 --- a/framework/aster-frame/src/sync/rwlock.rs +++ b/framework/aster-frame/src/sync/rwlock.rs @@ -544,7 +544,10 @@ pub struct RwLockReadGuard_> + Clone> { inner: R, } +/// A guard that provides shared read access to the data protected by a [`RwLock`]. pub type RwLockReadGuard<'a, T> = RwLockReadGuard_>; + +/// A guard that provides shared read access to the data protected by a [`Arc`]. pub type ArcRwLockReadGuard = RwLockReadGuard_>>; impl> + Clone> Deref for RwLockReadGuard_ { @@ -575,7 +578,9 @@ pub struct RwLockWriteGuard_> + Clone> { inner: R, } +/// A guard that provides exclusive write access to the data protected by a [`RwLock`]. pub type RwLockWriteGuard<'a, T> = RwLockWriteGuard_>; +/// A guard that provides exclusive write access to the data protected by a [`Arc`]. pub type ArcRwLockWriteGuard = RwLockWriteGuard_>>; impl> + Clone> Deref for RwLockWriteGuard_ { @@ -644,7 +649,9 @@ pub struct RwLockUpgradeableGuard_> + Clo inner: R, } +/// A upgradable guard that provides read access to the data protected by a [`RwLock`]. pub type RwLockUpgradeableGuard<'a, T> = RwLockUpgradeableGuard_>; +/// A upgradable guard that provides read access to the data protected by a [`Arc`]. pub type ArcRwLockUpgradeableGuard = RwLockUpgradeableGuard_>>; impl> + Clone> RwLockUpgradeableGuard_ { diff --git a/framework/aster-frame/src/sync/rwmutex.rs b/framework/aster-frame/src/sync/rwmutex.rs index 4732fca47..8365aaa65 100644 --- a/framework/aster-frame/src/sync/rwmutex.rs +++ b/framework/aster-frame/src/sync/rwmutex.rs @@ -225,7 +225,9 @@ pub struct RwMutexReadGuard_>> { inner: R, } +/// A guard that provides shared read access to the data protected by a [`RwMutex`]. pub type RwMutexReadGuard<'a, T> = RwMutexReadGuard_>; +/// A guard that provides shared read access to the data protected by a [`Arc`]. pub type ArcRwMutexReadGuard = RwMutexReadGuard_>>; impl>> Deref for RwMutexReadGuard_ { @@ -250,7 +252,9 @@ pub struct RwMutexWriteGuard_>> { inner: R, } +/// A guard that provides exclusive write access to the data protected by a [`RwMutex`]. pub type RwMutexWriteGuard<'a, T> = RwMutexWriteGuard_>; +/// A guard that provides exclusive write access to the data protected by a [`Arc`]. pub type ArcRwMutexWriteGuard = RwMutexWriteGuard_>>; impl>> Deref for RwMutexWriteGuard_ { @@ -315,7 +319,9 @@ pub struct RwMutexUpgradeableGuard_>> { inner: R, } +/// A upgradable guard that provides read access to the data protected by a [`RwMutex`]. pub type RwMutexUpgradeableGuard<'a, T> = RwMutexUpgradeableGuard_>; +/// A upgradable guard that provides read access to the data protected by a [`Arc`]. pub type ArcRwMutexUpgradeableGuard = RwMutexUpgradeableGuard_>>; impl> + Clone> RwMutexUpgradeableGuard_ { diff --git a/framework/aster-frame/src/sync/spin.rs b/framework/aster-frame/src/sync/spin.rs index 5ce423c98..26151b8c6 100644 --- a/framework/aster-frame/src/sync/spin.rs +++ b/framework/aster-frame/src/sync/spin.rs @@ -135,7 +135,9 @@ enum InnerGuard { PreemptGuard(DisablePreemptGuard), } +/// A guard that provides exclusive access to the data protected by a [`SpinLock`]. pub type SpinLockGuard<'a, T> = SpinLockGuard_>; +/// A guard that provides exclusive access to the data protected by a [`Arc`]. pub type ArcSpinLockGuard = SpinLockGuard_>>; /// The guard of a spin lock that disables the local IRQs. diff --git a/framework/aster-frame/src/task/priority.rs b/framework/aster-frame/src/task/priority.rs index fbd87c7c5..ee28a3ae5 100644 --- a/framework/aster-frame/src/task/priority.rs +++ b/framework/aster-frame/src/task/priority.rs @@ -3,6 +3,7 @@ pub const REAL_TIME_TASK_PRIORITY: u16 = 100; /// The priority of a task. +/// /// Similar to Linux, a larger value represents a lower priority, /// with a range of 0 to 139. Priorities ranging from 0 to 99 are considered real-time, /// while those ranging from 100 to 139 are considered normal. @@ -10,39 +11,52 @@ pub const REAL_TIME_TASK_PRIORITY: u16 = 100; pub struct Priority(u16); impl Priority { + /// Creates a new `Priority` with the specified value. + /// + /// # Panics + /// + /// Panics if the `val` is greater than 139. pub const fn new(val: u16) -> Self { assert!(val <= 139); Self(val) } + /// Returns a `Priority` representing the lowest priority (139). pub const fn lowest() -> Self { Self::new(139) } + /// Returns a `Priority` representing a low priority. pub const fn low() -> Self { Self::new(110) } + /// Returns a `Priority` representing a normal priority. pub const fn normal() -> Self { Self::new(100) } + /// Returns a `Priority` representing a high priority. pub const fn high() -> Self { Self::new(10) } + /// Returns a `Priority` representing the highest priority (0). pub const fn highest() -> Self { Self::new(0) } + /// Sets the value of the `Priority`. pub const fn set(&mut self, val: u16) { self.0 = val; } + /// Returns the value of the `Priority`. pub const fn get(self) -> u16 { self.0 } + /// Checks if the `Priority` is considered a real-time priority. pub const fn is_real_time(&self) -> bool { self.0 < REAL_TIME_TASK_PRIORITY } diff --git a/framework/aster-frame/src/task/processor.rs b/framework/aster-frame/src/task/processor.rs index 268bae2b1..871823537 100644 --- a/framework/aster-frame/src/task/processor.rs +++ b/framework/aster-frame/src/task/processor.rs @@ -55,6 +55,7 @@ pub fn take_current_task() -> Option> { }) } +/// Retrieves the current task running on the processor. pub fn current_task() -> Option> { CpuLocal::borrow_with(&PROCESSOR, |processor| processor.borrow().current()) } @@ -72,10 +73,10 @@ pub fn schedule() { } } -// TODO: This interface of this method is error prone. -// The method takes an argument for the current task to optimize its efficiency, -// but the argument provided by the caller may not be the current task, really. -// Thus, this method should be removed or reworked in the future. +/// TODO: This interface of this method is error prone. +/// The method takes an argument for the current task to optimize its efficiency, +/// but the argument provided by the caller may not be the current task, really. +/// Thus, this method should be removed or reworked in the future. pub fn preempt(task: &Arc) { // TODO: Refactor `preempt` and `schedule` // after the Atomic mode and `might_break` is enabled. @@ -219,6 +220,7 @@ impl Drop for DisablePreemptGuard { } } +/// Disables preemption. #[must_use] pub fn disable_preempt() -> DisablePreemptGuard { DisablePreemptGuard::new() diff --git a/framework/aster-frame/src/task/scheduler.rs b/framework/aster-frame/src/task/scheduler.rs index 15fa04300..b34f874d6 100644 --- a/framework/aster-frame/src/task/scheduler.rs +++ b/framework/aster-frame/src/task/scheduler.rs @@ -18,8 +18,10 @@ lazy_static! { /// An implementation of scheduler can attach scheduler-related information /// with the `TypeMap` returned from `task.data()`. pub trait Scheduler: Sync + Send { + /// Enqueues a task to the scheduler. fn enqueue(&self, task: Arc); + /// Dequeues a task from the scheduler. fn dequeue(&self) -> Option>; /// Tells whether the given task should be preempted by other tasks in the queue. @@ -61,6 +63,7 @@ pub fn fetch_task() -> Option> { GLOBAL_SCHEDULER.lock_irq_disabled().dequeue() } +/// Adds a task to the global scheduler. pub fn add_task(task: Arc) { GLOBAL_SCHEDULER.lock_irq_disabled().enqueue(task); } diff --git a/framework/aster-frame/src/task/task.rs b/framework/aster-frame/src/task/task.rs index e5ffafb94..8934be674 100644 --- a/framework/aster-frame/src/task/task.rs +++ b/framework/aster-frame/src/task/task.rs @@ -1,5 +1,8 @@ // SPDX-License-Identifier: MPL-2.0 +// FIXME: the `intrusive_adapter` macro will generate methods without docs. +// So we temporary allow missing_docs for this module. +#![allow(missing_docs)] #![allow(dead_code)] use core::cell::UnsafeCell; @@ -22,6 +25,7 @@ use crate::{ pub const KERNEL_STACK_SIZE: usize = PAGE_SIZE * 64; +/// Trait for manipulating the task context. pub trait TaskContextApi { /// Set instruction pointer fn set_instruction_pointer(&mut self, ip: usize); @@ -195,6 +199,7 @@ impl Task { unreachable!() } + /// Checks if the task has a real-time priority. pub fn is_real_time(&self) -> bool { self.priority.is_real_time() } @@ -238,6 +243,7 @@ impl TaskOptions { } } + /// Sets the function that represents the entry point of the task. pub fn func(mut self, func: F) -> Self where F: Fn() + Send + Sync + 'static, @@ -246,6 +252,7 @@ impl TaskOptions { self } + /// Sets the data associated with the task. pub fn data(mut self, data: T) -> Self where T: Any + Send + Sync, @@ -266,6 +273,10 @@ impl TaskOptions { self } + /// Sets the CPU affinity mask for the task. + /// + /// The `cpu_affinity` parameter is an instance of the [`CpuSet`] struct + /// that represents the desired set of CPUs to run the task on. pub fn cpu_affinity(mut self, cpu_affinity: CpuSet) -> Self { self.cpu_affinity = cpu_affinity; self diff --git a/framework/aster-frame/src/trap/irq.rs b/framework/aster-frame/src/trap/irq.rs index e13b38b32..1b0430fa0 100644 --- a/framework/aster-frame/src/trap/irq.rs +++ b/framework/aster-frame/src/trap/irq.rs @@ -13,12 +13,16 @@ use crate::{ Error, }; +/// Type alias for the irq callback function. pub type IrqCallbackFunction = dyn Fn(&TrapFrame) + Sync + Send + 'static; -/// An Interrupt ReQuest(IRQ) line. User can use `alloc` or `alloc_specific` to get specific IRQ line. +/// An Interrupt ReQuest(IRQ) line. User can use [`alloc`] or [`alloc_specific`] to get specific IRQ line. /// /// The IRQ number is guaranteed to be external IRQ number and user can register callback functions to this IRQ resource. /// When this resource is dropped, all the callback in this will be unregistered automatically. +/// +/// [`alloc`]: Self::alloc +/// [`alloc_specific`]: Self::alloc_specific #[derive(Debug)] #[must_use] pub struct IrqLine { @@ -29,6 +33,7 @@ pub struct IrqLine { } impl IrqLine { + /// Allocates a specific IRQ line. pub fn alloc_specific(irq: u8) -> Result { IRQ_ALLOCATOR .get() @@ -39,6 +44,7 @@ impl IrqLine { .ok_or(Error::NotEnoughResources) } + /// Allocates an available IRQ line. pub fn alloc() -> Result { let Some(irq_num) = IRQ_ALLOCATOR.get().unwrap().lock().alloc() else { return Err(Error::NotEnoughResources); @@ -71,6 +77,7 @@ impl IrqLine { self.callbacks.push(self.irq.on_active(callback)) } + /// Checks if there are no registered callbacks. pub fn is_empty(&self) -> bool { self.callbacks.is_empty() } diff --git a/framework/aster-frame/src/trap/mod.rs b/framework/aster-frame/src/trap/mod.rs index f98c2982e..40b6780db 100644 --- a/framework/aster-frame/src/trap/mod.rs +++ b/framework/aster-frame/src/trap/mod.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 +//! Handle trap across kernel and user space. + mod handler; mod irq; pub mod softirq; diff --git a/framework/aster-frame/src/user.rs b/framework/aster-frame/src/user.rs index f831c3760..e3219aa39 100644 --- a/framework/aster-frame/src/user.rs +++ b/framework/aster-frame/src/user.rs @@ -112,6 +112,7 @@ pub struct UserMode<'a> { impl<'a> !Send for UserMode<'a> {} impl<'a> UserMode<'a> { + /// Creates a new `UserMode`. pub fn new(user_space: &'a Arc) -> Self { Self { current: Task::current(), diff --git a/framework/libs/align_ext/Cargo.toml b/framework/libs/align_ext/Cargo.toml index 048a5fcc9..637fe7598 100644 --- a/framework/libs/align_ext/Cargo.toml +++ b/framework/libs/align_ext/Cargo.toml @@ -5,4 +5,4 @@ edition = "2021" description = " An extension trait for Rust integer types to make integers aligned to a power of two" license = "MPL-2.0" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html \ No newline at end of file