Introduce HandleMap helper type

This commit is contained in:
bjorn3
2026-04-13 20:51:24 +02:00
parent f673afa839
commit 219d707362
8 changed files with 141 additions and 284 deletions
+20 -48
View File
@@ -1,11 +1,6 @@
use core::{
convert::TryInto,
sync::atomic::{self, AtomicUsize},
};
use alloc::{boxed::Box, vec::Vec};
use core::convert::TryInto;
use hashbrown::{hash_map::DefaultHashBuilder, HashMap};
use spin::{Mutex, Once};
use syscall::{
data::GlobalSchemes,
@@ -30,7 +25,7 @@ use crate::syscall::{
usercopy::UserSliceWo,
};
use super::{CallerCtx, KernelScheme, OpenResult, SchemeExt, StrOrBytes};
use super::{CallerCtx, HandleMap, KernelScheme, OpenResult, SchemeExt, StrOrBytes};
/// A scheme used to access the RSDT or XSDT, which is needed for e.g. `acpid` to function.
pub struct AcpiScheme;
@@ -48,9 +43,7 @@ enum HandleKind {
SchemeRoot,
}
static HANDLES: RwLock<L1, HashMap<usize, Handle>> =
RwLock::new(HashMap::with_hasher(DefaultHashBuilder::new()));
static NEXT_FD: AtomicUsize = AtomicUsize::new(0);
static HANDLES: RwLock<L1, HandleMap<Handle>> = RwLock::new(HandleMap::new());
static DATA: Once<Box<[u8]>> = Once::new();
@@ -116,16 +109,10 @@ impl AcpiScheme {
impl KernelScheme for AcpiScheme {
fn scheme_root(&self, token: &mut CleanLockToken) -> Result<usize> {
let fd = NEXT_FD.fetch_add(1, atomic::Ordering::Relaxed);
let mut handles_guard = HANDLES.write(token.token());
let _ = handles_guard.insert(
fd,
Handle {
kind: HandleKind::SchemeRoot,
stat: false,
},
);
let fd = HANDLES.write(token.token()).insert(Handle {
kind: HandleKind::SchemeRoot,
stat: false,
});
Ok(fd)
}
@@ -139,11 +126,7 @@ impl KernelScheme for AcpiScheme {
token: &mut CleanLockToken,
) -> Result<OpenResult> {
if !matches!(
HANDLES
.read(token.token())
.get(&id)
.ok_or(Error::new(EBADF))?
.kind,
HANDLES.read(token.token()).get(id)?.kind,
HandleKind::SchemeRoot
) {
return Err(Error::new(EACCES));
@@ -189,23 +172,17 @@ impl KernelScheme for AcpiScheme {
_ => return Err(Error::new(ENOENT)),
};
let fd = NEXT_FD.fetch_add(1, atomic::Ordering::Relaxed);
let mut handles_guard = HANDLES.write(token.token());
let _ = handles_guard.insert(
fd,
Handle {
kind: handle_kind,
// TODO: Redundant
stat: flags & O_STAT == O_STAT,
},
);
let fd = HANDLES.write(token.token()).insert(Handle {
kind: handle_kind,
// TODO: Redundant
stat: flags & O_STAT == O_STAT,
});
Ok(OpenResult::SchemeLocal(fd, int_flags))
}
fn fsize(&self, id: usize, token: &mut CleanLockToken) -> Result<u64> {
let mut handles = HANDLES.write(token.token());
let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
let handle = handles.get_mut(id)?;
if handle.stat {
return Err(Error::new(EBADF));
@@ -226,7 +203,7 @@ impl KernelScheme for AcpiScheme {
token: &mut CleanLockToken,
) -> Result<EventFlags> {
let handles = HANDLES.read(token.token());
let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
let handle = handles.get(id)?;
if handle.stat {
return Err(Error::new(EBADF));
@@ -235,9 +212,7 @@ impl KernelScheme for AcpiScheme {
Ok(EventFlags::empty())
}
fn close(&self, id: usize, token: &mut CleanLockToken) -> Result<()> {
if HANDLES.write(token.token()).remove(&id).is_none() {
return Err(Error::new(EBADF));
}
HANDLES.write(token.token()).remove(id)?;
Ok(())
}
fn kreadoff(
@@ -253,10 +228,7 @@ impl KernelScheme for AcpiScheme {
return Ok(0);
};
let handle = {
let handles = HANDLES.read(token.token());
*handles.get(&id).ok_or(Error::new(EBADF))?
};
let handle = *HANDLES.read(token.token()).get(id)?;
if handle.stat {
return Err(Error::new(EBADF));
@@ -301,10 +273,10 @@ impl KernelScheme for AcpiScheme {
opaque: u64,
token: &mut CleanLockToken,
) -> Result<usize> {
let Some(Handle {
let Handle {
kind: HandleKind::TopLevel,
..
}) = HANDLES.read(token.token()).get(&id)
} = HANDLES.read(token.token()).get(id)?
else {
return Err(Error::new(ENOTDIR));
};
@@ -334,7 +306,7 @@ impl KernelScheme for AcpiScheme {
}
fn kfstat(&self, id: usize, buf: UserSliceWo, token: &mut CleanLockToken) -> Result<()> {
let handles = HANDLES.read(token.token());
let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
let handle = handles.get(id)?;
buf.copy_exactly(&match handle.kind {
HandleKind::Rxsdt => {
+12 -45
View File
@@ -1,4 +1,3 @@
use core::sync::atomic::{AtomicUsize, Ordering};
use syscall::data::GlobalSchemes;
use crate::{
@@ -13,8 +12,6 @@ use crate::{
},
};
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
/// Input queue
static INPUT: WaitQueue<u8> = WaitQueue::new();
@@ -23,8 +20,7 @@ struct Handle {
num: usize,
}
static HANDLES: RwLock<L1, HashMap<usize, Handle>> =
RwLock::new(HashMap::with_hasher(DefaultHashBuilder::new()));
static HANDLES: RwLock<L1, HandleMap<Handle>> = RwLock::new(HandleMap::new());
/// Add to the input queue
pub fn debug_input(data: u8, token: &mut CleanLockToken) {
@@ -56,13 +52,9 @@ enum SpecialFds {
impl KernelScheme for DebugScheme {
fn scheme_root(&self, token: &mut CleanLockToken) -> Result<usize> {
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
HANDLES.write(token.token()).insert(
id,
Handle {
num: SpecialFds::SchemeRoot as usize,
},
);
let id = HANDLES.write(token.token()).insert(Handle {
num: SpecialFds::SchemeRoot as usize,
});
Ok(id)
}
@@ -75,13 +67,7 @@ impl KernelScheme for DebugScheme {
ctx: CallerCtx,
token: &mut CleanLockToken,
) -> Result<OpenResult> {
if HANDLES
.read(token.token())
.get(&id)
.ok_or(Error::new(EBADF))?
.num
!= SpecialFds::SchemeRoot as usize
{
if HANDLES.read(token.token()).get(id)?.num != SpecialFds::SchemeRoot as usize {
return Err(Error::new(EACCES));
}
@@ -112,8 +98,7 @@ impl KernelScheme for DebugScheme {
_ => return Err(Error::new(ENOENT)),
};
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
HANDLES.write(token.token()).insert(id, Handle { num });
let id = HANDLES.write(token.token()).insert(Handle { num });
Ok(OpenResult::SchemeLocal(id, InternalFlags::empty()))
}
@@ -124,28 +109,19 @@ impl KernelScheme for DebugScheme {
_flags: EventFlags,
token: &mut CleanLockToken,
) -> Result<EventFlags> {
let _handle = {
let handles = HANDLES.read(token.token());
*handles.get(&id).ok_or(Error::new(EBADF))?
};
let _handle = *HANDLES.read(token.token()).get(id)?;
Ok(EventFlags::empty())
}
fn fsync(&self, id: usize, token: &mut CleanLockToken) -> Result<()> {
let _handle = {
let handles = HANDLES.read(token.token());
*handles.get(&id).ok_or(Error::new(EBADF))?
};
let _handle = *HANDLES.read(token.token()).get(id)?;
Ok(())
}
fn close(&self, id: usize, token: &mut CleanLockToken) -> Result<()> {
let _handle = {
let mut handles = HANDLES.write(token.token());
handles.remove(&id).ok_or(Error::new(EBADF))?
};
HANDLES.write(token.token()).remove(id)?;
Ok(())
}
@@ -157,10 +133,7 @@ impl KernelScheme for DebugScheme {
_stored_flags: u32,
token: &mut CleanLockToken,
) -> Result<usize> {
let handle = {
let handles = HANDLES.read(token.token());
*handles.get(&id).ok_or(Error::new(EBADF))?
};
let handle = *HANDLES.read(token.token()).get(id)?;
if handle.num == SpecialFds::DisableGraphicalDebug as usize
|| handle.num == SpecialFds::SchemeRoot as usize
@@ -200,10 +173,7 @@ impl KernelScheme for DebugScheme {
_stored_flags: u32,
token: &mut CleanLockToken,
) -> Result<usize> {
let handle = {
let handles = HANDLES.read(token.token());
*handles.get(&id).ok_or(Error::new(EBADF))?
};
let handle = *HANDLES.read(token.token()).get(id)?;
#[cfg(feature = "profiling")]
if handle.num == SpecialFds::CtlProfiling as usize {
@@ -248,10 +218,7 @@ impl KernelScheme for DebugScheme {
Ok(buf.len())
}
fn kfpath(&self, id: usize, buf: UserSliceWo, token: &mut CleanLockToken) -> Result<usize> {
let handle = {
let handles = HANDLES.read(token.token());
*handles.get(&id).ok_or(Error::new(EBADF))?
};
let handle = *HANDLES.read(token.token()).get(id)?;
if handle.num != SpecialFds::Default as usize
&& handle.num != SpecialFds::NoPreserve as usize
{
+15 -40
View File
@@ -1,10 +1,7 @@
use core::sync::atomic::{self, AtomicUsize};
use alloc::boxed::Box;
use hashbrown::{hash_map::DefaultHashBuilder, HashMap};
use spin::Once;
use super::{CallerCtx, KernelScheme, OpenResult, StrOrBytes};
use super::{CallerCtx, HandleMap, KernelScheme, OpenResult, StrOrBytes};
use crate::{
dtb::DTB_BINARY,
scheme::InternalFlags,
@@ -30,9 +27,7 @@ struct Handle {
stat: bool,
}
static HANDLES: RwLock<L1, HashMap<usize, Handle>> =
RwLock::new(HashMap::with_hasher(DefaultHashBuilder::new()));
static NEXT_FD: AtomicUsize = AtomicUsize::new(0);
static HANDLES: RwLock<L1, HandleMap<Handle>> = RwLock::new(HandleMap::new());
static DATA: Once<Box<[u8]>> = Once::new();
impl DtbScheme {
@@ -53,17 +48,10 @@ impl DtbScheme {
impl KernelScheme for DtbScheme {
fn scheme_root(&self, token: &mut CleanLockToken) -> Result<usize> {
let id = NEXT_FD.fetch_add(1, atomic::Ordering::Relaxed);
let mut handles_guard = HANDLES.write(token.token());
let _ = handles_guard.insert(
id,
Handle {
kind: HandleKind::SchemeRoot,
stat: false,
},
);
let id = HANDLES.write(token.token()).insert(Handle {
kind: HandleKind::SchemeRoot,
stat: false,
});
Ok(id)
}
fn kopenat(
@@ -76,11 +64,7 @@ impl KernelScheme for DtbScheme {
token: &mut CleanLockToken,
) -> Result<OpenResult> {
if !matches!(
HANDLES
.read(token.token())
.get(&id)
.ok_or(Error::new(EBADF))?
.kind,
HANDLES.read(token.token()).get(id)?.kind,
HandleKind::SchemeRoot
) {
return Err(Error::new(EACCES));
@@ -92,17 +76,10 @@ impl KernelScheme for DtbScheme {
.trim_matches('/');
if path.is_empty() {
let id = NEXT_FD.fetch_add(1, atomic::Ordering::Relaxed);
let mut handles_guard = HANDLES.write(token.token());
let _ = handles_guard.insert(
id,
Handle {
kind: HandleKind::RawData,
stat: _flags & O_STAT == O_STAT,
},
);
let id = HANDLES.write(token.token()).insert(Handle {
kind: HandleKind::RawData,
stat: _flags & O_STAT == O_STAT,
});
return Ok(OpenResult::SchemeLocal(id, InternalFlags::POSITIONED));
}
@@ -111,7 +88,7 @@ impl KernelScheme for DtbScheme {
fn fsize(&self, id: usize, token: &mut CleanLockToken) -> Result<u64> {
let mut handles = HANDLES.write(token.token());
let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
let handle = handles.get_mut(id)?;
if handle.stat {
return Err(Error::new(EBADF));
@@ -126,9 +103,7 @@ impl KernelScheme for DtbScheme {
}
fn close(&self, id: usize, token: &mut CleanLockToken) -> Result<()> {
if HANDLES.write(token.token()).remove(&id).is_none() {
return Err(Error::new(EBADF));
}
HANDLES.write(token.token()).remove(id)?;
Ok(())
}
@@ -142,7 +117,7 @@ impl KernelScheme for DtbScheme {
token: &mut CleanLockToken,
) -> Result<usize> {
let mut handles = HANDLES.write(token.token());
let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
let handle = handles.get_mut(id)?;
if handle.stat {
return Err(Error::new(EBADF));
@@ -168,7 +143,7 @@ impl KernelScheme for DtbScheme {
fn kfstat(&self, id: usize, buf: UserSliceWo, token: &mut CleanLockToken) -> Result<()> {
let handles = HANDLES.read(token.token());
let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
let handle = handles.get(id)?;
buf.copy_exactly(&match handle.kind {
HandleKind::RawData => {
let data = DATA.get().ok_or(Error::new(EBADFD))?;
+12 -22
View File
@@ -1,15 +1,13 @@
// TODO: Rewrite this entire scheme. Legacy x86 APIs should be abstracted by a userspace scheme,
// this scheme should only handle raw IRQ registration and delivery to userspace.
use alloc::{borrow::ToOwned, string::String, vec::Vec};
use core::{
str,
str::FromStr,
sync::atomic::{AtomicUsize, Ordering},
};
use alloc::{borrow::ToOwned, string::String, vec::Vec};
use hashbrown::{hash_map::DefaultHashBuilder, HashMap};
use smallvec::SmallVec;
use spin::{Mutex, Once};
use syscall::{
@@ -19,7 +17,7 @@ use syscall::{
use crate::context::file::InternalFlags;
use super::{CallerCtx, OpenResult, SchemeExt, StrOrBytes};
use super::{CallerCtx, HandleMap, OpenResult, SchemeExt, StrOrBytes};
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
use crate::arch::interrupt::{available_irqs_iter, irq::acknowledge, is_reserved, set_reserved};
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
@@ -39,8 +37,7 @@ use crate::{
///
/// IRQ queues
pub(super) static COUNTS: Mutex<[usize; 224]> = Mutex::new([0; 224]);
static HANDLES: RwLock<L1, HashMap<usize, Handle>> =
RwLock::new(HashMap::with_hasher(DefaultHashBuilder::new()));
static HANDLES: RwLock<L1, HandleMap<Handle>> = RwLock::new(HandleMap::new());
/// These are IRQs 0..=15 (corresponding to interrupt vectors 32..=47). They are opened without the
/// O_CREAT flag.
@@ -95,7 +92,6 @@ impl Handle {
}
}
static NEXT_FD: AtomicUsize = AtomicUsize::new(1);
static CPUS: Once<Vec<u8>> = Once::new();
pub struct IrqScheme;
@@ -220,8 +216,7 @@ const fn vector_to_irq(vector: u8) -> u8 {
impl crate::scheme::KernelScheme for IrqScheme {
fn scheme_root(&self, token: &mut CleanLockToken) -> Result<usize> {
let id = NEXT_FD.fetch_add(1, Ordering::Relaxed);
HANDLES.write(token.token()).insert(id, Handle::SchemeRoot);
let id = HANDLES.write(token.token()).insert(Handle::SchemeRoot);
Ok(id)
}
fn kopenat(
@@ -235,7 +230,7 @@ impl crate::scheme::KernelScheme for IrqScheme {
) -> Result<OpenResult> {
{
let handles = HANDLES.read(token.token());
let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
let handle = handles.get(id)?;
if !matches!(handle, Handle::SchemeRoot) {
return Err(Error::new(EACCES));
@@ -327,8 +322,7 @@ impl crate::scheme::KernelScheme for IrqScheme {
} else {
return Err(Error::new(ENOENT));
};
let fd = NEXT_FD.fetch_add(1, Ordering::Relaxed);
HANDLES.write(token.token()).insert(fd, handle);
let fd = HANDLES.write(token.token()).insert(handle);
Ok(OpenResult::SchemeLocal(fd, int_flags))
}
fn getdents(
@@ -348,11 +342,7 @@ impl crate::scheme::KernelScheme for IrqScheme {
let mut buf = DirentBuf::new(buf, header_size).ok_or(Error::new(EIO))?;
let mut intermediate = String::new();
match *HANDLES
.read(token.token())
.get(&id)
.ok_or(Error::new(EBADF))?
{
match *HANDLES.read(token.token()).get(id)? {
Handle::TopLevel => {
let cpus = CPUS.get().expect("IRQ scheme not initialized");
@@ -423,7 +413,7 @@ impl crate::scheme::KernelScheme for IrqScheme {
fn close(&self, id: usize, token: &mut CleanLockToken) -> Result<()> {
let handles_guard = HANDLES.read(token.token());
let handle = handles_guard.get(&id).ok_or(Error::new(EBADF))?;
let handle = handles_guard.get(id)?;
if let &Handle::Irq {
irq: handle_irq, ..
@@ -443,7 +433,7 @@ impl crate::scheme::KernelScheme for IrqScheme {
token: &mut CleanLockToken,
) -> Result<usize> {
let handles_guard = HANDLES.read(token.token());
let handle = handles_guard.get(&file).ok_or(Error::new(EBADF))?;
let handle = handles_guard.get(file)?;
match handle {
&Handle::Irq {
@@ -471,7 +461,7 @@ impl crate::scheme::KernelScheme for IrqScheme {
fn kfstat(&self, id: usize, buf: UserSliceWo, token: &mut CleanLockToken) -> Result<()> {
let handles_guard = HANDLES.read(token.token());
let handle = handles_guard.get(&id).ok_or(Error::new(EBADF))?;
let handle = handles_guard.get(id)?;
buf.copy_exactly(&match *handle {
Handle::Irq {
@@ -522,7 +512,7 @@ impl crate::scheme::KernelScheme for IrqScheme {
}
fn kfpath(&self, id: usize, buf: UserSliceWo, token: &mut CleanLockToken) -> Result<usize> {
let handles_guard = HANDLES.read(token.token());
let handle = handles_guard.get(&id).ok_or(Error::new(EBADF))?;
let handle = handles_guard.get(id)?;
let scheme_path = match handle {
Handle::Irq { irq, .. } => format!("irq:{}", irq),
@@ -546,7 +536,7 @@ impl crate::scheme::KernelScheme for IrqScheme {
token: &mut CleanLockToken,
) -> Result<usize> {
let handles_guard = HANDLES.read(token.token());
let handle = handles_guard.get(&file).ok_or(Error::new(EBADF))?;
let handle = handles_guard.get(file)?;
match *handle {
// Ensures that the length of the buffer is larger than the size of a usize
+38 -1
View File
@@ -16,7 +16,7 @@ use core::{
str,
sync::atomic::{AtomicUsize, Ordering},
};
use hashbrown::hash_map::{DefaultHashBuilder, HashMap};
use hashbrown::hash_map::{self, DefaultHashBuilder, HashMap};
use spin::Once;
use syscall::{
data::{GlobalSchemes, NewFdParams, StdFsCallMeta},
@@ -125,6 +125,43 @@ impl<'a> StrOrBytes<'a> {
}
}
struct HandleMap<T> {
handles: HashMap<usize, T>,
next_id: usize,
}
impl<T> HandleMap<T> {
const fn new() -> Self {
HandleMap {
handles: HashMap::with_hasher(DefaultHashBuilder::new()),
next_id: 1,
}
}
fn insert(&mut self, handle: T) -> usize {
let id = self.next_id;
self.next_id += 1;
self.handles.insert(id, handle);
id
}
fn remove(&mut self, id: usize) -> Result<T> {
self.handles.remove(&id).ok_or(Error::new(EBADF))
}
fn get(&self, id: usize) -> Result<&T> {
self.handles.get(&id).ok_or(Error::new(EBADF))
}
fn get_mut(&mut self, id: usize) -> Result<&mut T> {
self.handles.get_mut(&id).ok_or(Error::new(EBADF))
}
fn iter(&self) -> hash_map::Iter<'_, usize, T> {
self.handles.iter()
}
}
enum Handle {
SchemeCreationCapability,
Scheme(KernelSchemes),
+13 -36
View File
@@ -1,8 +1,6 @@
//! PS/2 unfortunately requires a kernel driver to prevent race conditions due
//! to how status is utilized
use core::sync::atomic::{AtomicUsize, Ordering};
use hashbrown::{hash_map::DefaultHashBuilder, HashMap};
use syscall::data::GlobalSchemes;
use crate::{
@@ -15,8 +13,6 @@ use crate::{
},
};
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
use super::StrOrBytes;
/// Input queue
@@ -33,8 +29,7 @@ struct Handle {
kind: HandleKind,
}
static HANDLES: RwLock<L1, HashMap<usize, Handle>> =
RwLock::new(HashMap::with_hasher(DefaultHashBuilder::new()));
static HANDLES: RwLock<L1, HandleMap<Handle>> = RwLock::new(HandleMap::new());
/// Add to the input queue
pub fn serio_input(index: usize, data: u8, token: &mut CleanLockToken) {
@@ -59,13 +54,9 @@ pub struct SerioScheme;
impl KernelScheme for SerioScheme {
fn scheme_root(&self, token: &mut CleanLockToken) -> Result<usize> {
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
HANDLES.write(token.token()).insert(
id,
Handle {
kind: HandleKind::SchemeRoot,
},
);
let id = HANDLES.write(token.token()).insert(Handle {
kind: HandleKind::SchemeRoot,
});
Ok(id)
}
@@ -80,7 +71,7 @@ impl KernelScheme for SerioScheme {
) -> Result<OpenResult> {
{
let handles = HANDLES.read(token.token());
let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
let handle = handles.get(id)?;
if !matches!(handle.kind, HandleKind::SchemeRoot) {
return Err(Error::new(EACCES));
@@ -97,13 +88,9 @@ impl KernelScheme for SerioScheme {
return Err(Error::new(ENOENT));
}
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
HANDLES.write(token.token()).insert(
id,
Handle {
kind: HandleKind::Device(index),
},
);
let id = HANDLES.write(token.token()).insert(Handle {
kind: HandleKind::Device(index),
});
Ok(OpenResult::SchemeLocal(id, InternalFlags::empty()))
}
@@ -115,7 +102,7 @@ impl KernelScheme for SerioScheme {
token: &mut CleanLockToken,
) -> Result<EventFlags> {
let handles = HANDLES.read(token.token());
let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
let handle = handles.get(id)?;
if let HandleKind::Device(_) = handle.kind {
Ok(EventFlags::empty())
@@ -125,16 +112,12 @@ impl KernelScheme for SerioScheme {
}
fn fsync(&self, id: usize, token: &mut CleanLockToken) -> Result<()> {
let handles = HANDLES.read(token.token());
handles.get(&id).ok_or(Error::new(EBADF))?;
HANDLES.read(token.token()).get(id)?;
Ok(())
}
fn close(&self, id: usize, token: &mut CleanLockToken) -> Result<()> {
HANDLES
.write(token.token())
.remove(&id)
.ok_or(Error::new(EBADF))?;
HANDLES.write(token.token()).remove(id)?;
Ok(())
}
@@ -146,10 +129,7 @@ impl KernelScheme for SerioScheme {
_stored_flags: u32,
token: &mut CleanLockToken,
) -> Result<usize> {
let handle = {
let handles = HANDLES.read(token.token());
*handles.get(&id).ok_or(Error::new(EBADF))?
};
let handle = *HANDLES.read(token.token()).get(id)?;
let index = match handle.kind {
HandleKind::Device(index) => index,
@@ -165,10 +145,7 @@ impl KernelScheme for SerioScheme {
}
fn kfpath(&self, id: usize, buf: UserSliceWo, token: &mut CleanLockToken) -> Result<usize> {
let handle = {
let handles = HANDLES.read(token.token());
*handles.get(&id).ok_or(Error::new(EBADF))?
};
let handle = *HANDLES.read(token.token()).get(id)?;
let path = match handle.kind {
HandleKind::Device(index) => format!("serio:{}", index).into_bytes(),
+18 -51
View File
@@ -8,11 +8,7 @@ use ::syscall::{
EACCES, EINVAL, EIO, EISDIR, ENOTDIR, EPERM,
};
use alloc::{sync::Arc, vec::Vec};
use core::{
str,
sync::atomic::{AtomicUsize, Ordering},
};
use hashbrown::{hash_map::DefaultHashBuilder, HashMap};
use core::str;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
use crate::arch::interrupt;
@@ -27,7 +23,7 @@ use crate::{
},
};
use super::{CallerCtx, KernelScheme, OpenResult, StrOrBytes};
use super::{CallerCtx, HandleMap, KernelScheme, OpenResult, StrOrBytes};
mod block;
mod context;
@@ -68,9 +64,7 @@ impl Kind {
/// System information scheme
pub struct SysScheme;
static NEXT_ID: AtomicUsize = AtomicUsize::new(1);
static HANDLES: RwLock<L1, HashMap<usize, Handle>> =
RwLock::new(HashMap::with_hasher(DefaultHashBuilder::new()));
static HANDLES: RwLock<L1, HandleMap<Handle>> = RwLock::new(HandleMap::new());
const FILES: &[(&str, Kind)] = &[
("block", Rd(block::resource)),
@@ -114,8 +108,7 @@ const FILES: &[(&str, Kind)] = &[
impl KernelScheme for SysScheme {
fn scheme_root(&self, token: &mut CleanLockToken) -> Result<usize> {
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
HANDLES.write(token.token()).insert(id, Handle::SchemeRoot);
let id = HANDLES.write(token.token()).insert(Handle::SchemeRoot);
Ok(id)
}
fn kopenat(
@@ -127,13 +120,7 @@ impl KernelScheme for SysScheme {
ctx: CallerCtx,
token: &mut CleanLockToken,
) -> Result<OpenResult> {
if !matches!(
HANDLES
.read(token.token())
.get(&id)
.ok_or(Error::new(EBADF))?,
Handle::SchemeRoot
) {
if !matches!(HANDLES.read(token.token()).get(id)?, Handle::SchemeRoot) {
return Err(Error::new(EACCES));
}
@@ -143,9 +130,7 @@ impl KernelScheme for SysScheme {
.trim_matches('/');
if path.is_empty() {
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
HANDLES.write(token.token()).insert(id, Handle::TopLevel);
let id = HANDLES.write(token.token()).insert(Handle::TopLevel);
Ok(OpenResult::SchemeLocal(id, InternalFlags::POSITIONED))
} else {
@@ -159,24 +144,19 @@ impl KernelScheme for SysScheme {
return Err(Error::new(EPERM));
}
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
// TODO: Initialize resources during openat to use them as a snapshot.
HANDLES.write(token.token()).insert(
id,
Handle::Resource {
path: entry.0,
kind: entry.1,
data: Arc::new(RwLock::new(None)),
},
);
let id = HANDLES.write(token.token()).insert(Handle::Resource {
path: entry.0,
kind: entry.1,
data: Arc::new(RwLock::new(None)),
});
Ok(OpenResult::SchemeLocal(id, InternalFlags::POSITIONED))
}
}
fn fsize(&self, id: usize, token: &mut CleanLockToken) -> Result<u64> {
let (kind, data_lock) = {
let handles = HANDLES.read(token.token());
match handles.get(&id).ok_or(Error::new(EBADF))? {
match HANDLES.read(token.token()).get(id)? {
Handle::TopLevel => return Ok(0),
Handle::Resource { kind, data, .. } => (*kind, data.clone()),
Handle::SchemeRoot => return Err(Error::new(EBADF)),
@@ -200,15 +180,11 @@ impl KernelScheme for SysScheme {
}
fn close(&self, id: usize, token: &mut CleanLockToken) -> Result<()> {
HANDLES
.write(token.token())
.remove(&id)
.ok_or(Error::new(EBADF))?;
HANDLES.write(token.token()).remove(id)?;
Ok(())
}
fn kfpath(&self, id: usize, buf: UserSliceWo, token: &mut CleanLockToken) -> Result<usize> {
let handles = HANDLES.read(token.token());
let path = match handles.get(&id).ok_or(Error::new(EBADF))? {
let path = match HANDLES.read(token.token()).get(id)? {
Handle::TopLevel => "",
Handle::Resource { path, .. } => path,
Handle::SchemeRoot => return Err(Error::new(EBADF)),
@@ -237,8 +213,7 @@ impl KernelScheme for SysScheme {
};
let (kind, data_lock) = {
let handles = HANDLES.read(token.token());
match handles.get(&id).ok_or(Error::new(EBADF))? {
match HANDLES.read(token.token()).get(id)? {
Handle::Resource { kind, data, .. } => (*kind, data.clone()),
_ => return Err(Error::new(EBADF)),
}
@@ -265,11 +240,7 @@ impl KernelScheme for SysScheme {
_stored_flags: u32,
token: &mut CleanLockToken,
) -> Result<usize> {
let (handler, intermediate, len) = match HANDLES
.read(token.token())
.get(&id)
.ok_or(Error::new(EBADF))?
{
let (handler, intermediate, len) = match HANDLES.read(token.token()).get(id)? {
Handle::TopLevel
| Handle::Resource {
kind: Kind::Rd(_), ..
@@ -297,11 +268,7 @@ impl KernelScheme for SysScheme {
let Ok(first_index) = usize::try_from(first_index) else {
return Ok(0);
};
match HANDLES
.read(token.token())
.get(&id)
.ok_or(Error::new(EBADF))?
{
match HANDLES.read(token.token()).get(id)? {
Handle::Resource { .. } => Err(Error::new(ENOTDIR)),
Handle::TopLevel => {
let mut buf = DirentBuf::new(buf, header_size).ok_or(Error::new(EIO))?;
@@ -322,7 +289,7 @@ impl KernelScheme for SysScheme {
fn kfstat(&self, id: usize, buf: UserSliceWo, token: &mut CleanLockToken) -> Result<()> {
let stat_base = {
let handles = HANDLES.read(token.token());
match handles.get(&id).ok_or(Error::new(EBADF))? {
match handles.get(id)? {
Handle::Resource { kind, data, .. } => Some((*kind, data.clone())),
Handle::TopLevel => None,
Handle::SchemeRoot => return Err(Error::new(EBADF)),
+13 -41
View File
@@ -1,9 +1,5 @@
use alloc::vec::Vec;
use core::{
fmt, str,
sync::atomic::{AtomicUsize, Ordering},
};
use hashbrown::{hash_map::DefaultHashBuilder, HashMap};
use core::{fmt, str};
use syscall::data::GlobalSchemes;
use crate::{
@@ -18,7 +14,7 @@ use crate::{
time,
};
use super::{CallerCtx, KernelScheme, OpenResult, SchemeExt, StrOrBytes};
use super::{CallerCtx, HandleMap, KernelScheme, OpenResult, SchemeExt, StrOrBytes};
#[derive(Clone)]
enum Handle {
@@ -26,9 +22,7 @@ enum Handle {
Clock(TimeSchemeHandle),
}
static NEXT_ID: AtomicUsize = AtomicUsize::new(1);
static HANDLES: RwLock<L1, HashMap<usize, Handle>> =
RwLock::new(HashMap::with_hasher(DefaultHashBuilder::new()));
static HANDLES: RwLock<L1, HandleMap<Handle>> = RwLock::new(HandleMap::new());
pub struct TimeScheme;
@@ -59,8 +53,7 @@ pub struct TimeSchemeHandle {
impl KernelScheme for TimeScheme {
fn scheme_root(&self, token: &mut CleanLockToken) -> Result<usize> {
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
HANDLES.write(token.token()).insert(id, Handle::SchemeRoot);
let id = HANDLES.write(token.token()).insert(Handle::SchemeRoot);
Ok(id)
}
fn kopenat(
@@ -74,7 +67,7 @@ impl KernelScheme for TimeScheme {
) -> Result<OpenResult> {
{
let handles = HANDLES.read(token.token());
let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
let handle = handles.get(id)?;
if !matches!(handle, Handle::SchemeRoot) {
return Err(Error::new(EACCES));
@@ -100,10 +93,9 @@ impl KernelScheme for TimeScheme {
_ => return Err(Error::new(ENOENT)),
}
let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
HANDLES
let id = HANDLES
.write(token.token())
.insert(id, Handle::Clock(TimeSchemeHandle { clock, kind }));
.insert(Handle::Clock(TimeSchemeHandle { clock, kind }));
Ok(OpenResult::SchemeLocal(id, InternalFlags::empty()))
}
@@ -126,25 +118,17 @@ impl KernelScheme for TimeScheme {
) -> Result<EventFlags> {
HANDLES
.read(token.token())
.get(&id)
.ok_or(Error::new(EBADF))
.get(id)
.and(Ok(EventFlags::empty()))
}
fn fsync(&self, id: usize, token: &mut CleanLockToken) -> Result<()> {
HANDLES
.read(token.token())
.get(&id)
.ok_or(Error::new(EBADF))?;
HANDLES.read(token.token()).get(id)?;
Ok(())
}
fn close(&self, id: usize, token: &mut CleanLockToken) -> Result<()> {
HANDLES
.write(token.token())
.remove(&id)
.ok_or(Error::new(EBADF))
.and(Ok(()))
HANDLES.write(token.token()).remove(id).and(Ok(()))
}
fn kread(
&self,
@@ -154,11 +138,7 @@ impl KernelScheme for TimeScheme {
_stored_flags: u32,
token: &mut CleanLockToken,
) -> Result<usize> {
let handle = match HANDLES
.read(token.token())
.get(&id)
.ok_or(Error::new(EBADF))?
{
let handle = match HANDLES.read(token.token()).get(id)? {
Handle::Clock(handle) => handle.clone(),
Handle::SchemeRoot => return Err(Error::new(EBADF)),
};
@@ -197,11 +177,7 @@ impl KernelScheme for TimeScheme {
_stored_flags: u32,
token: &mut CleanLockToken,
) -> Result<usize> {
let handle = match HANDLES
.read(token.token())
.get(&id)
.ok_or(Error::new(EBADF))?
{
let handle = match HANDLES.read(token.token()).get(id)? {
Handle::Clock(handle) => handle.clone(),
Handle::SchemeRoot => return Err(Error::new(EBADF)),
};
@@ -230,11 +206,7 @@ impl KernelScheme for TimeScheme {
Ok(bytes_written)
}
fn kfpath(&self, id: usize, buf: UserSliceWo, token: &mut CleanLockToken) -> Result<usize> {
let handle = match HANDLES
.read(token.token())
.get(&id)
.ok_or(Error::new(EBADF))?
{
let handle = match HANDLES.read(token.token()).get(id)? {
Handle::Clock(handle) => handle.clone(),
Handle::SchemeRoot => return Err(Error::new(EBADF)),
};