mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 15:26:47 +00:00
添加AlignBox和int_like宏 (#272)
This commit is contained in:
parent
ab5c8ca46d
commit
bb24249faa
@ -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)]
|
||||
|
114
kernel/src/libs/align.rs
Normal file
114
kernel/src/libs/align.rs
Normal file
@ -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<T, const ALIGN: usize> {
|
||||
inner: Unique<T>,
|
||||
}
|
||||
|
||||
impl<T, const ALIGN: usize> AlignedBox<T, ALIGN> {
|
||||
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::<T>(),
|
||||
max(ALIGN, core::mem::align_of::<T>()),
|
||||
);
|
||||
|
||||
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<Self, SystemError>
|
||||
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<T, const ALIGN: usize> Debug for AlignedBox<T, ALIGN> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
return write!(
|
||||
f,
|
||||
"AlignedBox<{:?}, {:?}>, ptr: {:p}, size: {:}",
|
||||
core::any::type_name::<T>(),
|
||||
core::mem::align_of::<T>(),
|
||||
self.inner.as_ptr(),
|
||||
core::mem::size_of::<T>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const ALIGN: usize> Drop for AlignedBox<T, ALIGN> {
|
||||
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<T, const ALIGN: usize> core::ops::Deref for AlignedBox<T, ALIGN> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { &*self.inner.as_ptr() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const ALIGN: usize> core::ops::DerefMut for AlignedBox<T, ALIGN> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
unsafe { &mut *self.inner.as_ptr() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone + SafeForZero, const ALIGN: usize> Clone for AlignedBox<T, ALIGN> {
|
||||
fn clone(&self) -> Self {
|
||||
let mut new: AlignedBox<T, ALIGN> =
|
||||
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<const NUM: usize> SafeForZero for [u8; NUM] {}
|
109
kernel/src/libs/int_like.rs
Normal file
109
kernel/src/libs/int_like.rs
Normal file
@ -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::<UsizeLike>(), size_of::<usize>());
|
||||
|
||||
|
||||
// Generate types `usize_like` and `AtomicUsize`.
|
||||
int_like!(UsizeLike2, AtomicUsizeLike, usize, AtomicUsize);
|
||||
assert_eq!(size_of::<UsizeLike2>(), size_of::<usize>());
|
||||
assert_eq!(size_of::<AtomicUsizeLike>(), size_of::<AtomicUsize>());
|
||||
}
|
@ -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;
|
||||
|
@ -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..."
|
||||
|
Loading…
x
Reference in New Issue
Block a user