Add missing docs in aster-frame

This commit is contained in:
Jianfeng Jiang
2024-05-23 08:55:39 +00:00
committed by Tate, Hongliang Tian
parent a93f922a25
commit 6e59617fc7
39 changed files with 202 additions and 12 deletions

View File

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

View File

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

View File

@ -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<u32>) {
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<u32>) {
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;

View File

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

View File

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

View File

@ -1,5 +1,7 @@
// SPDX-License-Identifier: MPL-2.0
//! Interrupts.
#![allow(dead_code)]
use alloc::{boxed::Box, fmt::Debug, sync::Arc, vec::Vec};

View File

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

View File

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

View File

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

View File

@ -1,5 +1,7 @@
// SPDX-License-Identifier: MPL-2.0
//! The timer support.
mod apic;
mod hpet;
mod jiffies;

View File

@ -27,9 +27,12 @@ struct InitprocArgs {
envp: Vec<CString>,
}
/// Kernel module arguments
#[derive(PartialEq, Debug, Clone)]
pub enum ModuleArg {
/// A string argument
Arg(CString),
/// A key-value argument
KeyVal(CString, CString),
}

View File

@ -71,6 +71,7 @@ impl MemoryRegion {
self.len
}
/// Checks whether the region is empty
pub fn is_empty(&self) -> bool {
self.len == 0
}

View File

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

View File

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

View File

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

View File

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

View File

@ -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<Paddr>) -> Result<()> {
let start_vaddr = paddr_to_vaddr(range.start);
let virtual_end = self

View File

@ -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)]

View File

@ -1,5 +1,7 @@
// SPDX-License-Identifier: MPL-2.0
//! Logging support.
use log::{Level, Metadata, Record};
use crate::early_println;

View File

