mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-20 13:06:33 +00:00
Fix multiple issues pointed out by the new compiler
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
5f2bd9d0ac
commit
9e4257b655
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -655,9 +655,9 @@ checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.30.0"
|
version = "0.31.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2e1d97fbe9722ba9bbd0c97051c2956e726562b61f86a25a4360398a40edfc9"
|
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hash32"
|
name = "hash32"
|
||||||
@ -1668,11 +1668,11 @@ checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unwinding"
|
name = "unwinding"
|
||||||
version = "0.2.2"
|
version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dc55842d0db6329a669d55a623c674b02d677b16bfb2d24857d4089d41eba882"
|
checksum = "637d511437df708cee34bdec7ba2f1548d256b7acf3ff20e0a1c559f9bf3a987"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gimli 0.30.0",
|
"gimli 0.31.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -48,7 +48,7 @@ impl device::RxToken for RxToken {
|
|||||||
|
|
||||||
pub struct TxToken<'a>(&'a mut dyn AnyNetworkDevice);
|
pub struct TxToken<'a>(&'a mut dyn AnyNetworkDevice);
|
||||||
|
|
||||||
impl<'a> device::TxToken for TxToken<'a> {
|
impl device::TxToken for TxToken<'_> {
|
||||||
fn consume<R, F>(self, len: usize, f: F) -> R
|
fn consume<R, F>(self, len: usize, f: F) -> R
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut [u8]) -> R,
|
F: FnOnce(&mut [u8]) -> R,
|
||||||
|
@ -166,9 +166,12 @@ impl ClockSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `Instant` captures a specific moment, storing the duration of time
|
/// A specific moment.
|
||||||
|
///
|
||||||
|
/// [`Instant`] captures a specific moment, storing the duration of time
|
||||||
/// elapsed since a reference point (typically the system boot time).
|
/// elapsed since a reference point (typically the system boot time).
|
||||||
/// The `Instant` is expressed in seconds and the fractional part is expressed in nanoseconds.
|
/// The [`Instant`] is expressed in seconds and the fractional part is
|
||||||
|
/// expressed in nanoseconds.
|
||||||
#[derive(Debug, Default, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct Instant {
|
pub struct Instant {
|
||||||
secs: u64,
|
secs: u64,
|
||||||
|
@ -162,9 +162,9 @@ impl<D, E> EtherIface<D, E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ignore the ARP packet if we do not own the target address.
|
// Ignore the ARP packet if we do not own the target address.
|
||||||
if !iface_cx
|
if iface_cx
|
||||||
.ipv4_addr()
|
.ipv4_addr()
|
||||||
.is_some_and(|addr| addr == *target_protocol_addr)
|
.is_none_or(|addr| addr != *target_protocol_addr)
|
||||||
{
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ impl<'a, E> PollContext<'a, E> {
|
|||||||
pub(super) trait FnHelper<A, B, C, O>: FnMut(A, B, C) -> O {}
|
pub(super) trait FnHelper<A, B, C, O>: FnMut(A, B, C) -> O {}
|
||||||
impl<A, B, C, O, F> FnHelper<A, B, C, O> for F where F: FnMut(A, B, C) -> O {}
|
impl<A, B, C, O, F> FnHelper<A, B, C, O> for F where F: FnMut(A, B, C) -> O {}
|
||||||
|
|
||||||
impl<'a, E> PollContext<'a, E> {
|
impl<E> PollContext<'_, E> {
|
||||||
pub(super) fn poll_ingress<D, P, Q>(
|
pub(super) fn poll_ingress<D, P, Q>(
|
||||||
&mut self,
|
&mut self,
|
||||||
device: &mut D,
|
device: &mut D,
|
||||||
@ -280,7 +280,7 @@ impl<'a, E> PollContext<'a, E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, E> PollContext<'a, E> {
|
impl<E> PollContext<'_, E> {
|
||||||
pub(super) fn poll_egress<D, Q>(&mut self, device: &mut D, mut dispatch_phy: Q)
|
pub(super) fn poll_egress<D, Q>(&mut self, device: &mut D, mut dispatch_phy: Q)
|
||||||
where
|
where
|
||||||
D: Device + ?Sized,
|
D: Device + ?Sized,
|
||||||
|
@ -368,7 +368,7 @@ impl<T, R> SafePtr<T, DmaStream, R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inherit_methods(from = "(*self)")]
|
#[inherit_methods(from = "(*self)")]
|
||||||
impl<'a, T, R> SafePtr<T, &'a DmaStream, R> {
|
impl<T, R> SafePtr<T, &DmaStream, R> {
|
||||||
pub fn sync(&self) -> Result<()>;
|
pub fn sync(&self) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
use crate::{Cons, Nil};
|
use crate::{Cons, Nil};
|
||||||
|
|
||||||
/// This trait will extend a set with another item.
|
/// This trait will extend a set with another item.
|
||||||
|
///
|
||||||
/// If the set already contains the item, it will return the original set.
|
/// If the set already contains the item, it will return the original set.
|
||||||
/// Otherwise, it will return the new set with the new item.
|
/// Otherwise, it will return the new set with the new item.
|
||||||
/// The implementation should care about the item orders when extending set.
|
/// The implementation should care about the item orders when extending set.
|
||||||
|
@ -159,15 +159,19 @@ impl<'a> CurrentUserSpace<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A trait providing the ability to read a C string from the user space
|
/// A trait providing the ability to read a C string from the user space.
|
||||||
/// of the current process specifically for [`VmReader<'_, UserSpace>`], which
|
///
|
||||||
/// should reading the bytes iteratively in the reader until encountering
|
/// The user space should be of the current process. The implemented method
|
||||||
/// the end of the reader or reading a `\0` (is also included into the final C String).
|
/// should read the bytes iteratively in the reader ([`VmReader`]) until
|
||||||
|
/// encountering the end of the reader or reading a `\0` (which is also
|
||||||
|
/// included in the final C String).
|
||||||
pub trait ReadCString {
|
pub trait ReadCString {
|
||||||
fn read_cstring(&mut self) -> Result<CString>;
|
fn read_cstring(&mut self) -> Result<CString>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ReadCString for VmReader<'a, Fallible> {
|
impl ReadCString for VmReader<'_, Fallible> {
|
||||||
|
/// Reads a C string from the user space.
|
||||||
|
///
|
||||||
/// This implementation is inspired by
|
/// This implementation is inspired by
|
||||||
/// the `do_strncpy_from_user` function in Linux kernel.
|
/// the `do_strncpy_from_user` function in Linux kernel.
|
||||||
/// The original Linux implementation can be found at:
|
/// The original Linux implementation can be found at:
|
||||||
|
@ -240,7 +240,7 @@ impl LineDiscipline {
|
|||||||
b'\r' => echo_callback("\r\n"),
|
b'\r' => echo_callback("\r\n"),
|
||||||
ch if ch == *termios.get_special_char(CC_C_CHAR::VERASE) => {
|
ch if ch == *termios.get_special_char(CC_C_CHAR::VERASE) => {
|
||||||
// write a space to overwrite current character
|
// write a space to overwrite current character
|
||||||
let backspace: &str = core::str::from_utf8(&[b'\x08', b' ', b'\x08']).unwrap();
|
let backspace: &str = core::str::from_utf8(b"\x08 \x08").unwrap();
|
||||||
echo_callback(backspace);
|
echo_callback(backspace);
|
||||||
}
|
}
|
||||||
ch if is_printable_char(ch) => print!("{}", char::from(ch)),
|
ch if is_printable_char(ch) => print!("{}", char::from(ch)),
|
||||||
|
@ -403,8 +403,8 @@ impl ExfatDentrySet {
|
|||||||
}
|
}
|
||||||
Ok(name)
|
Ok(name)
|
||||||
}
|
}
|
||||||
/// Name dentries are not permitted to modify. We should create a new dentry set for renaming.
|
|
||||||
|
|
||||||
|
/// Name dentries are not permitted to modify. We should create a new dentry set for renaming.
|
||||||
fn calculate_checksum(&self) -> u16 {
|
fn calculate_checksum(&self) -> u16 {
|
||||||
const CHECKSUM_BYTES_RANGE: Range<usize> = 2..4;
|
const CHECKSUM_BYTES_RANGE: Range<usize> = 2..4;
|
||||||
const EMPTY_RANGE: Range<usize> = 0..0;
|
const EMPTY_RANGE: Range<usize> = 0..0;
|
||||||
@ -502,7 +502,6 @@ impl Iterator for ExfatDentryIterator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// On-disk dentry formats
|
/// On-disk dentry formats
|
||||||
|
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
#[derive(Clone, Debug, Default, Copy, Pod)]
|
#[derive(Clone, Debug, Default, Copy, Pod)]
|
||||||
// For files & directories
|
// For files & directories
|
||||||
|
@ -891,7 +891,7 @@ impl ExfatInode {
|
|||||||
// TODO: remove trailing periods of pathname.
|
// TODO: remove trailing periods of pathname.
|
||||||
// Do not allow creation of files with names ending with period(s).
|
// Do not allow creation of files with names ending with period(s).
|
||||||
|
|
||||||
let name_dentries = (name.len() + EXFAT_FILE_NAME_LEN - 1) / EXFAT_FILE_NAME_LEN;
|
let name_dentries = name.len().div_ceil(EXFAT_FILE_NAME_LEN);
|
||||||
let num_dentries = name_dentries + 2; // FILE Entry + Stream Entry + Name Entry
|
let num_dentries = name_dentries + 2; // FILE Entry + Stream Entry + Name Entry
|
||||||
|
|
||||||
// We update the size of inode before writing page_cache, but it is fine since we've cleaned the page_cache.
|
// We update the size of inode before writing page_cache, but it is fine since we've cleaned the page_cache.
|
||||||
@ -1139,7 +1139,7 @@ impl Inode for ExfatInode {
|
|||||||
ino: inner.ino,
|
ino: inner.ino,
|
||||||
size: inner.size,
|
size: inner.size,
|
||||||
blk_size,
|
blk_size,
|
||||||
blocks: (inner.size + blk_size - 1) / blk_size,
|
blocks: inner.size.div_ceil(blk_size),
|
||||||
atime: inner.atime.as_duration().unwrap_or_default(),
|
atime: inner.atime.as_duration().unwrap_or_default(),
|
||||||
mtime: inner.mtime.as_duration().unwrap_or_default(),
|
mtime: inner.mtime.as_duration().unwrap_or_default(),
|
||||||
ctime: inner.ctime.as_duration().unwrap_or_default(),
|
ctime: inner.ctime.as_duration().unwrap_or_default(),
|
||||||
|
@ -698,7 +698,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let steps = 7;
|
let steps = 7;
|
||||||
let write_len = (BUF_SIZE + steps - 1) / steps;
|
let write_len = BUF_SIZE.div_ceil(steps);
|
||||||
for i in 0..steps {
|
for i in 0..steps {
|
||||||
let start = i * write_len;
|
let start = i * write_len;
|
||||||
let end = BUF_SIZE.min(start + write_len);
|
let end = BUF_SIZE.min(start + write_len);
|
||||||
|
@ -14,7 +14,7 @@ pub fn make_hash_index(cluster: ClusterID, offset: u32) -> usize {
|
|||||||
pub fn calc_checksum_32(data: &[u8]) -> u32 {
|
pub fn calc_checksum_32(data: &[u8]) -> u32 {
|
||||||
let mut checksum: u32 = 0;
|
let mut checksum: u32 = 0;
|
||||||
for &value in data {
|
for &value in data {
|
||||||
checksum = ((checksum << 31) | (checksum >> 1)).wrapping_add(value as u32);
|
checksum = checksum.rotate_right(1).wrapping_add(value as u32);
|
||||||
}
|
}
|
||||||
checksum
|
checksum
|
||||||
}
|
}
|
||||||
@ -27,7 +27,7 @@ pub fn calc_checksum_16(data: &[u8], ignore: core::ops::Range<usize>, prev_check
|
|||||||
if ignore.contains(&pos) {
|
if ignore.contains(&pos) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
result = ((result << 15) | (result >> 1)).wrapping_add(value as u16);
|
result = result.rotate_right(1).wrapping_add(value as u16);
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,7 @@ impl<'a> DirEntryReader<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for DirEntryReader<'a> {
|
impl Iterator for DirEntryReader<'_> {
|
||||||
type Item = (usize, DirEntry);
|
type Item = (usize, DirEntry);
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
@ -1761,7 +1761,7 @@ impl<'a> DeviceRangeReader<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for DeviceRangeReader<'a> {
|
impl Iterator for DeviceRangeReader<'_> {
|
||||||
type Item = Range<Ext2Bid>;
|
type Item = Range<Ext2Bid>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
@ -491,7 +491,7 @@ impl<'a> FsPath<'a> {
|
|||||||
impl<'a> TryFrom<&'a str> for FsPath<'a> {
|
impl<'a> TryFrom<&'a str> for FsPath<'a> {
|
||||||
type Error = crate::error::Error;
|
type Error = crate::error::Error;
|
||||||
|
|
||||||
fn try_from(path: &'a str) -> Result<FsPath> {
|
fn try_from(path: &'a str) -> Result<FsPath<'a>> {
|
||||||
if path.is_empty() {
|
if path.is_empty() {
|
||||||
return_errno_with_message!(Errno::ENOENT, "path is an empty string");
|
return_errno_with_message!(Errno::ENOENT, "path is an empty string");
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,6 @@ use crate::{
|
|||||||
mod cap_last_cap;
|
mod cap_last_cap;
|
||||||
|
|
||||||
/// Represents the inode at `/proc/sys/kernel`.
|
/// Represents the inode at `/proc/sys/kernel`.
|
||||||
|
|
||||||
pub struct KernelDirOps;
|
pub struct KernelDirOps;
|
||||||
|
|
||||||
impl KernelDirOps {
|
impl KernelDirOps {
|
||||||
|
@ -502,7 +502,7 @@ pub struct InodeWriter<'a> {
|
|||||||
offset: usize,
|
offset: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Write for InodeWriter<'a> {
|
impl Write for InodeWriter<'_> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
|
fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
|
||||||
let mut reader = VmReader::from(buf).to_fallible();
|
let mut reader = VmReader::from(buf).to_fallible();
|
||||||
|
@ -6,6 +6,7 @@ use super::*;
|
|||||||
pub const OFFSET_MAX: usize = i64::MAX as usize;
|
pub const OFFSET_MAX: usize = i64::MAX as usize;
|
||||||
|
|
||||||
/// A range in a file.
|
/// A range in a file.
|
||||||
|
///
|
||||||
/// The range is [start, end).
|
/// The range is [start, end).
|
||||||
/// The range is valid if start < end.
|
/// The range is valid if start < end.
|
||||||
/// The range is empty if start == end.
|
/// The range is empty if start == end.
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
#![feature(fn_traits)]
|
#![feature(fn_traits)]
|
||||||
#![feature(format_args_nl)]
|
#![feature(format_args_nl)]
|
||||||
#![feature(int_roundings)]
|
#![feature(int_roundings)]
|
||||||
#![feature(iter_repeat_n)]
|
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![feature(linkage)]
|
#![feature(linkage)]
|
||||||
#![feature(linked_list_remove)]
|
#![feature(linked_list_remove)]
|
||||||
|
@ -74,9 +74,8 @@ impl BoundDatagram {
|
|||||||
// But current smoltcp API seems not to support this behavior.
|
// But current smoltcp API seems not to support this behavior.
|
||||||
reader
|
reader
|
||||||
.read(&mut VmWriter::from(socket_buffer))
|
.read(&mut VmWriter::from(socket_buffer))
|
||||||
.map_err(|e| {
|
.inspect_err(|e| {
|
||||||
warn!("unexpected UDP packet will be sent");
|
warn!("unexpected UDP packet {e:#?} will be sent");
|
||||||
e
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -34,8 +34,8 @@ pub(super) struct Credentials_ {
|
|||||||
supplementary_gids: RwLock<BTreeSet<Gid>>,
|
supplementary_gids: RwLock<BTreeSet<Gid>>,
|
||||||
|
|
||||||
/// The Linux capabilities.
|
/// The Linux capabilities.
|
||||||
|
///
|
||||||
/// This is not the capability (in static_cap.rs) enforced on rust objects.
|
/// This is not the capability (in static_cap.rs) enforced on rust objects.
|
||||||
|
|
||||||
/// Capability that child processes can inherit
|
/// Capability that child processes can inherit
|
||||||
inheritable_capset: AtomicCapSet,
|
inheritable_capset: AtomicCapSet,
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ impl<'a> FutexIter<'a> {
|
|||||||
|
|
||||||
const ROBUST_LIST_LIMIT: isize = 2048;
|
const ROBUST_LIST_LIMIT: isize = 2048;
|
||||||
|
|
||||||
impl<'a> Iterator for FutexIter<'a> {
|
impl Iterator for FutexIter<'_> {
|
||||||
type Item = Vaddr;
|
type Item = Vaddr;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
@ -108,7 +108,7 @@ pub struct ProcessGroupGuard<'a> {
|
|||||||
inner: MutexGuard<'a, Inner>,
|
inner: MutexGuard<'a, Inner>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ProcessGroupGuard<'a> {
|
impl ProcessGroupGuard<'_> {
|
||||||
/// Returns an iterator over the processes in the group.
|
/// Returns an iterator over the processes in the group.
|
||||||
pub fn iter(&self) -> ProcessGroupIter {
|
pub fn iter(&self) -> ProcessGroupIter {
|
||||||
ProcessGroupIter {
|
ProcessGroupIter {
|
||||||
|
@ -44,7 +44,7 @@ pub struct ProcessTable<'a> {
|
|||||||
inner: MutexGuard<'a, BTreeMap<Pid, Arc<Process>>>,
|
inner: MutexGuard<'a, BTreeMap<Pid, Arc<Process>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ProcessTable<'a> {
|
impl ProcessTable<'_> {
|
||||||
/// Returns an iterator over the processes in the table.
|
/// Returns an iterator over the processes in the table.
|
||||||
pub fn iter(&self) -> ProcessTableIter {
|
pub fn iter(&self) -> ProcessTableIter {
|
||||||
ProcessTableIter {
|
ProcessTableIter {
|
||||||
|
@ -14,7 +14,6 @@ use crate::prelude::*;
|
|||||||
/// > about the environment in which it is operating. The form of this information
|
/// > about the environment in which it is operating. The form of this information
|
||||||
/// > is a table of key-value pairs, where the keys are from the set of ‘AT_’
|
/// > is a table of key-value pairs, where the keys are from the set of ‘AT_’
|
||||||
/// > values in elf.h.
|
/// > values in elf.h.
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
@ -338,11 +338,7 @@ fn map_segment_vmo(
|
|||||||
vm_map_options = vm_map_options.offset(offset).handle_page_faults_around();
|
vm_map_options = vm_map_options.offset(offset).handle_page_faults_around();
|
||||||
let map_addr = vm_map_options.build()?;
|
let map_addr = vm_map_options.build()?;
|
||||||
|
|
||||||
let anonymous_map_size: usize = if total_map_size > segment_size {
|
let anonymous_map_size: usize = total_map_size.saturating_sub(segment_size);
|
||||||
total_map_size - segment_size
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
if anonymous_map_size > 0 {
|
if anonymous_map_size > 0 {
|
||||||
let mut anonymous_map_options = root_vmar
|
let mut anonymous_map_options = root_vmar
|
||||||
|
@ -104,7 +104,7 @@ impl<'a, T: DirentSerializer> DirentBufferReader<'a, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: DirentSerializer> DirentVisitor for DirentBufferReader<'a, T> {
|
impl<T: DirentSerializer> DirentVisitor for DirentBufferReader<'_, T> {
|
||||||
fn visit(&mut self, name: &str, ino: u64, type_: InodeType, offset: usize) -> Result<()> {
|
fn visit(&mut self, name: &str, ino: u64, type_: InodeType, offset: usize) -> Result<()> {
|
||||||
let dirent_serializer = T::new(ino, offset as u64, type_, CString::new(name)?);
|
let dirent_serializer = T::new(ino, offset as u64, type_, CString::new(name)?);
|
||||||
if self.read_len >= self.buffer.len() {
|
if self.read_len >= self.buffer.len() {
|
||||||
|
@ -218,6 +218,7 @@ impl MMapOptions {
|
|||||||
self.typ
|
self.typ
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub fn flags(&self) -> MMapFlags {
|
pub fn flags(&self) -> MMapFlags {
|
||||||
self.flags
|
self.flags
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,7 @@ impl From<c_pollfd> for PollFd {
|
|||||||
|
|
||||||
impl From<PollFd> for c_pollfd {
|
impl From<PollFd> for c_pollfd {
|
||||||
fn from(raw: PollFd) -> Self {
|
fn from(raw: PollFd) -> Self {
|
||||||
let fd = if let Some(fd) = raw.fd() { fd } else { -1 };
|
let fd = raw.fd().unwrap_or(-1);
|
||||||
let events = raw.events().bits() as i16;
|
let events = raw.events().bits() as i16;
|
||||||
let revents = raw.revents().get().bits() as i16;
|
let revents = raw.revents().get().bits() as i16;
|
||||||
Self {
|
Self {
|
||||||
|
@ -61,6 +61,7 @@ pub struct Taskless {
|
|||||||
/// The function that will be called when executing this taskless job.
|
/// The function that will be called when executing this taskless job.
|
||||||
callback: Box<RefCell<dyn FnMut() + Send + Sync + 'static>>,
|
callback: Box<RefCell<dyn FnMut() + Send + Sync + 'static>>,
|
||||||
/// Whether this `Taskless` is disabled.
|
/// Whether this `Taskless` is disabled.
|
||||||
|
#[allow(unused)]
|
||||||
is_disabled: AtomicBool,
|
is_disabled: AtomicBool,
|
||||||
link: LinkedListAtomicLink,
|
link: LinkedListAtomicLink,
|
||||||
}
|
}
|
||||||
@ -74,6 +75,7 @@ cpu_local! {
|
|||||||
|
|
||||||
impl Taskless {
|
impl Taskless {
|
||||||
/// Creates a new `Taskless` instance with its callback function.
|
/// Creates a new `Taskless` instance with its callback function.
|
||||||
|
#[allow(unused)]
|
||||||
pub fn new<F>(callback: F) -> Arc<Self>
|
pub fn new<F>(callback: F) -> Arc<Self>
|
||||||
where
|
where
|
||||||
F: FnMut() + Send + Sync + 'static,
|
F: FnMut() + Send + Sync + 'static,
|
||||||
@ -94,6 +96,7 @@ impl Taskless {
|
|||||||
/// Schedules this taskless job and it will be executed in later time.
|
/// Schedules this taskless job and it will be executed in later time.
|
||||||
///
|
///
|
||||||
/// If the taskless job has been scheduled, this function will do nothing.
|
/// If the taskless job has been scheduled, this function will do nothing.
|
||||||
|
#[allow(unused)]
|
||||||
pub fn schedule(self: &Arc<Self>) {
|
pub fn schedule(self: &Arc<Self>) {
|
||||||
do_schedule(self, &TASKLESS_LIST);
|
do_schedule(self, &TASKLESS_LIST);
|
||||||
SoftIrqLine::get(TASKLESS_SOFTIRQ_ID).raise();
|
SoftIrqLine::get(TASKLESS_SOFTIRQ_ID).raise();
|
||||||
@ -103,6 +106,7 @@ impl Taskless {
|
|||||||
/// in softirq context.
|
/// in softirq context.
|
||||||
///
|
///
|
||||||
/// If the taskless job has been scheduled, this function will do nothing.
|
/// If the taskless job has been scheduled, this function will do nothing.
|
||||||
|
#[allow(unused)]
|
||||||
pub fn schedule_urgent(self: &Arc<Self>) {
|
pub fn schedule_urgent(self: &Arc<Self>) {
|
||||||
do_schedule(self, &TASKLESS_URGENT_LIST);
|
do_schedule(self, &TASKLESS_URGENT_LIST);
|
||||||
SoftIrqLine::get(TASKLESS_URGENT_SOFTIRQ_ID).raise();
|
SoftIrqLine::get(TASKLESS_URGENT_SOFTIRQ_ID).raise();
|
||||||
@ -111,17 +115,20 @@ impl Taskless {
|
|||||||
/// Enables this `Taskless` so that it can be executed once it has been scheduled.
|
/// Enables this `Taskless` so that it can be executed once it has been scheduled.
|
||||||
///
|
///
|
||||||
/// A new `Taskless` is enabled by default.
|
/// A new `Taskless` is enabled by default.
|
||||||
|
#[allow(unused)]
|
||||||
pub fn enable(&self) {
|
pub fn enable(&self) {
|
||||||
self.is_disabled.store(false, Ordering::Release);
|
self.is_disabled.store(false, Ordering::Release);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disables this `Taskless` so that it can not be scheduled. Note that if the `Taskless`
|
/// Disables this `Taskless` so that it can not be scheduled. Note that if the `Taskless`
|
||||||
/// has been scheduled, it can still continue to complete this job.
|
/// has been scheduled, it can still continue to complete this job.
|
||||||
|
#[allow(unused)]
|
||||||
pub fn disable(&self) {
|
pub fn disable(&self) {
|
||||||
self.is_disabled.store(true, Ordering::Release);
|
self.is_disabled.store(true, Ordering::Release);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
fn do_schedule(
|
fn do_schedule(
|
||||||
taskless: &Arc<Taskless>,
|
taskless: &Arc<Taskless>,
|
||||||
taskless_list: &'static CpuLocal<RefCell<LinkedList<TasklessAdapter>>>,
|
taskless_list: &'static CpuLocal<RefCell<LinkedList<TasklessAdapter>>>,
|
||||||
|
@ -2,6 +2,68 @@
|
|||||||
|
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
//! Work queue mechanism.
|
||||||
|
//!
|
||||||
|
//! # Overview
|
||||||
|
//!
|
||||||
|
//! A `workqueue` is a kernel-level mechanism used to schedule and execute deferred work.
|
||||||
|
//! Deferred work refers to tasks that need to be executed at some point in the future,
|
||||||
|
//! but not necessarily immediately.
|
||||||
|
//!
|
||||||
|
//! The workqueue mechanism is implemented using a combination of kernel threads and data
|
||||||
|
//! structures such as `WorkItem`, `WorkQueue`, `Worker` and `WorkerPool`. The `WorkItem`
|
||||||
|
//! represents a task to be processed, while the `WorkQueue` maintains the queue of submitted
|
||||||
|
//! `WorkItems`. The `Worker` is responsible for processing these submitted tasks,
|
||||||
|
//! and the `WorkerPool` manages and schedules these workers.
|
||||||
|
//!
|
||||||
|
//! # Examples
|
||||||
|
//!
|
||||||
|
//! The system has a default work queue and worker pool,
|
||||||
|
//! and it also provides high-level APIs for users to use.
|
||||||
|
//! Here is a basic example to how to use those APIs.
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use crate::thread::work_queue::{submit_work_func, submit_work_item, WorkItem};
|
||||||
|
//!
|
||||||
|
//! // Submit to high priority queue.
|
||||||
|
//! submit_work_func(||{ }, true);
|
||||||
|
//!
|
||||||
|
//! // Submit to low priority queue.
|
||||||
|
//! submit_work_func(||{ }, false);
|
||||||
|
//!
|
||||||
|
//! fn deferred_task(){
|
||||||
|
//! // ...
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! // Create a work item.
|
||||||
|
//! let work_item = Arc::new(WorkItem::new(Box::new(deferred_task)));
|
||||||
|
//!
|
||||||
|
//! // Submit to high priority queue.
|
||||||
|
//! submit_work_item(work_item, true);
|
||||||
|
//!
|
||||||
|
//! // Submit to low priority queue.
|
||||||
|
//! submit_work_item(work_item, false);
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! Certainly, users can also create a dedicated WorkQueue and WorkerPool.
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use ostd::cpu::CpuSet;
|
||||||
|
//! use crate::thread::work_queue::{WorkQueue, WorkerPool, WorkItem};
|
||||||
|
//!
|
||||||
|
//! fn deferred_task(){
|
||||||
|
//! // ...
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! let cpu_set = CpuSet::new_full();
|
||||||
|
//! let high_pri_pool = WorkerPool::new(true, cpu_set);
|
||||||
|
//! let my_queue = WorkQueue::new(Arc::downgrade(high_pri_pool.get().unwrap()));
|
||||||
|
//!
|
||||||
|
//! let work_item = Arc::new(WorkItem::new(Box::new(deferred_task)));
|
||||||
|
//! my_queue.enqueue(work_item);
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
|
||||||
use ostd::cpu::CpuSet;
|
use ostd::cpu::CpuSet;
|
||||||
use spin::Once;
|
use spin::Once;
|
||||||
use work_item::WorkItem;
|
use work_item::WorkItem;
|
||||||
@ -19,68 +81,6 @@ static WORKERPOOL_HIGH_PRI: Once<Arc<WorkerPool>> = Once::new();
|
|||||||
static WORKQUEUE_GLOBAL_NORMAL: Once<Arc<WorkQueue>> = Once::new();
|
static WORKQUEUE_GLOBAL_NORMAL: Once<Arc<WorkQueue>> = Once::new();
|
||||||
static WORKQUEUE_GLOBAL_HIGH_PRI: Once<Arc<WorkQueue>> = Once::new();
|
static WORKQUEUE_GLOBAL_HIGH_PRI: Once<Arc<WorkQueue>> = Once::new();
|
||||||
|
|
||||||
/// Work queue mechanism.
|
|
||||||
///
|
|
||||||
/// # Overview
|
|
||||||
///
|
|
||||||
/// A `workqueue` is a kernel-level mechanism used to schedule and execute deferred work.
|
|
||||||
/// Deferred work refers to tasks that need to be executed at some point in the future,
|
|
||||||
/// but not necessarily immediately.
|
|
||||||
///
|
|
||||||
/// The workqueue mechanism is implemented using a combination of kernel threads and data
|
|
||||||
/// structures such as `WorkItem`, `WorkQueue`, `Worker` and `WorkerPool`. The `WorkItem`
|
|
||||||
/// represents a task to be processed, while the `WorkQueue` maintains the queue of submitted
|
|
||||||
/// `WorkItems`. The `Worker` is responsible for processing these submitted tasks,
|
|
||||||
/// and the `WorkerPool` manages and schedules these workers.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// The system has a default work queue and worker pool,
|
|
||||||
/// and it also provides high-level APIs for users to use.
|
|
||||||
/// Here is a basic example to how to use those APIs.
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// use crate::thread::work_queue::{submit_work_func, submit_work_item, WorkItem};
|
|
||||||
///
|
|
||||||
/// // Submit to high priority queue.
|
|
||||||
/// submit_work_func(||{ }, true);
|
|
||||||
///
|
|
||||||
/// // Submit to low priority queue.
|
|
||||||
/// submit_work_func(||{ }, false);
|
|
||||||
///
|
|
||||||
/// fn deferred_task(){
|
|
||||||
/// // ...
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// // Create a work item.
|
|
||||||
/// let work_item = Arc::new(WorkItem::new(Box::new(deferred_task)));
|
|
||||||
///
|
|
||||||
/// // Submit to high priority queue.
|
|
||||||
/// submit_work_item(work_item, true);
|
|
||||||
///
|
|
||||||
/// // Submit to low priority queue.
|
|
||||||
/// submit_work_item(work_item, false);
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Certainly, users can also create a dedicated WorkQueue and WorkerPool.
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// use ostd::cpu::CpuSet;
|
|
||||||
/// use crate::thread::work_queue::{WorkQueue, WorkerPool, WorkItem};
|
|
||||||
///
|
|
||||||
/// fn deferred_task(){
|
|
||||||
/// // ...
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// let cpu_set = CpuSet::new_full();
|
|
||||||
/// let high_pri_pool = WorkerPool::new(true, cpu_set);
|
|
||||||
/// let my_queue = WorkQueue::new(Arc::downgrade(high_pri_pool.get().unwrap()));
|
|
||||||
///
|
|
||||||
/// let work_item = Arc::new(WorkItem::new(Box::new(deferred_task)));
|
|
||||||
/// my_queue.enqueue(work_item);
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
/// Submit a function to a global work queue.
|
/// Submit a function to a global work queue.
|
||||||
pub fn submit_work_func<F>(work_func: F, work_priority: WorkPriority)
|
pub fn submit_work_func<F>(work_func: F, work_priority: WorkPriority)
|
||||||
where
|
where
|
||||||
|
@ -57,6 +57,7 @@ pub trait WorkerScheduler: Sync + Send {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The `Monitor` is responsible for monitoring the `WorkerPool` for scheduling needs.
|
/// The `Monitor` is responsible for monitoring the `WorkerPool` for scheduling needs.
|
||||||
|
///
|
||||||
/// Currently, it only performs a liveness check, and attempts to schedule when no workers
|
/// Currently, it only performs a liveness check, and attempts to schedule when no workers
|
||||||
/// are found processing in the pool.
|
/// are found processing in the pool.
|
||||||
pub struct Monitor {
|
pub struct Monitor {
|
||||||
|
@ -13,6 +13,7 @@ pub struct CpuClock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A profiling clock that contains a user CPU clock and a kernel CPU clock.
|
/// A profiling clock that contains a user CPU clock and a kernel CPU clock.
|
||||||
|
///
|
||||||
/// These two clocks record the CPU time in user mode and kernel mode respectively.
|
/// These two clocks record the CPU time in user mode and kernel mode respectively.
|
||||||
/// Reading this clock directly returns the sum of both times.
|
/// Reading this clock directly returns the sum of both times.
|
||||||
pub struct ProfClock {
|
pub struct ProfClock {
|
||||||
|
@ -173,7 +173,7 @@ pub trait MultiWrite {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MultiRead for VmReaderArray<'a> {
|
impl MultiRead for VmReaderArray<'_> {
|
||||||
fn read(&mut self, writer: &mut VmWriter<'_, Infallible>) -> Result<usize> {
|
fn read(&mut self, writer: &mut VmWriter<'_, Infallible>) -> Result<usize> {
|
||||||
let mut total_len = 0;
|
let mut total_len = 0;
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ impl<'a> MultiRead for VmReaderArray<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MultiRead for VmReader<'a> {
|
impl MultiRead for VmReader<'_> {
|
||||||
fn read(&mut self, writer: &mut VmWriter<'_, Infallible>) -> Result<usize> {
|
fn read(&mut self, writer: &mut VmWriter<'_, Infallible>) -> Result<usize> {
|
||||||
Ok(self.read_fallible(writer)?)
|
Ok(self.read_fallible(writer)?)
|
||||||
}
|
}
|
||||||
@ -202,7 +202,7 @@ impl<'a> MultiRead for VmReader<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MultiWrite for VmWriterArray<'a> {
|
impl MultiWrite for VmWriterArray<'_> {
|
||||||
fn write(&mut self, reader: &mut VmReader<'_, Infallible>) -> Result<usize> {
|
fn write(&mut self, reader: &mut VmReader<'_, Infallible>) -> Result<usize> {
|
||||||
let mut total_len = 0;
|
let mut total_len = 0;
|
||||||
|
|
||||||
@ -221,7 +221,7 @@ impl<'a> MultiWrite for VmWriterArray<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MultiWrite for VmWriter<'a> {
|
impl MultiWrite for VmWriter<'_> {
|
||||||
fn write(&mut self, reader: &mut VmReader<'_, Infallible>) -> Result<usize> {
|
fn write(&mut self, reader: &mut VmReader<'_, Infallible>) -> Result<usize> {
|
||||||
Ok(self.write_fallible(reader)?)
|
Ok(self.write_fallible(reader)?)
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,9 @@ where
|
|||||||
|
|
||||||
bytes[..2].copy_from_slice(&(CSocketAddrFamily::AF_UNIX as u16).to_ne_bytes());
|
bytes[..2].copy_from_slice(&(CSocketAddrFamily::AF_UNIX as u16).to_ne_bytes());
|
||||||
#[allow(clippy::assertions_on_constants)]
|
#[allow(clippy::assertions_on_constants)]
|
||||||
const { assert!(CSocketAddrUnix::PATH_OFFSET == 2) };
|
const {
|
||||||
|
assert!(CSocketAddrUnix::PATH_OFFSET == 2)
|
||||||
|
};
|
||||||
|
|
||||||
let sun_path = &mut bytes[CSocketAddrUnix::PATH_OFFSET..];
|
let sun_path = &mut bytes[CSocketAddrUnix::PATH_OFFSET..];
|
||||||
|
|
||||||
|
@ -224,6 +224,7 @@ impl RingBuffer<u8> {
|
|||||||
/// Writes data from the `reader` to the `RingBuffer`.
|
/// Writes data from the `reader` to the `RingBuffer`.
|
||||||
///
|
///
|
||||||
/// Returns the number of bytes written.
|
/// Returns the number of bytes written.
|
||||||
|
#[allow(unused)]
|
||||||
pub fn write_fallible(&mut self, reader: &mut dyn MultiRead) -> Result<usize> {
|
pub fn write_fallible(&mut self, reader: &mut dyn MultiRead) -> Result<usize> {
|
||||||
let mut producer = Producer {
|
let mut producer = Producer {
|
||||||
rb: self,
|
rb: self,
|
||||||
|
@ -11,4 +11,4 @@ repository ="https://github.com/asterinas/asterinas"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
ostd = { version = "0.9.2", path = "../../ostd" }
|
ostd = { version = "0.9.2", path = "../../ostd" }
|
||||||
owo-colors = "4.0.0"
|
owo-colors = "4.0.0"
|
||||||
unwinding = { version = "0.2.2", default-features = false, features = ["fde-gnu-eh-frame-hdr", "hide-trace", "panic", "personality", "unwinder"] }
|
unwinding = { version = "0.2.3", default-features = false, features = ["fde-gnu-eh-frame-hdr", "hide-trace", "panic", "personality", "unwinder"] }
|
||||||
|
@ -46,6 +46,7 @@ impl KtestPath {
|
|||||||
self.path.pop_back()
|
self.path.pop_back()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn push_front(&mut self, s: &str) {
|
pub fn push_front(&mut self, s: &str) {
|
||||||
self.path.push_front(PathElement::from(s))
|
self.path.push_front(PathElement::from(s))
|
||||||
}
|
}
|
||||||
@ -54,6 +55,7 @@ impl KtestPath {
|
|||||||
self.path.pop_front()
|
self.path.pop_front()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.path.len()
|
self.path.len()
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ pub struct KtestModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl KtestModule {
|
impl KtestModule {
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn nr_this_tests(&self) -> usize {
|
pub fn nr_this_tests(&self) -> usize {
|
||||||
self.tests.len()
|
self.tests.len()
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ owo-colors = { version = "3", optional = true }
|
|||||||
ostd-pod = { git = "https://github.com/asterinas/ostd-pod", rev = "c4644be", version = "0.1.1" }
|
ostd-pod = { git = "https://github.com/asterinas/ostd-pod", rev = "c4644be", version = "0.1.1" }
|
||||||
spin = "0.9.4"
|
spin = "0.9.4"
|
||||||
static_assertions = "1.1.0"
|
static_assertions = "1.1.0"
|
||||||
unwinding = { version = "0.2.2", default-features = false, features = ["fde-gnu-eh-frame-hdr", "hide-trace", "panic", "personality", "unwinder"] }
|
unwinding = { version = "0.2.3", default-features = false, features = ["fde-gnu-eh-frame-hdr", "hide-trace", "panic", "personality", "unwinder"] }
|
||||||
volatile = { version = "0.4.5", features = ["unstable"] }
|
volatile = { version = "0.4.5", features = ["unstable"] }
|
||||||
xarray = { git = "https://github.com/asterinas/xarray", version = "0.1.0" }
|
xarray = { git = "https://github.com/asterinas/xarray", version = "0.1.0" }
|
||||||
|
|
||||||
|
@ -6,9 +6,6 @@
|
|||||||
/// `u64`, and `usize`, to provide methods to make integers aligned to a
|
/// `u64`, and `usize`, to provide methods to make integers aligned to a
|
||||||
/// power of two.
|
/// power of two.
|
||||||
pub trait AlignExt {
|
pub trait AlignExt {
|
||||||
/// Returns whether the number is a power of two
|
|
||||||
fn is_power_of_two(&self) -> bool;
|
|
||||||
|
|
||||||
/// Returns to the smallest number that is greater than or equal to
|
/// Returns to the smallest number that is greater than or equal to
|
||||||
/// `self` and is a multiple of the given power of two.
|
/// `self` and is a multiple of the given power of two.
|
||||||
///
|
///
|
||||||
@ -50,11 +47,6 @@ macro_rules! impl_align_ext {
|
|||||||
($( $uint_type:ty ),+,) => {
|
($( $uint_type:ty ),+,) => {
|
||||||
$(
|
$(
|
||||||
impl AlignExt for $uint_type {
|
impl AlignExt for $uint_type {
|
||||||
#[inline]
|
|
||||||
fn is_power_of_two(&self) -> bool {
|
|
||||||
(*self != 0) && ((*self & (*self - 1)) == 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn align_up(self, align: Self) -> Self {
|
fn align_up(self, align: Self) -> Self {
|
||||||
assert!(align.is_power_of_two() && align >= 2);
|
assert!(align.is_power_of_two() && align >= 2);
|
||||||
|
@ -33,20 +33,37 @@ impl Write for Stdout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Print a string to the console.
|
||||||
|
///
|
||||||
/// This is used when dyn Trait is not supported or fmt::Arguments is fragile to use in PIE.
|
/// This is used when dyn Trait is not supported or fmt::Arguments is fragile to use in PIE.
|
||||||
///
|
///
|
||||||
/// SAFETY: init() must be called before print_str() and there should be no race conditions.
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// [`init()`] must be called before it and there should be no race conditions.
|
||||||
pub unsafe fn print_str(s: &str) {
|
pub unsafe fn print_str(s: &str) {
|
||||||
|
#[allow(static_mut_refs)]
|
||||||
STDOUT.write_str(s).unwrap();
|
STDOUT.write_str(s).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Print a single character to the console.
|
||||||
|
///
|
||||||
|
/// This is used when dyn Trait is not supported or fmt::Arguments is fragile to use in PIE.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// [`init()`] must be called before it and there should be no race conditions.
|
||||||
unsafe fn print_char(c: char) {
|
unsafe fn print_char(c: char) {
|
||||||
|
#[allow(static_mut_refs)]
|
||||||
STDOUT.serial_port.send(c as u8);
|
STDOUT.serial_port.send(c as u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Print a hexadecimal number to the console.
|
||||||
|
///
|
||||||
/// This is used when dyn Trait is not supported or fmt::Arguments is fragile to use in PIE.
|
/// This is used when dyn Trait is not supported or fmt::Arguments is fragile to use in PIE.
|
||||||
///
|
///
|
||||||
/// SAFETY: init() must be called before print_hex() and there should be no race conditions.
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// [`init()`] must be called before it and there should be no race conditions.
|
||||||
pub unsafe fn print_hex(n: u64) {
|
pub unsafe fn print_hex(n: u64) {
|
||||||
print_str("0x");
|
print_str("0x");
|
||||||
for i in (0..16).rev() {
|
for i in (0..16).rev() {
|
||||||
|
@ -65,7 +65,6 @@
|
|||||||
//!
|
//!
|
||||||
|
|
||||||
#![cfg_attr(not(test), no_std)]
|
#![cfg_attr(not(test), no_std)]
|
||||||
#![feature(panic_info_message)]
|
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
use alloc::{boxed::Box, string::String};
|
use alloc::{boxed::Box, string::String};
|
||||||
|
@ -30,6 +30,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
#[allow(dead_code)]
|
||||||
pub struct IommuVersion {
|
pub struct IommuVersion {
|
||||||
major: u8,
|
major: u8,
|
||||||
minor: u8,
|
minor: u8,
|
||||||
@ -37,11 +38,13 @@ pub struct IommuVersion {
|
|||||||
|
|
||||||
impl IommuVersion {
|
impl IommuVersion {
|
||||||
/// Major version number
|
/// Major version number
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn major(&self) -> u8 {
|
pub fn major(&self) -> u8 {
|
||||||
self.major
|
self.major
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Minor version number
|
/// Minor version number
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn minor(&self) -> u8 {
|
pub fn minor(&self) -> u8 {
|
||||||
self.minor
|
self.minor
|
||||||
}
|
}
|
||||||
@ -50,6 +53,7 @@ impl IommuVersion {
|
|||||||
/// Important registers used by IOMMU.
|
/// Important registers used by IOMMU.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct IommuRegisters {
|
pub struct IommuRegisters {
|
||||||
|
#[allow(dead_code)]
|
||||||
version: Volatile<&'static u32, ReadOnly>,
|
version: Volatile<&'static u32, ReadOnly>,
|
||||||
capability: Volatile<&'static u64, ReadOnly>,
|
capability: Volatile<&'static u64, ReadOnly>,
|
||||||
extended_capability: Volatile<&'static u64, ReadOnly>,
|
extended_capability: Volatile<&'static u64, ReadOnly>,
|
||||||
@ -62,6 +66,7 @@ pub struct IommuRegisters {
|
|||||||
|
|
||||||
impl IommuRegisters {
|
impl IommuRegisters {
|
||||||
/// Version of IOMMU
|
/// Version of IOMMU
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn version(&self) -> IommuVersion {
|
pub fn version(&self) -> IommuVersion {
|
||||||
let version = self.version.read();
|
let version = self.version.read();
|
||||||
IommuVersion {
|
IommuVersion {
|
||||||
|
@ -195,6 +195,7 @@ impl ApicId {
|
|||||||
/// In x2APIC mode, the 32-bit logical x2APIC ID, which can be read from
|
/// In x2APIC mode, the 32-bit logical x2APIC ID, which can be read from
|
||||||
/// LDR, is derived from the 32-bit local x2APIC ID:
|
/// LDR, is derived from the 32-bit local x2APIC ID:
|
||||||
/// Logical x2APIC ID = [(x2APIC ID[19:4] << 16) | (1 << x2APIC ID[3:0])]
|
/// Logical x2APIC ID = [(x2APIC ID[19:4] << 16) | (1 << x2APIC ID[3:0])]
|
||||||
|
#[allow(unused)]
|
||||||
pub fn x2apic_logical_id(&self) -> u32 {
|
pub fn x2apic_logical_id(&self) -> u32 {
|
||||||
self.x2apic_logical_cluster_id() << 16 | 1 << self.x2apic_logical_field_id()
|
self.x2apic_logical_cluster_id() << 16 | 1 << self.x2apic_logical_field_id()
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,13 @@
|
|||||||
|
|
||||||
//! Provides the ability to exit QEMU and return a value as debug result.
|
//! Provides the ability to exit QEMU and return a value as debug result.
|
||||||
|
|
||||||
/// The exit code of x86 QEMU isa debug device. In `qemu-system-x86_64` the
|
/// The exit code of x86 QEMU isa debug device.
|
||||||
/// exit code will be `(code << 1) | 1`. So you could never let QEMU invoke
|
///
|
||||||
/// `exit(0)`. We also need to check if the exit code is returned by the
|
/// In `qemu-system-x86_64` the exit code will be `(code << 1) | 1`. So you
|
||||||
/// kernel, so we couldn't use 0 as exit_success because this may conflict
|
/// could never let QEMU invoke `exit(0)`. We also need to check if the exit
|
||||||
/// with QEMU return value 1, which indicates that QEMU itself fails.
|
/// code is returned by the kernel, so we couldn't use 0 as exit_success
|
||||||
|
/// because this may conflict with QEMU return value 1, which indicates that
|
||||||
|
/// QEMU itself fails.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
pub enum QemuExitCode {
|
pub enum QemuExitCode {
|
||||||
|
@ -17,15 +17,18 @@ use crate::{
|
|||||||
trap::{self, IrqLine, TrapFrame},
|
trap::{self, IrqLine, TrapFrame},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The timer frequency (Hz). Here we choose 1000Hz since 1000Hz is easier for unit conversion and
|
/// The timer frequency (Hz).
|
||||||
/// convenient for timer. What's more, the frequency cannot be set too high or too low, 1000Hz is
|
|
||||||
/// a modest choice.
|
|
||||||
///
|
///
|
||||||
/// For system performance reasons, this rate cannot be set too high, otherwise most of the time
|
/// Here we choose 1000Hz since 1000Hz is easier for unit conversion and
|
||||||
/// is spent executing timer code.
|
/// convenient for timer. What's more, the frequency cannot be set too high or
|
||||||
|
/// too low, 1000Hz is a modest choice.
|
||||||
///
|
///
|
||||||
/// Due to hardware limitations, this value cannot be set too low; for example, PIT cannot accept
|
/// For system performance reasons, this rate cannot be set too high, otherwise
|
||||||
/// frequencies lower than 19Hz = 1193182 / 65536 (Timer rate / Divider)
|
/// most of the time is spent executing timer code.
|
||||||
|
///
|
||||||
|
/// Due to hardware limitations, this value cannot be set too low; for example,
|
||||||
|
/// PIT cannot accept frequencies lower than 19Hz = 1193182 / 65536 (Timer rate
|
||||||
|
/// / Divider)
|
||||||
pub const TIMER_FREQ: u64 = 1000;
|
pub const TIMER_FREQ: u64 = 1000;
|
||||||
|
|
||||||
static TIMER_IRQ: Once<IrqLine> = Once::new();
|
static TIMER_IRQ: Once<IrqLine> = Once::new();
|
||||||
|
@ -208,6 +208,7 @@ impl<T: 'static + SingleInstructionBitXorAssign<T>> CpuLocalCell<T> {
|
|||||||
///
|
///
|
||||||
/// Note that this memory operation will not be elided or reordered by the
|
/// Note that this memory operation will not be elided or reordered by the
|
||||||
/// compiler since it is a black-box.
|
/// compiler since it is a black-box.
|
||||||
|
#[allow(unused)]
|
||||||
pub fn bitxor_assign(&'static self, rhs: T) {
|
pub fn bitxor_assign(&'static self, rhs: T) {
|
||||||
let offset = self as *const _ as usize - __cpu_local_start as usize;
|
let offset = self as *const _ as usize - __cpu_local_start as usize;
|
||||||
// SAFETY: The CPU-local object is defined in the `.cpu_local` section,
|
// SAFETY: The CPU-local object is defined in the `.cpu_local` section,
|
||||||
|
@ -114,6 +114,7 @@ pub trait SingleInstructionBitXorAssign<Rhs = Self> {
|
|||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// Please refer to the module-level documentation of [`self`].
|
/// Please refer to the module-level documentation of [`self`].
|
||||||
|
#[allow(unused)]
|
||||||
unsafe fn bitxor_assign(offset: *mut Self, rhs: Rhs);
|
unsafe fn bitxor_assign(offset: *mut Self, rhs: Rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,24 +2,20 @@
|
|||||||
|
|
||||||
//! The standard library for Asterinas and other Rust OSes.
|
//! The standard library for Asterinas and other Rust OSes.
|
||||||
#![feature(alloc_error_handler)]
|
#![feature(alloc_error_handler)]
|
||||||
#![feature(const_mut_refs)]
|
#![feature(allocator_api)]
|
||||||
#![feature(const_ptr_sub_ptr)]
|
#![feature(const_ptr_sub_ptr)]
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
#![feature(coroutines)]
|
#![feature(coroutines)]
|
||||||
#![feature(fn_traits)]
|
#![feature(fn_traits)]
|
||||||
#![feature(generic_const_exprs)]
|
#![feature(generic_const_exprs)]
|
||||||
#![feature(is_none_or)]
|
|
||||||
#![feature(iter_from_coroutine)]
|
#![feature(iter_from_coroutine)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
#![feature(negative_impls)]
|
#![feature(negative_impls)]
|
||||||
#![feature(new_uninit)]
|
|
||||||
#![feature(panic_info_message)]
|
|
||||||
#![feature(ptr_sub_ptr)]
|
#![feature(ptr_sub_ptr)]
|
||||||
#![feature(strict_provenance)]
|
#![feature(strict_provenance)]
|
||||||
#![feature(sync_unsafe_cell)]
|
#![feature(sync_unsafe_cell)]
|
||||||
#![feature(allocator_api)]
|
|
||||||
// The `generic_const_exprs` feature is incomplete however required for the page table
|
// The `generic_const_exprs` feature is incomplete however required for the page table
|
||||||
// const generic implementation. We are using this feature in a conservative manner.
|
// const generic implementation. We are using this feature in a conservative manner.
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
@ -81,7 +77,8 @@ pub unsafe fn init() {
|
|||||||
// SAFETY: This function is called only once and only on the BSP.
|
// SAFETY: This function is called only once and only on the BSP.
|
||||||
unsafe { cpu::local::early_init_bsp_local_base() };
|
unsafe { cpu::local::early_init_bsp_local_base() };
|
||||||
|
|
||||||
mm::heap_allocator::init();
|
// SAFETY: This function is called only once and only on the BSP.
|
||||||
|
unsafe { mm::heap_allocator::init() };
|
||||||
|
|
||||||
boot::init();
|
boot::init();
|
||||||
logger::init();
|
logger::init();
|
||||||
|
@ -199,7 +199,7 @@ pub struct FrameRef<'a> {
|
|||||||
_marker: PhantomData<&'a Frame>,
|
_marker: PhantomData<&'a Frame>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Deref for FrameRef<'a> {
|
impl Deref for FrameRef<'_> {
|
||||||
type Target = Frame;
|
type Target = Frame;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
@ -210,7 +210,10 @@ impl<'a> Deref for FrameRef<'a> {
|
|||||||
// SAFETY: `Frame` is essentially an `*const MetaSlot` that could be used as a `*const` pointer.
|
// SAFETY: `Frame` is essentially an `*const MetaSlot` that could be used as a `*const` pointer.
|
||||||
// The pointer is also aligned to 4.
|
// The pointer is also aligned to 4.
|
||||||
unsafe impl xarray::ItemEntry for Frame {
|
unsafe impl xarray::ItemEntry for Frame {
|
||||||
type Ref<'a> = FrameRef<'a> where Self: 'a;
|
type Ref<'a>
|
||||||
|
= FrameRef<'a>
|
||||||
|
where
|
||||||
|
Self: 'a;
|
||||||
|
|
||||||
fn into_raw(self) -> *const () {
|
fn into_raw(self) -> *const () {
|
||||||
let ptr = self.page.ptr;
|
let ptr = self.page.ptr;
|
||||||
|
@ -31,11 +31,16 @@ const INIT_KERNEL_HEAP_SIZE: usize = PAGE_SIZE * 256;
|
|||||||
#[repr(align(4096))]
|
#[repr(align(4096))]
|
||||||
struct InitHeapSpace([u8; INIT_KERNEL_HEAP_SIZE]);
|
struct InitHeapSpace([u8; INIT_KERNEL_HEAP_SIZE]);
|
||||||
|
|
||||||
static mut HEAP_SPACE: InitHeapSpace = InitHeapSpace([0; INIT_KERNEL_HEAP_SIZE]);
|
/// Initialize the heap allocator.
|
||||||
|
///
|
||||||
pub fn init() {
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This function should be called only once.
|
||||||
|
pub unsafe fn init() {
|
||||||
|
static mut HEAP_SPACE: InitHeapSpace = InitHeapSpace([0; INIT_KERNEL_HEAP_SIZE]);
|
||||||
// SAFETY: The HEAP_SPACE is a static memory range, so it's always valid.
|
// SAFETY: The HEAP_SPACE is a static memory range, so it's always valid.
|
||||||
unsafe {
|
unsafe {
|
||||||
|
#[allow(static_mut_refs)]
|
||||||
HEAP_ALLOCATOR.init(HEAP_SPACE.0.as_ptr(), INIT_KERNEL_HEAP_SIZE);
|
HEAP_ALLOCATOR.init(HEAP_SPACE.0.as_ptr(), INIT_KERNEL_HEAP_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -222,6 +222,7 @@ impl Heap {
|
|||||||
|
|
||||||
/// Returns bounds on the guaranteed usable size of a successful
|
/// Returns bounds on the guaranteed usable size of a successful
|
||||||
/// allocation created with the specified `layout`.
|
/// allocation created with the specified `layout`.
|
||||||
|
#[allow(unused)]
|
||||||
pub fn usable_size(&self, layout: Layout) -> (usize, usize) {
|
pub fn usable_size(&self, layout: Layout) -> (usize, usize) {
|
||||||
match Heap::layout_to_allocator(&layout) {
|
match Heap::layout_to_allocator(&layout) {
|
||||||
HeapAllocator::Slab64Bytes => (layout.size(), 64),
|
HeapAllocator::Slab64Bytes => (layout.size(), 64),
|
||||||
@ -257,6 +258,7 @@ impl Heap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns total memory size in bytes of the heap.
|
/// Returns total memory size in bytes of the heap.
|
||||||
|
#[allow(unused)]
|
||||||
pub fn total_bytes(&self) -> usize {
|
pub fn total_bytes(&self) -> usize {
|
||||||
self.slab_64_bytes.total_blocks() * 64
|
self.slab_64_bytes.total_blocks() * 64
|
||||||
+ self.slab_128_bytes.total_blocks() * 128
|
+ self.slab_128_bytes.total_blocks() * 128
|
||||||
@ -269,6 +271,7 @@ impl Heap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns allocated memory size in bytes.
|
/// Returns allocated memory size in bytes.
|
||||||
|
#[allow(unused)]
|
||||||
pub fn used_bytes(&self) -> usize {
|
pub fn used_bytes(&self) -> usize {
|
||||||
self.slab_64_bytes.used_blocks() * 64
|
self.slab_64_bytes.used_blocks() * 64
|
||||||
+ self.slab_128_bytes.used_blocks() * 128
|
+ self.slab_128_bytes.used_blocks() * 128
|
||||||
@ -281,6 +284,7 @@ impl Heap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns available memory size in bytes.
|
/// Returns available memory size in bytes.
|
||||||
|
#[allow(unused)]
|
||||||
pub fn available_bytes(&self) -> usize {
|
pub fn available_bytes(&self) -> usize {
|
||||||
self.total_bytes() - self.used_bytes()
|
self.total_bytes() - self.used_bytes()
|
||||||
}
|
}
|
||||||
|
@ -45,10 +45,12 @@ impl<const BLK_SIZE: usize> Slab<BLK_SIZE> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub fn total_blocks(&self) -> usize {
|
pub fn total_blocks(&self) -> usize {
|
||||||
self.total_blocks
|
self.total_blocks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub fn used_blocks(&self) -> usize {
|
pub fn used_blocks(&self) -> usize {
|
||||||
self.total_blocks - self.free_block_list.len()
|
self.total_blocks - self.free_block_list.len()
|
||||||
}
|
}
|
||||||
@ -120,6 +122,7 @@ impl<const BLK_SIZE: usize> FreeBlockList<BLK_SIZE> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn pop(&mut self) -> Option<&'static mut FreeBlock> {
|
fn pop(&mut self) -> Option<&'static mut FreeBlock> {
|
||||||
|
#[allow(clippy::manual_inspect)]
|
||||||
self.head.take().map(|node| {
|
self.head.take().map(|node| {
|
||||||
self.head = node.next.take();
|
self.head = node.next.take();
|
||||||
self.len -= 1;
|
self.len -= 1;
|
||||||
|
@ -543,7 +543,7 @@ impl<'a> VmReader<'a, Infallible> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> VmReader<'a, Fallible> {
|
impl VmReader<'_, Fallible> {
|
||||||
/// Constructs a `VmReader` from a pointer and a length, which represents
|
/// Constructs a `VmReader` from a pointer and a length, which represents
|
||||||
/// a memory range in user space.
|
/// a memory range in user space.
|
||||||
///
|
///
|
||||||
@ -608,7 +608,7 @@ impl<'a> VmReader<'a, Fallible> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Fallibility> VmReader<'a, Fallibility> {
|
impl<Fallibility> VmReader<'_, Fallibility> {
|
||||||
/// Returns the number of bytes for the remaining data.
|
/// Returns the number of bytes for the remaining data.
|
||||||
pub const fn remain(&self) -> usize {
|
pub const fn remain(&self) -> usize {
|
||||||
// SAFETY: the end is equal to or greater than the cursor.
|
// SAFETY: the end is equal to or greater than the cursor.
|
||||||
@ -794,7 +794,7 @@ impl<'a> VmWriter<'a, Infallible> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> VmWriter<'a, Fallible> {
|
impl VmWriter<'_, Fallible> {
|
||||||
/// Constructs a `VmWriter` from a pointer and a length, which represents
|
/// Constructs a `VmWriter` from a pointer and a length, which represents
|
||||||
/// a memory range in user space.
|
/// a memory range in user space.
|
||||||
///
|
///
|
||||||
@ -870,7 +870,7 @@ impl<'a> VmWriter<'a, Fallible> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Fallibility> VmWriter<'a, Fallibility> {
|
impl<Fallibility> VmWriter<'_, Fallibility> {
|
||||||
/// Returns the number of bytes for the available space.
|
/// Returns the number of bytes for the available space.
|
||||||
pub const fn avail(&self) -> usize {
|
pub const fn avail(&self) -> usize {
|
||||||
// SAFETY: the end is equal to or greater than the cursor.
|
// SAFETY: the end is equal to or greater than the cursor.
|
||||||
|
@ -334,8 +334,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, M: PageTableMode, E: PageTableEntryTrait, C: PagingConstsTrait> Iterator
|
impl<M: PageTableMode, E: PageTableEntryTrait, C: PagingConstsTrait> Iterator
|
||||||
for Cursor<'a, M, E, C>
|
for Cursor<'_, M, E, C>
|
||||||
where
|
where
|
||||||
[(); C::NR_LEVELS as usize]:,
|
[(); C::NR_LEVELS as usize]:,
|
||||||
{
|
{
|
||||||
|
@ -147,17 +147,6 @@ fn test_user_copy_on_write() {
|
|||||||
assert!(child_pt.query(from.start + 10).is_none());
|
assert!(child_pt.query(from.start + 10).is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
|
||||||
struct BasePagingConsts {}
|
|
||||||
|
|
||||||
impl PagingConstsTrait for BasePagingConsts {
|
|
||||||
const NR_LEVELS: PagingLevel = 4;
|
|
||||||
const BASE_PAGE_SIZE: usize = PAGE_SIZE;
|
|
||||||
const ADDRESS_WIDTH: usize = 48;
|
|
||||||
const HIGHEST_TRANSLATION_LEVEL: PagingLevel = 1;
|
|
||||||
const PTE_SIZE: usize = core::mem::size_of::<PageTableEntry>();
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<M: PageTableMode, E: PageTableEntryTrait, C: PagingConstsTrait> PageTable<M, E, C>
|
impl<M: PageTableMode, E: PageTableEntryTrait, C: PagingConstsTrait> PageTable<M, E, C>
|
||||||
where
|
where
|
||||||
[(); C::NR_LEVELS as usize]:,
|
[(); C::NR_LEVELS as usize]:,
|
||||||
|
@ -22,6 +22,8 @@ cpu_local_cell! {
|
|||||||
static IN_PANIC: bool = false;
|
static IN_PANIC: bool = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The asterinas panic handler.
|
||||||
|
///
|
||||||
/// The panic handler must be defined in the binary crate or in the crate that the binary
|
/// The panic handler must be defined in the binary crate or in the crate that the binary
|
||||||
/// crate explicitly declares by `extern crate`. We cannot let the base crate depend on OSTD
|
/// crate explicitly declares by `extern crate`. We cannot let the base crate depend on OSTD
|
||||||
/// due to prismatic dependencies. That's why we export this symbol and state the
|
/// due to prismatic dependencies. That's why we export this symbol and state the
|
||||||
|
@ -116,7 +116,7 @@ impl<'a> Iter<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for Iter<'a> {
|
impl Iterator for Iter<'_> {
|
||||||
type Item = bool;
|
type Item = bool;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<bool> {
|
fn next(&mut self) -> Option<bool> {
|
||||||
@ -171,7 +171,7 @@ impl<'a> OnesIter<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for OnesIter<'a> {
|
impl Iterator for OnesIter<'_> {
|
||||||
type Item = usize;
|
type Item = usize;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<usize> {
|
fn next(&mut self) -> Option<usize> {
|
||||||
@ -236,7 +236,7 @@ impl<'a> ZeroesIter<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for ZeroesIter<'a> {
|
impl Iterator for ZeroesIter<'_> {
|
||||||
type Item = usize;
|
type Item = usize;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<usize> {
|
fn next(&mut self) -> Option<usize> {
|
||||||
|
@ -26,13 +26,6 @@ pub struct KernelStack {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl KernelStack {
|
impl KernelStack {
|
||||||
pub fn new() -> Result<Self> {
|
|
||||||
Ok(Self {
|
|
||||||
segment: FrameAllocOptions::new(STACK_SIZE_IN_PAGES as usize).alloc_contiguous()?,
|
|
||||||
has_guard_page: false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generates a kernel stack with a guard page.
|
/// Generates a kernel stack with a guard page.
|
||||||
/// An additional page is allocated and be regarded as a guard page, which should not be accessed.
|
/// An additional page is allocated and be regarded as a guard page, which should not be accessed.
|
||||||
pub fn new_with_guard_page() -> Result<Self> {
|
pub fn new_with_guard_page() -> Result<Self> {
|
||||||
|
@ -118,7 +118,7 @@ pub struct UserMode<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// An instance of `UserMode` is bound to the current task. So it must not be sent to other tasks.
|
// An instance of `UserMode` is bound to the current task. So it must not be sent to other tasks.
|
||||||
impl<'a> !Send for UserMode<'a> {}
|
impl !Send for UserMode<'_> {}
|
||||||
// Note that implementing `!Sync` is unnecessary
|
// Note that implementing `!Sync` is unnecessary
|
||||||
// because entering the user space via `UserMode` requires taking a mutable reference.
|
// because entering the user space via `UserMode` requires taking a mutable reference.
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user