diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 09098b4f..6c8a1a9e 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -1,11 +1,12 @@ #![no_std] // <1> #![no_main] // <1> +#![feature(alloc_error_handler)] #![feature(const_mut_refs)] #![feature(core_intrinsics)] // <2> -#![feature(alloc_error_handler)] -#![feature(panic_info_message)] -#![feature(drain_filter)] // 允许Vec的drain_filter特性 #![feature(c_void_variant)] +#![feature(drain_filter)] // 允许Vec的drain_filter特性 +#![feature(panic_info_message)] +#![feature(ptr_internals)] #![feature(trait_upcasting)] #[allow(non_upper_case_globals)] #[allow(non_camel_case_types)] diff --git a/kernel/src/libs/align.rs b/kernel/src/libs/align.rs new file mode 100644 index 00000000..d46ee262 --- /dev/null +++ b/kernel/src/libs/align.rs @@ -0,0 +1,114 @@ +#![allow(dead_code)] +//! 这是一个关于对齐的库,提供了一些对齐的宏和函数、结构体 + +use core::{alloc::GlobalAlloc, fmt::Debug, ptr::Unique}; + +use crate::{syscall::SystemError, KERNEL_ALLOCATOR}; + +/// # AlignedBox +/// +/// 一个用于分配对齐内存的结构体。分配的内存地址符合`ALIGN`的要求。 +/// 如果类型T的对齐要求大于`ALIGN`,则采用T的对齐要求。 +/// +/// ## 说明 +/// +/// `ALIGN`: 对齐要求,必须是2的幂次方,且不为0,否则编译时报错 +pub struct AlignedBox { + inner: Unique, +} + +impl AlignedBox { + const LAYOUT: core::alloc::Layout = { + const fn max(a: usize, b: usize) -> usize { + if a > b { + a + } else { + b + } + } + let layout = core::alloc::Layout::from_size_align( + core::mem::size_of::(), + max(ALIGN, core::mem::align_of::()), + ); + + if let Ok(layout) = layout { + layout + } else { + panic!("Check alignment failed at compile time.") + } + }; + + /// 分配一个新的内存空间,并将其初始化为零。然后返回AlignedBox + /// + /// # Errors + /// + /// 如果分配失败,则返回`Err(SystemError::ENOMEM)` + #[inline(always)] + pub fn new_zeroed() -> Result + where + T: SafeForZero, + { + let ptr = unsafe { KERNEL_ALLOCATOR.alloc_zeroed(Self::LAYOUT) }; + if ptr.is_null() { + return Err(SystemError::ENOMEM); + } else { + return Ok(AlignedBox { + inner: unsafe { Unique::new_unchecked(ptr.cast()) }, + }); + } + } +} + +impl Debug for AlignedBox { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + return write!( + f, + "AlignedBox<{:?}, {:?}>, ptr: {:p}, size: {:}", + core::any::type_name::(), + core::mem::align_of::(), + self.inner.as_ptr(), + core::mem::size_of::() + ); + } +} + +impl Drop for AlignedBox { + fn drop(&mut self) { + unsafe { + // 释放 Unique 智能指针所拥有的内存,并调用类型的析构函数以清理资源 + core::ptr::drop_in_place(self.inner.as_ptr()); + // dealloc memory space + KERNEL_ALLOCATOR.dealloc(self.inner.as_ptr().cast(), Self::LAYOUT); + } + } +} + +impl core::ops::Deref for AlignedBox { + type Target = T; + + fn deref(&self) -> &Self::Target { + unsafe { &*self.inner.as_ptr() } + } +} + +impl core::ops::DerefMut for AlignedBox { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { &mut *self.inner.as_ptr() } + } +} + +impl Clone for AlignedBox { + fn clone(&self) -> Self { + let mut new: AlignedBox = + Self::new_zeroed().unwrap_or_else(|_| alloc::alloc::handle_alloc_error(Self::LAYOUT)); + new.clone_from(self); + return new; + } +} + +/// 一个用于表明某个类型是安全的用于零初始化的 trait +/// +/// 该 trait 用于表明某个类型是安全的用于零初始化的,即该类型的所有位都可以被初始化为 0 而不会出现未定义行为。 +pub unsafe trait SafeForZero {} + +unsafe impl SafeForZero for [u8; NUM] {} diff --git a/kernel/src/libs/int_like.rs b/kernel/src/libs/int_like.rs new file mode 100644 index 00000000..4ee926dc --- /dev/null +++ b/kernel/src/libs/int_like.rs @@ -0,0 +1,109 @@ +//! These code are bring from redox-os, and I think it's a good idea to use it in our project. +//! +//! Helpers used to define types that are backed by integers (typically `usize`), +//! without compromising safety. +//! +//! # Example +//! +//! ``` +//! /// Define an opaque type `Pid` backed by a `usize`. +//! int_like!(Pid, usize); +//! +//! const ZERO: Pid = Pid::from(0); +//! ``` +//! +//! # Example +//! +//! ``` +//! /// Define opaque types `Pid` and `AtomicPid`, backed respectively by a `usize` +//! /// and a `AtomicUsize`. +//! +//! int_like!(Pid, AtomicPid, usize, AtomicUsize); +//! +//! const ZERO: Pid = Pid::from(0); +//! let ATOMIC_PID: AtomicPid = AtomicPid::default(); +//! ``` + +#[macro_export] +macro_rules! int_like { + ($new_type_name:ident, $backing_type: ident) => { + #[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)] + pub struct $new_type_name($backing_type); + + impl $new_type_name { + #[allow(dead_code)] + pub const fn into(self) -> $backing_type { + self.0 + } + #[allow(dead_code)] + pub const fn from(x: $backing_type) -> Self { + $new_type_name(x) + } + } + }; + + ($new_type_name:ident, $new_atomic_type_name: ident, $backing_type:ident, $backing_atomic_type:ident) => { + int_like!($new_type_name, $backing_type); + + /// A mutable holder for T that can safely be shared among threads. + /// Runtime equivalent to using `AtomicUsize`, just type-safer. + pub struct $new_atomic_type_name { + container: $backing_atomic_type, + } + + impl $new_atomic_type_name { + #[allow(dead_code)] + pub const fn new(x: $new_type_name) -> Self { + $new_atomic_type_name { + container: $backing_atomic_type::new(x.into()) + } + } + #[allow(dead_code)] + pub const fn default() -> Self { + Self::new($new_type_name::from(0)) + } + #[allow(dead_code)] + pub fn load(&self, order: ::core::sync::atomic::Ordering) -> $new_type_name { + $new_type_name::from(self.container.load(order)) + } + #[allow(dead_code)] + pub fn store(&self, val: $new_type_name, order: ::core::sync::atomic::Ordering) { + self.container.store(val.into(), order) + } + #[allow(dead_code)] + pub fn swap(&self, val: $new_type_name, order: ::core::sync::atomic::Ordering) -> $new_type_name { + $new_type_name::from(self.container.swap(val.into(), order)) + } + #[allow(dead_code)] + pub fn compare_exchange(&self, current: $new_type_name, new: $new_type_name, success: ::core::sync::atomic::Ordering, failure: ::core::sync::atomic::Ordering) -> ::core::result::Result<$new_type_name, $new_type_name> { + match self.container.compare_exchange(current.into(), new.into(), success, failure) { + Ok(result) => Ok($new_type_name::from(result)), + Err(result) => Err($new_type_name::from(result)) + } + } + #[allow(dead_code)] + pub fn compare_exchange_weak(&self, current: $new_type_name, new: $new_type_name, success: ::core::sync::atomic::Ordering, failure: ::core::sync::atomic::Ordering) -> ::core::result::Result<$new_type_name, $new_type_name> { + match self.container.compare_exchange_weak(current.into(), new.into(), success, failure) { + Ok(result) => Ok($new_type_name::from(result)), + Err(result) => Err($new_type_name::from(result)) + } + } + } + } +} + +#[test] +fn test() { + use core::mem::size_of; + use ::core::sync::atomic::AtomicUsize; + + // Generate type `usize_like`. + int_like!(UsizeLike, usize); + assert_eq!(size_of::(), size_of::()); + + + // Generate types `usize_like` and `AtomicUsize`. + int_like!(UsizeLike2, AtomicUsizeLike, usize, AtomicUsize); + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::(), size_of::()); +} \ No newline at end of file diff --git a/kernel/src/libs/mod.rs b/kernel/src/libs/mod.rs index ed01fba2..9c11da39 100644 --- a/kernel/src/libs/mod.rs +++ b/kernel/src/libs/mod.rs @@ -1,6 +1,11 @@ +pub mod align; pub mod atomic; pub mod casting; pub mod ffi_convert; +#[macro_use] +pub mod int_like; +pub mod keyboard_parser; +pub mod lazy_init; pub mod list; pub mod lockref; pub mod mutex; @@ -14,6 +19,4 @@ pub mod spinlock; pub mod vec_cursor; #[macro_use] pub mod volatile; -pub mod keyboard_parser; -pub mod lazy_init; pub mod wait_queue; diff --git a/tools/bootstrap.sh b/tools/bootstrap.sh index e70696d8..09e5611b 100644 --- a/tools/bootstrap.sh +++ b/tools/bootstrap.sh @@ -43,7 +43,7 @@ install_ubuntu_debian_pkg() gnupg \ lsb-release \ llvm-dev libclang-dev clang gcc-multilib \ - gcc build-essential fdisk dosfstools dnsmasq bridge-utils iptables libssl-dev + gcc build-essential fdisk dosfstools dnsmasq bridge-utils iptables libssl-dev pkg-config if [ -z "$(which docker)" ] && [ -n ${dockerInstall} ]; then echo "正在安装docker..."