From 219d707362a377960b80bbaf5f973cc43f7cdff1 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 13 Apr 2026 20:51:24 +0200 Subject: [PATCH] Introduce HandleMap helper type --- src/scheme/acpi.rs | 68 +++++++++++++----------------------------- src/scheme/debug.rs | 57 ++++++++--------------------------- src/scheme/dtb.rs | 55 ++++++++++------------------------ src/scheme/irq.rs | 34 ++++++++------------- src/scheme/mod.rs | 39 +++++++++++++++++++++++- src/scheme/serio.rs | 49 ++++++++---------------------- src/scheme/sys/mod.rs | 69 +++++++++++-------------------------------- src/scheme/time.rs | 54 ++++++++------------------------- 8 files changed, 141 insertions(+), 284 deletions(-) diff --git a/src/scheme/acpi.rs b/src/scheme/acpi.rs index 29ca8a12ab..87570a1297 100644 --- a/src/scheme/acpi.rs +++ b/src/scheme/acpi.rs @@ -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> = - RwLock::new(HashMap::with_hasher(DefaultHashBuilder::new())); -static NEXT_FD: AtomicUsize = AtomicUsize::new(0); +static HANDLES: RwLock> = RwLock::new(HandleMap::new()); static DATA: Once> = Once::new(); @@ -116,16 +109,10 @@ impl AcpiScheme { impl KernelScheme for AcpiScheme { fn scheme_root(&self, token: &mut CleanLockToken) -> Result { - 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 { 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 { 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 { 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 { - 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 => { diff --git a/src/scheme/debug.rs b/src/scheme/debug.rs index d2100d1227..c70ac5792b 100644 --- a/src/scheme/debug.rs +++ b/src/scheme/debug.rs @@ -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 = WaitQueue::new(); @@ -23,8 +20,7 @@ struct Handle { num: usize, } -static HANDLES: RwLock> = - RwLock::new(HashMap::with_hasher(DefaultHashBuilder::new())); +static HANDLES: RwLock> = 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { diff --git a/src/scheme/dtb.rs b/src/scheme/dtb.rs index 824e8b4a9a..bc288dc9cc 100644 --- a/src/scheme/dtb.rs +++ b/src/scheme/dtb.rs @@ -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> = - RwLock::new(HashMap::with_hasher(DefaultHashBuilder::new())); -static NEXT_FD: AtomicUsize = AtomicUsize::new(0); +static HANDLES: RwLock> = RwLock::new(HandleMap::new()); static DATA: Once> = Once::new(); impl DtbScheme { @@ -53,17 +48,10 @@ impl DtbScheme { impl KernelScheme for DtbScheme { fn scheme_root(&self, token: &mut CleanLockToken) -> Result { - 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 { 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 { 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 { 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))?; diff --git a/src/scheme/irq.rs b/src/scheme/irq.rs index 453165f953..a8795e5958 100644 --- a/src/scheme/irq.rs +++ b/src/scheme/irq.rs @@ -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> = - RwLock::new(HashMap::with_hasher(DefaultHashBuilder::new())); +static HANDLES: RwLock> = 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> = 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 { - 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 { { 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 { 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 { 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 { 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 diff --git a/src/scheme/mod.rs b/src/scheme/mod.rs index 87ffdc2649..d30272c129 100644 --- a/src/scheme/mod.rs +++ b/src/scheme/mod.rs @@ -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 { + handles: HashMap, + next_id: usize, +} + +impl HandleMap { + 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 { + 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), diff --git a/src/scheme/serio.rs b/src/scheme/serio.rs index 5fdcd8b47d..26505021ad 100644 --- a/src/scheme/serio.rs +++ b/src/scheme/serio.rs @@ -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> = - RwLock::new(HashMap::with_hasher(DefaultHashBuilder::new())); +static HANDLES: RwLock> = 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 { - 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 { { 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 { 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 { - 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 { - 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(), diff --git a/src/scheme/sys/mod.rs b/src/scheme/sys/mod.rs index 91e846e6dc..8f26187a79 100644 --- a/src/scheme/sys/mod.rs +++ b/src/scheme/sys/mod.rs @@ -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> = - RwLock::new(HashMap::with_hasher(DefaultHashBuilder::new())); +static HANDLES: RwLock> = 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 { - 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 { - 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 { 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 { - 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 { - 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)), diff --git a/src/scheme/time.rs b/src/scheme/time.rs index 2ef0177185..4ec3aed320 100644 --- a/src/scheme/time.rs +++ b/src/scheme/time.rs @@ -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> = - RwLock::new(HashMap::with_hasher(DefaultHashBuilder::new())); +static HANDLES: RwLock> = 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 { - 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 { { 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 { 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 { - 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 { - 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 { - 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)), };