Introduce HandleMap helper type
This commit is contained in:
+20
-48
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user