mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-18 16:26:31 +00:00
feat(ida): IDA内部改为使用XArray实现 (#934)
目前可以记录哪些ID已经分配,支持了ID释放的功能. Signed-off-by: longjin <longjin@DragonOS.org>
This commit is contained in:
11
docs/kernel/libs/id-allocation.md
Normal file
11
docs/kernel/libs/id-allocation.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# ID分配
|
||||||
|
|
||||||
|
:::{note}
|
||||||
|
本文作者:龙进 <longjin@DragonOS.org>
|
||||||
|
|
||||||
|
2024年9月25日
|
||||||
|
:::
|
||||||
|
|
||||||
|
内核提供了一个名为`IdAllocator`的ID分配器,位于`kernel/crates/ida`中。
|
||||||
|
|
||||||
|
它能够分配、释放ID。默认它会自增分配,假如ID大于设定的最大值,它会从最小值开始寻找空闲ID。如果没有空闲的ID,则会分配失败。
|
@ -10,4 +10,5 @@
|
|||||||
lib_ui/scm
|
lib_ui/scm
|
||||||
lib_ui/textui
|
lib_ui/textui
|
||||||
unified-init
|
unified-init
|
||||||
|
id-allocation
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ elf = { version = "=0.7.2", default-features = false }
|
|||||||
fdt = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/fdt", rev = "9862813020" }
|
fdt = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/fdt", rev = "9862813020" }
|
||||||
# 一个no_std的hashmap、hashset
|
# 一个no_std的hashmap、hashset
|
||||||
hashbrown = "=0.13.2"
|
hashbrown = "=0.13.2"
|
||||||
ida = { path = "src/libs/ida" }
|
ida = { path = "crates/ida" }
|
||||||
intertrait = { path = "crates/intertrait" }
|
intertrait = { path = "crates/intertrait" }
|
||||||
kdepends = { path = "crates/kdepends" }
|
kdepends = { path = "crates/kdepends" }
|
||||||
klog_types = { path = "crates/klog_types" }
|
klog_types = { path = "crates/klog_types" }
|
||||||
@ -57,7 +57,6 @@ wait_queue_macros = { path = "crates/wait_queue_macros" }
|
|||||||
paste = "=1.0.14"
|
paste = "=1.0.14"
|
||||||
slabmalloc = { path = "crates/rust-slabmalloc" }
|
slabmalloc = { path = "crates/rust-slabmalloc" }
|
||||||
log = "0.4.21"
|
log = "0.4.21"
|
||||||
xarray = "0.1.0"
|
|
||||||
lru = "0.12.3"
|
lru = "0.12.3"
|
||||||
|
|
||||||
# target为x86_64时,使用下面的依赖
|
# target为x86_64时,使用下面的依赖
|
||||||
|
@ -3,7 +3,7 @@ name = "ida"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["longjin <longjin@dragonos.org>"]
|
authors = ["longjin <longjin@dragonos.org>"]
|
||||||
|
description = "一个基于XArray的ID分配器"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
kdepends = { path = "../kdepends" }
|
3
kernel/crates/ida/README.md
Normal file
3
kernel/crates/ida/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# IDA
|
||||||
|
|
||||||
|
一个基于XArray的ID分配器
|
210
kernel/crates/ida/src/lib.rs
Normal file
210
kernel/crates/ida/src/lib.rs
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![feature(core_intrinsics)]
|
||||||
|
#![allow(internal_features)]
|
||||||
|
#![allow(clippy::needless_return)]
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[macro_use]
|
||||||
|
extern crate std;
|
||||||
|
|
||||||
|
use core::cmp::min;
|
||||||
|
use core::intrinsics::unlikely;
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
use core::ops::Deref;
|
||||||
|
|
||||||
|
struct EmptyIdaItemRef<'a> {
|
||||||
|
_marker: PhantomData<&'a EmptyIdaItem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Deref for EmptyIdaItemRef<'a> {
|
||||||
|
type Target = EmptyIdaItem;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&EmptyIdaItem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct EmptyIdaItem;
|
||||||
|
|
||||||
|
unsafe impl kdepends::xarray::ItemEntry for EmptyIdaItem {
|
||||||
|
type Ref<'a> = EmptyIdaItemRef<'a> where Self: 'a;
|
||||||
|
|
||||||
|
fn into_raw(self) -> *const () {
|
||||||
|
core::ptr::null()
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn from_raw(_raw: *const ()) -> Self {
|
||||||
|
EmptyIdaItem
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn raw_as_ref<'a>(_raw: *const ()) -> Self::Ref<'a> {
|
||||||
|
EmptyIdaItemRef {
|
||||||
|
_marker: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// id分配器
|
||||||
|
pub struct IdAllocator {
|
||||||
|
current_id: usize,
|
||||||
|
min_id: usize,
|
||||||
|
max_id: usize,
|
||||||
|
used: usize,
|
||||||
|
xarray: kdepends::xarray::XArray<EmptyIdaItem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IdAllocator {
|
||||||
|
/// 创建一个新的id分配器
|
||||||
|
pub const fn new(initial_id: usize, max_id: usize) -> Option<Self> {
|
||||||
|
if initial_id >= max_id {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(Self {
|
||||||
|
current_id: initial_id,
|
||||||
|
min_id: initial_id,
|
||||||
|
max_id,
|
||||||
|
used: 0,
|
||||||
|
xarray: kdepends::xarray::XArray::new(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 可用的id数量
|
||||||
|
#[inline]
|
||||||
|
pub fn available(&self) -> usize {
|
||||||
|
self.max_id - self.min_id - self.used
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 分配一个新的id
|
||||||
|
///
|
||||||
|
/// ## 返回
|
||||||
|
///
|
||||||
|
/// 如果分配成功,返回Some(id),否则返回None
|
||||||
|
pub fn alloc(&mut self) -> Option<usize> {
|
||||||
|
if unlikely(self.available() == 0) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(try1) = self.do_find_first_free_index(self.current_id, self.max_id) {
|
||||||
|
self.current_id = try1;
|
||||||
|
self.xarray.store(try1 as u64, EmptyIdaItem);
|
||||||
|
self.used += 1;
|
||||||
|
return Some(try1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从头开始找
|
||||||
|
if let Some(try2) =
|
||||||
|
self.do_find_first_free_index(self.min_id, min(self.current_id, self.max_id))
|
||||||
|
{
|
||||||
|
self.current_id = try2;
|
||||||
|
self.xarray.store(try2 as u64, EmptyIdaItem);
|
||||||
|
self.used += 1;
|
||||||
|
return Some(try2);
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 检查id是否存在
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `id`:要检查的id
|
||||||
|
///
|
||||||
|
/// ## 返回
|
||||||
|
///
|
||||||
|
/// 如果id存在,返回true,否则返回false
|
||||||
|
pub fn exists(&self, id: usize) -> bool {
|
||||||
|
if id < self.min_id || id >= self.max_id {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
self.xarray.load(id as u64).is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_find_first_free_index(&self, start_id: usize, end: usize) -> Option<usize> {
|
||||||
|
(start_id..end).find(|&i| !self.exists(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 释放一个id
|
||||||
|
///
|
||||||
|
/// ## 参数
|
||||||
|
///
|
||||||
|
/// - `id`:要释放的id
|
||||||
|
pub fn free(&mut self, id: usize) {
|
||||||
|
if id < self.min_id || id >= self.max_id {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if self.xarray.remove(id as u64).is_some() {
|
||||||
|
self.used -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 返回已经使用的id数量
|
||||||
|
pub fn used(&self) -> usize {
|
||||||
|
self.used
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl core::fmt::Debug for IdAllocator {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
f.debug_struct("IdAllocator")
|
||||||
|
.field("current_id", &self.current_id)
|
||||||
|
.field("min_id", &self.min_id)
|
||||||
|
.field("max_id", &self.max_id)
|
||||||
|
.field("used", &self.used)
|
||||||
|
.field("xarray", &"xarray<()>")
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
#[test]
|
||||||
|
fn test_new_fail() {
|
||||||
|
assert_eq!(IdAllocator::new(10, 10).is_none(), true);
|
||||||
|
assert_eq!(IdAllocator::new(11, 10).is_none(), true);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_new_success() {
|
||||||
|
assert_eq!(IdAllocator::new(9, 10).is_some(), true);
|
||||||
|
assert_eq!(IdAllocator::new(0, 10).is_some(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_id_allocator() {
|
||||||
|
let mut ida = IdAllocator::new(0, 10).unwrap();
|
||||||
|
assert_eq!(ida.alloc(), Some(0));
|
||||||
|
assert_eq!(ida.alloc(), Some(1));
|
||||||
|
assert_eq!(ida.alloc(), Some(2));
|
||||||
|
assert_eq!(ida.alloc(), Some(3));
|
||||||
|
assert_eq!(ida.alloc(), Some(4));
|
||||||
|
assert_eq!(ida.alloc(), Some(5));
|
||||||
|
assert_eq!(ida.alloc(), Some(6));
|
||||||
|
assert_eq!(ida.alloc(), Some(7));
|
||||||
|
assert_eq!(ida.alloc(), Some(8));
|
||||||
|
assert_eq!(ida.alloc(), Some(9));
|
||||||
|
assert_eq!(ida.alloc(), None);
|
||||||
|
|
||||||
|
for i in 0..10 {
|
||||||
|
assert_eq!(ida.exists(i), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
ida.free(5);
|
||||||
|
|
||||||
|
for i in 0..10 {
|
||||||
|
if i == 5 {
|
||||||
|
assert_eq!(ida.exists(i), false);
|
||||||
|
} else {
|
||||||
|
assert_eq!(ida.exists(i), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert_eq!(ida.used(), 9);
|
||||||
|
assert_eq!(ida.alloc(), Some(5));
|
||||||
|
assert_eq!(ida.alloc(), None);
|
||||||
|
|
||||||
|
assert_eq!(ida.used(), 10);
|
||||||
|
for i in 0..10 {
|
||||||
|
ida.free(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(ida.used(), 0);
|
||||||
|
}
|
||||||
|
}
|
@ -7,9 +7,10 @@ description = "需要导出的依赖项(为保持内核依赖版本与调试
|
|||||||
# 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
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ringbuffer = "0.15.0"
|
|
||||||
memoffset = "0.9.0"
|
|
||||||
crc = { path = "../crc" }
|
crc = { path = "../crc" }
|
||||||
|
memoffset = "0.9.0"
|
||||||
|
ringbuffer = "0.15.0"
|
||||||
|
xarray = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/xarray", rev = "de93b57c34", features = ["slab-friendly"] }
|
||||||
|
|
||||||
# 一个无锁MPSC队列
|
# 一个无锁MPSC队列
|
||||||
[dependencies.thingbuf]
|
[dependencies.thingbuf]
|
||||||
|
@ -7,3 +7,4 @@ pub extern crate memoffset;
|
|||||||
pub extern crate ringbuffer;
|
pub extern crate ringbuffer;
|
||||||
|
|
||||||
pub extern crate crc;
|
pub extern crate crc;
|
||||||
|
pub extern crate xarray;
|
||||||
|
@ -4,7 +4,7 @@ use core::sync::atomic::{compiler_fence, Ordering};
|
|||||||
|
|
||||||
use klog_types::{AllocatorLog, AllocatorLogType, LogSource, MMLogChannel};
|
use klog_types::{AllocatorLog, AllocatorLogType, LogSource, MMLogChannel};
|
||||||
|
|
||||||
use crate::{arch::CurrentTimeArch, process::Pid, time::TimeArch};
|
use crate::{arch::CurrentTimeArch, libs::spinlock::SpinLock, process::Pid, time::TimeArch};
|
||||||
|
|
||||||
/// 全局的内存分配器日志通道
|
/// 全局的内存分配器日志通道
|
||||||
///
|
///
|
||||||
@ -16,7 +16,8 @@ static __MM_ALLOCATOR_LOG_CHANNEL: MMLogChannel<{ MMDebugLogManager::MAX_ALLOC_L
|
|||||||
/// 全局的内存分配器日志id分配器
|
/// 全局的内存分配器日志id分配器
|
||||||
///
|
///
|
||||||
/// id从1开始, 因为0是无效的id
|
/// id从1开始, 因为0是无效的id
|
||||||
static __MM_DEBUG_LOG_IDA: ida::IdAllocator = ida::IdAllocator::new(1, usize::MAX);
|
static __MM_DEBUG_LOG_IDA: SpinLock<ida::IdAllocator> =
|
||||||
|
SpinLock::new(ida::IdAllocator::new(1, usize::MAX).unwrap());
|
||||||
|
|
||||||
/// 记录内存分配器的日志
|
/// 记录内存分配器的日志
|
||||||
///
|
///
|
||||||
@ -50,7 +51,7 @@ impl MMDebugLogManager {
|
|||||||
/// - `pid`:日志来源的pid
|
/// - `pid`:日志来源的pid
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn log(log_type: AllocatorLogType, source: LogSource, pid: Option<Pid>) {
|
pub fn log(log_type: AllocatorLogType, source: LogSource, pid: Option<Pid>) {
|
||||||
let id = __MM_DEBUG_LOG_IDA.alloc().unwrap();
|
let id = __MM_DEBUG_LOG_IDA.lock_irqsave().alloc().unwrap();
|
||||||
let log = AllocatorLog::new(
|
let log = AllocatorLog::new(
|
||||||
id as u64,
|
id as u64,
|
||||||
log_type,
|
log_type,
|
||||||
|
@ -27,7 +27,8 @@ use system_error::SystemError;
|
|||||||
use super::{super::device::DeviceState, platform_bus, platform_bus_device, CompatibleTable};
|
use super::{super::device::DeviceState, platform_bus, platform_bus_device, CompatibleTable};
|
||||||
|
|
||||||
/// 平台设备id分配器
|
/// 平台设备id分配器
|
||||||
static PLATFORM_DEVID_IDA: IdAllocator = IdAllocator::new(0, i32::MAX as usize);
|
static PLATFORM_DEVID_IDA: SpinLock<IdAllocator> =
|
||||||
|
SpinLock::new(IdAllocator::new(0, i32::MAX as usize).unwrap());
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn platform_device_manager() -> &'static PlatformDeviceManager {
|
pub fn platform_device_manager() -> &'static PlatformDeviceManager {
|
||||||
@ -93,7 +94,10 @@ impl PlatformDeviceManager {
|
|||||||
pdev.set_name(pdev.pdev_name().to_string());
|
pdev.set_name(pdev.pdev_name().to_string());
|
||||||
}
|
}
|
||||||
PLATFORM_DEVID_AUTO => {
|
PLATFORM_DEVID_AUTO => {
|
||||||
let id = PLATFORM_DEVID_IDA.alloc().ok_or(SystemError::EOVERFLOW)?;
|
let id = PLATFORM_DEVID_IDA
|
||||||
|
.lock()
|
||||||
|
.alloc()
|
||||||
|
.ok_or(SystemError::EOVERFLOW)?;
|
||||||
pdev.set_pdev_id(id as i32);
|
pdev.set_pdev_id(id as i32);
|
||||||
pdev.set_pdev_id_auto(true);
|
pdev.set_pdev_id_auto(true);
|
||||||
pdev.set_name(format!("{}.{}.auto", pdev.pdev_name(), pdev.pdev_id().0));
|
pdev.set_name(format!("{}.{}.auto", pdev.pdev_name(), pdev.pdev_id().0));
|
||||||
@ -112,7 +116,7 @@ impl PlatformDeviceManager {
|
|||||||
// failed
|
// failed
|
||||||
let pdevid = pdev.pdev_id();
|
let pdevid = pdev.pdev_id();
|
||||||
if pdevid.1 {
|
if pdevid.1 {
|
||||||
PLATFORM_DEVID_IDA.free(pdevid.0 as usize);
|
PLATFORM_DEVID_IDA.lock().free(pdevid.0 as usize);
|
||||||
pdev.set_pdev_id(PLATFORM_DEVID_AUTO);
|
pdev.set_pdev_id(PLATFORM_DEVID_AUTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,8 @@ use super::{
|
|||||||
GeneralRtcPriority, RtcClassOps, RtcDevice,
|
GeneralRtcPriority, RtcClassOps, RtcDevice,
|
||||||
};
|
};
|
||||||
|
|
||||||
static RTC_GENERAL_DEVICE_IDA: IdAllocator = IdAllocator::new(0, usize::MAX);
|
static RTC_GENERAL_DEVICE_IDA: SpinLock<IdAllocator> =
|
||||||
|
SpinLock::new(IdAllocator::new(0, usize::MAX).unwrap());
|
||||||
|
|
||||||
pub(super) const RTC_HCTOSYS_DEVICE: &str = "rtc0";
|
pub(super) const RTC_HCTOSYS_DEVICE: &str = "rtc0";
|
||||||
|
|
||||||
@ -63,7 +64,7 @@ impl RtcGeneralDevice {
|
|||||||
///
|
///
|
||||||
/// 注意,由于还需要进行其他的初始化操作,因此这个函数并不是公开的构造函数。
|
/// 注意,由于还需要进行其他的初始化操作,因此这个函数并不是公开的构造函数。
|
||||||
fn new(priority: GeneralRtcPriority) -> Arc<Self> {
|
fn new(priority: GeneralRtcPriority) -> Arc<Self> {
|
||||||
let id = RTC_GENERAL_DEVICE_IDA.alloc().unwrap();
|
let id = RTC_GENERAL_DEVICE_IDA.lock().alloc().unwrap();
|
||||||
let name = format!("rtc{}", id);
|
let name = format!("rtc{}", id);
|
||||||
Arc::new(Self {
|
Arc::new(Self {
|
||||||
name,
|
name,
|
||||||
@ -106,7 +107,7 @@ impl RtcGeneralDevice {
|
|||||||
|
|
||||||
impl Drop for RtcGeneralDevice {
|
impl Drop for RtcGeneralDevice {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
RTC_GENERAL_DEVICE_IDA.free(self.id);
|
RTC_GENERAL_DEVICE_IDA.lock().free(self.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ use crate::{
|
|||||||
vfs::syscall::ModeType,
|
vfs::syscall::ModeType,
|
||||||
},
|
},
|
||||||
init::initcall::INITCALL_CORE,
|
init::initcall::INITCALL_CORE,
|
||||||
|
libs::spinlock::SpinLock,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{VirtIODevice, VirtIODeviceIndex, VirtIODriver, VIRTIO_DEV_ANY_ID};
|
use super::{VirtIODevice, VirtIODeviceIndex, VirtIODriver, VIRTIO_DEV_ANY_ID};
|
||||||
@ -255,7 +256,7 @@ pub struct VirtIODeviceIndexManager {
|
|||||||
// ID分配器
|
// ID分配器
|
||||||
///
|
///
|
||||||
/// ID分配器用于分配唯一的索引给VirtIO设备。
|
/// ID分配器用于分配唯一的索引给VirtIO设备。
|
||||||
ida: IdAllocator,
|
ida: SpinLock<IdAllocator>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// VirtIO设备索引管理器的新建实例
|
// VirtIO设备索引管理器的新建实例
|
||||||
@ -265,7 +266,7 @@ impl VirtIODeviceIndexManager {
|
|||||||
/// 创建一个新的VirtIO设备索引管理器实例,初始时分配器从0开始,直到最大usize值。
|
/// 创建一个新的VirtIO设备索引管理器实例,初始时分配器从0开始,直到最大usize值。
|
||||||
const fn new() -> Self {
|
const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
ida: IdAllocator::new(0, usize::MAX),
|
ida: SpinLock::new(IdAllocator::new(0, usize::MAX).unwrap()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,7 +274,7 @@ impl VirtIODeviceIndexManager {
|
|||||||
///
|
///
|
||||||
/// 分配一个唯一的索引给VirtIO设备。
|
/// 分配一个唯一的索引给VirtIO设备。
|
||||||
pub fn alloc(&self) -> VirtIODeviceIndex {
|
pub fn alloc(&self) -> VirtIODeviceIndex {
|
||||||
VirtIODeviceIndex(self.ida.alloc().unwrap())
|
VirtIODeviceIndex(self.ida.lock().alloc().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
// 释放一个VirtIO设备索引
|
// 释放一个VirtIO设备索引
|
||||||
@ -281,7 +282,7 @@ impl VirtIODeviceIndexManager {
|
|||||||
/// 释放之前分配的VirtIO设备索引,使其可以被重新使用。
|
/// 释放之前分配的VirtIO设备索引,使其可以被重新使用。
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn free(&self, index: VirtIODeviceIndex) {
|
pub fn free(&self, index: VirtIODeviceIndex) {
|
||||||
self.ida.free(index.0);
|
self.ida.lock().free(index.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ const PTY_NR_LIMIT: usize = 4096;
|
|||||||
pub struct DevPtsFs {
|
pub struct DevPtsFs {
|
||||||
/// 根节点
|
/// 根节点
|
||||||
root_inode: Arc<LockedDevPtsFSInode>,
|
root_inode: Arc<LockedDevPtsFSInode>,
|
||||||
pts_ida: IdAllocator,
|
pts_ida: SpinLock<IdAllocator>,
|
||||||
pts_count: AtomicU32,
|
pts_count: AtomicU32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ impl DevPtsFs {
|
|||||||
let root_inode = Arc::new(LockedDevPtsFSInode::new());
|
let root_inode = Arc::new(LockedDevPtsFSInode::new());
|
||||||
let ret = Arc::new(Self {
|
let ret = Arc::new(Self {
|
||||||
root_inode,
|
root_inode,
|
||||||
pts_ida: IdAllocator::new(1, NR_UNIX98_PTY_MAX as usize),
|
pts_ida: SpinLock::new(IdAllocator::new(1, NR_UNIX98_PTY_MAX as usize).unwrap()),
|
||||||
pts_count: AtomicU32::new(0),
|
pts_count: AtomicU32::new(0),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ impl DevPtsFs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn alloc_index(&self) -> Result<usize, SystemError> {
|
pub fn alloc_index(&self) -> Result<usize, SystemError> {
|
||||||
self.pts_ida.alloc().ok_or(SystemError::ENOSPC)
|
self.pts_ida.lock().alloc().ok_or(SystemError::ENOSPC)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,8 @@ use core::any::Any;
|
|||||||
use ida::IdAllocator;
|
use ida::IdAllocator;
|
||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
|
|
||||||
static EVENTFD_ID_ALLOCATOR: IdAllocator = IdAllocator::new(0, u32::MAX as usize);
|
static EVENTFD_ID_ALLOCATOR: SpinLock<IdAllocator> =
|
||||||
|
SpinLock::new(IdAllocator::new(0, u32::MAX as usize).unwrap());
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
pub struct EventFdFlags: u32{
|
pub struct EventFdFlags: u32{
|
||||||
@ -251,7 +252,10 @@ impl Syscall {
|
|||||||
/// See: https://man7.org/linux/man-pages/man2/eventfd2.2.html
|
/// See: https://man7.org/linux/man-pages/man2/eventfd2.2.html
|
||||||
pub fn sys_eventfd(init_val: u32, flags: u32) -> Result<usize, SystemError> {
|
pub fn sys_eventfd(init_val: u32, flags: u32) -> Result<usize, SystemError> {
|
||||||
let flags = EventFdFlags::from_bits(flags).ok_or(SystemError::EINVAL)?;
|
let flags = EventFdFlags::from_bits(flags).ok_or(SystemError::EINVAL)?;
|
||||||
let id = EVENTFD_ID_ALLOCATOR.alloc().ok_or(SystemError::ENOMEM)? as u32;
|
let id = EVENTFD_ID_ALLOCATOR
|
||||||
|
.lock()
|
||||||
|
.alloc()
|
||||||
|
.ok_or(SystemError::ENOMEM)? as u32;
|
||||||
let eventfd = EventFd::new(init_val as u64, flags, id);
|
let eventfd = EventFd::new(init_val as u64, flags, id);
|
||||||
let inode = Arc::new(EventFdInode::new(eventfd));
|
let inode = Arc::new(EventFdInode::new(eventfd));
|
||||||
let filemode = if flags.contains(EventFdFlags::EFD_CLOEXEC) {
|
let filemode = if flags.contains(EventFdFlags::EFD_CLOEXEC) {
|
||||||
|
@ -5,9 +5,9 @@ use alloc::{
|
|||||||
sync::{Arc, Weak},
|
sync::{Arc, Weak},
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
|
use kdepends::xarray::XArray;
|
||||||
use log::error;
|
use log::error;
|
||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
use xarray::XArray;
|
|
||||||
|
|
||||||
use super::{Dirent, FileType, IndexNode, InodeId, Metadata, SpecialNodeData};
|
use super::{Dirent, FileType, IndexNode, InodeId, Metadata, SpecialNodeData};
|
||||||
use crate::filesystem::eventfd::EventFdInode;
|
use crate::filesystem::eventfd::EventFdInode;
|
||||||
|
@ -125,7 +125,7 @@ pub struct ShmManager {
|
|||||||
impl ShmManager {
|
impl ShmManager {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
ShmManager {
|
ShmManager {
|
||||||
id_allocator: IdAllocator::new(0, usize::MAX - 1),
|
id_allocator: IdAllocator::new(0, usize::MAX - 1).unwrap(),
|
||||||
id2shm: HashMap::new(),
|
id2shm: HashMap::new(),
|
||||||
key2id: HashMap::new(),
|
key2id: HashMap::new(),
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#![feature(concat_idents)]
|
#![feature(concat_idents)]
|
||||||
#![feature(const_for)]
|
#![feature(const_for)]
|
||||||
#![feature(const_mut_refs)]
|
#![feature(const_mut_refs)]
|
||||||
|
#![feature(const_option)]
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![feature(const_refs_to_cell)]
|
#![feature(const_refs_to_cell)]
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
|
@ -1,52 +0,0 @@
|
|||||||
#![no_std]
|
|
||||||
#![feature(core_intrinsics)]
|
|
||||||
#![allow(internal_features)]
|
|
||||||
#![allow(clippy::needless_return)]
|
|
||||||
|
|
||||||
use core::intrinsics::unlikely;
|
|
||||||
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
|
||||||
|
|
||||||
/// id分配器
|
|
||||||
///
|
|
||||||
/// TODO: 当前只是为了简单实现功能,将来这里应使用类似linux的ida的方式去实现
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct IdAllocator {
|
|
||||||
current_id: AtomicUsize,
|
|
||||||
max_id: usize,
|
|
||||||
dead: AtomicBool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IdAllocator {
|
|
||||||
/// 创建一个新的id分配器
|
|
||||||
pub const fn new(initial_id: usize, max_id: usize) -> Self {
|
|
||||||
Self {
|
|
||||||
current_id: AtomicUsize::new(initial_id),
|
|
||||||
max_id,
|
|
||||||
dead: AtomicBool::new(false),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 分配一个新的id
|
|
||||||
///
|
|
||||||
/// ## 返回
|
|
||||||
///
|
|
||||||
/// 如果分配成功,返回Some(id),否则返回None
|
|
||||||
pub fn alloc(&self) -> Option<usize> {
|
|
||||||
if unlikely(self.dead.load(Ordering::SeqCst)) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let ret = self.current_id.fetch_add(1, Ordering::SeqCst);
|
|
||||||
// 如果id溢出,panic
|
|
||||||
if ret == self.max_id {
|
|
||||||
self.dead.store(true, Ordering::SeqCst);
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Some(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn free(&self, _id: usize) {
|
|
||||||
// todo: free
|
|
||||||
}
|
|
||||||
}
|
|
@ -54,7 +54,8 @@ use super::{
|
|||||||
pub const DEFAULT_MMAP_MIN_ADDR: usize = 65536;
|
pub const DEFAULT_MMAP_MIN_ADDR: usize = 65536;
|
||||||
|
|
||||||
/// LockedVMA的id分配器
|
/// LockedVMA的id分配器
|
||||||
static LOCKEDVMA_ID_ALLOCATOR: IdAllocator = IdAllocator::new(0, usize::MAX);
|
static LOCKEDVMA_ID_ALLOCATOR: SpinLock<IdAllocator> =
|
||||||
|
SpinLock::new(IdAllocator::new(0, usize::MAX).unwrap());
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AddressSpace {
|
pub struct AddressSpace {
|
||||||
@ -1097,7 +1098,7 @@ impl Eq for LockedVMA {}
|
|||||||
impl LockedVMA {
|
impl LockedVMA {
|
||||||
pub fn new(vma: VMA) -> Arc<Self> {
|
pub fn new(vma: VMA) -> Arc<Self> {
|
||||||
let r = Arc::new(Self {
|
let r = Arc::new(Self {
|
||||||
id: LOCKEDVMA_ID_ALLOCATOR.alloc().unwrap(),
|
id: LOCKEDVMA_ID_ALLOCATOR.lock().alloc().unwrap(),
|
||||||
vma: SpinLock::new(vma),
|
vma: SpinLock::new(vma),
|
||||||
});
|
});
|
||||||
r.vma.lock_irqsave().self_ref = Arc::downgrade(&r);
|
r.vma.lock_irqsave().self_ref = Arc::downgrade(&r);
|
||||||
@ -1316,7 +1317,7 @@ impl LockedVMA {
|
|||||||
|
|
||||||
impl Drop for LockedVMA {
|
impl Drop for LockedVMA {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
LOCKEDVMA_ID_ALLOCATOR.free(self.id);
|
LOCKEDVMA_ID_ALLOCATOR.lock().free(self.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
use ida::IdAllocator;
|
use ida::IdAllocator;
|
||||||
use smoltcp::iface::SocketHandle;
|
use smoltcp::iface::SocketHandle;
|
||||||
|
|
||||||
|
use crate::libs::spinlock::SpinLock;
|
||||||
|
|
||||||
int_like!(KernelHandle, usize);
|
int_like!(KernelHandle, usize);
|
||||||
|
|
||||||
/// # socket的句柄管理组件
|
/// # socket的句柄管理组件
|
||||||
@ -12,7 +14,8 @@ pub enum GlobalSocketHandle {
|
|||||||
Kernel(KernelHandle),
|
Kernel(KernelHandle),
|
||||||
}
|
}
|
||||||
|
|
||||||
static KERNEL_HANDLE_IDA: IdAllocator = IdAllocator::new(0, usize::MAX);
|
static KERNEL_HANDLE_IDA: SpinLock<IdAllocator> =
|
||||||
|
SpinLock::new(IdAllocator::new(0, usize::MAX).unwrap());
|
||||||
|
|
||||||
impl GlobalSocketHandle {
|
impl GlobalSocketHandle {
|
||||||
pub fn new_smoltcp_handle(handle: SocketHandle) -> Self {
|
pub fn new_smoltcp_handle(handle: SocketHandle) -> Self {
|
||||||
@ -20,7 +23,7 @@ impl GlobalSocketHandle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_kernel_handle() -> Self {
|
pub fn new_kernel_handle() -> Self {
|
||||||
return Self::Kernel(KernelHandle::new(KERNEL_HANDLE_IDA.alloc().unwrap()));
|
return Self::Kernel(KernelHandle::new(KERNEL_HANDLE_IDA.lock().alloc().unwrap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn smoltcp_handle(&self) -> Option<SocketHandle> {
|
pub fn smoltcp_handle(&self) -> Option<SocketHandle> {
|
||||||
|
Reference in New Issue
Block a user