@ -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<usize>) -> Result<(), Error> {
if byte_range.end > self.nbytes() {
return Err(Error::InvalidArgs);

View File

@ -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.

View File

@ -107,13 +107,16 @@ pub(crate) const KERNEL_VADDR_RANGE: Range<Vaddr> = 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<Vec<MemoryRegion>> = Once::new();
pub(crate) fn misc_init() {

View File

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

View File

@ -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<Option<PageProperty>> {
if !(0..MAX_USERSPACE_VADDR).contains(&vaddr) {

View File

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

View File

@ -2,6 +2,7 @@
//! The prelude.
/// A specialized [`core::result::Result``] type for this crate.
pub type Result<T> = core::result::Result<T, crate::error::Error>;
pub(crate) use alloc::{boxed::Box, sync::Arc, vec::Vec};

View File

@ -1,5 +1,7 @@
// SPDX-License-Identifier: MPL-2.0
//! Useful synchronization primitives.
mod atomic_bits;
mod mutex;
// TODO: refactor this rcu implementation

View File

@ -92,7 +92,10 @@ pub struct MutexGuard_<T: ?Sized, R: Deref<Target = Mutex<T>>> {
mutex: R,
}
/// A guard that provides exclusive access to the data protected by a [`Mutex`].
pub type MutexGuard<'a, T> = MutexGuard_<T, &'a Mutex<T>>;
/// An guard that provides exclusive access to the data protected by a [`Arc<Mutex>`].
pub type ArcMutexGuard<T> = MutexGuard_<T, Arc<Mutex<T>>>;
impl<T: ?Sized, R: Deref<Target = Mutex<T>>> Deref for MutexGuard_<T, R> {

View File

@ -544,7 +544,10 @@ pub struct RwLockReadGuard_<T: ?Sized, R: Deref<Target = RwLock<T>> + Clone> {
inner: R,
}
/// A guard that provides shared read access to the data protected by a [`RwLock`].
pub type RwLockReadGuard<'a, T> = RwLockReadGuard_<T, &'a RwLock<T>>;
/// A guard that provides shared read access to the data protected by a [`Arc<RwLock>`].
pub type ArcRwLockReadGuard<T> = RwLockReadGuard_<T, Arc<RwLock<T>>>;
impl<T: ?Sized, R: Deref<Target = RwLock<T>> + Clone> Deref for RwLockReadGuard_<T, R> {
@ -575,7 +578,9 @@ pub struct RwLockWriteGuard_<T: ?Sized, R: Deref<Target = RwLock<T>> + Clone> {
inner: R,
}
/// A guard that provides exclusive write access to the data protected by a [`RwLock`].
pub type RwLockWriteGuard<'a, T> = RwLockWriteGuard_<T, &'a RwLock<T>>;
/// A guard that provides exclusive write access to the data protected by a [`Arc<RwLock>`].
pub type ArcRwLockWriteGuard<T> = RwLockWriteGuard_<T, Arc<RwLock<T>>>;
impl<T: ?Sized, R: Deref<Target = RwLock<T>> + Clone> Deref for RwLockWriteGuard_<T, R> {
@ -644,7 +649,9 @@ pub struct RwLockUpgradeableGuard_<T: ?Sized, R: Deref<Target = RwLock<T>> + Clo
inner: R,
}
/// A upgradable guard that provides read access to the data protected by a [`RwLock`].
pub type RwLockUpgradeableGuard<'a, T> = RwLockUpgradeableGuard_<T, &'a RwLock<T>>;
/// A upgradable guard that provides read access to the data protected by a [`Arc<RwLock>`].
pub type ArcRwLockUpgradeableGuard<T> = RwLockUpgradeableGuard_<T, Arc<RwLock<T>>>;
impl<T: ?Sized, R: Deref<Target = RwLock<T>> + Clone> RwLockUpgradeableGuard_<T, R> {

View File

@ -225,7 +225,9 @@ pub struct RwMutexReadGuard_<T: ?Sized, R: Deref<Target = RwMutex<T>>> {
inner: R,
}
/// A guard that provides shared read access to the data protected by a [`RwMutex`].
pub type RwMutexReadGuard<'a, T> = RwMutexReadGuard_<T, &'a RwMutex<T>>;
/// A guard that provides shared read access to the data protected by a [`Arc<RwMutex>`].
pub type ArcRwMutexReadGuard<T> = RwMutexReadGuard_<T, Arc<RwMutex<T>>>;
impl<T: ?Sized, R: Deref<Target = RwMutex<T>>> Deref for RwMutexReadGuard_<T, R> {
@ -250,7 +252,9 @@ pub struct RwMutexWriteGuard_<T: ?Sized, R: Deref<Target = RwMutex<T>>> {
inner: R,
}
/// A guard that provides exclusive write access to the data protected by a [`RwMutex`].
pub type RwMutexWriteGuard<'a, T> = RwMutexWriteGuard_<T, &'a RwMutex<T>>;
/// A guard that provides exclusive write access to the data protected by a [`Arc<RwMutex>`].
pub type ArcRwMutexWriteGuard<T> = RwMutexWriteGuard_<T, Arc<RwMutex<T>>>;
impl<T: ?Sized, R: Deref<Target = RwMutex<T>>> Deref for RwMutexWriteGuard_<T, R> {
@ -315,7 +319,9 @@ pub struct RwMutexUpgradeableGuard_<T: ?Sized, R: Deref<Target = RwMutex<T>>> {
inner: R,
}
/// A upgradable guard that provides read access to the data protected by a [`RwMutex`].
pub type RwMutexUpgradeableGuard<'a, T> = RwMutexUpgradeableGuard_<T, &'a RwMutex<T>>;
/// A upgradable guard that provides read access to the data protected by a [`Arc<RwMutex>`].
pub type ArcRwMutexUpgradeableGuard<T> = RwMutexUpgradeableGuard_<T, Arc<RwMutex<T>>>;
impl<T: ?Sized, R: Deref<Target = RwMutex<T>> + Clone> RwMutexUpgradeableGuard_<T, R> {

View File

@ -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_<T, &'a SpinLock<T>>;
/// A guard that provides exclusive access to the data protected by a [`Arc<SpinLock>`].
pub type ArcSpinLockGuard<T> = SpinLockGuard_<T, Arc<SpinLock<T>>>;
/// The guard of a spin lock that disables the local IRQs.

View File

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

View File

@ -55,6 +55,7 @@ pub fn take_current_task() -> Option<Arc<Task>> {
})
}
/// Retrieves the current task running on the processor.
pub fn current_task() -> Option<Arc<Task>> {
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<Task>) {
// 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()

View File

@ -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<Task>);
/// Dequeues a task from the scheduler.
fn dequeue(&self) -> Option<Arc<Task>>;
/// Tells whether the given task should be preempted by other tasks in the queue.
@ -61,6 +63,7 @@ pub fn fetch_task() -> Option<Arc<Task>> {
GLOBAL_SCHEDULER.lock_irq_disabled().dequeue()
}
/// Adds a task to the global scheduler.
pub fn add_task(task: Arc<Task>) {
GLOBAL_SCHEDULER.lock_irq_disabled().enqueue(task);
}

View File

@ -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<F>(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<T>(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

View File

@ -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<Self> {
IRQ_ALLOCATOR
.get()
@ -39,6 +44,7 @@ impl IrqLine {
.ok_or(Error::NotEnoughResources)
}
/// Allocates an available IRQ line.
pub fn alloc() -> Result<Self> {
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()
}

View File

@ -1,5 +1,7 @@
// SPDX-License-Identifier: MPL-2.0
//! Handle trap across kernel and user space.
mod handler;
mod irq;
pub mod softirq;

View File

@ -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<UserSpace>) -> Self {
Self {
current: Task::current(),

View File

@ -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