s/Arc<dyn KernelScheme>/enum, but deref as dyn.
This commit is contained in:
+4
-4
@@ -35,10 +35,10 @@ impl FileDescription {
|
||||
pub fn try_close(self) -> Result<()> {
|
||||
event::unregister_file(self.scheme, self.number);
|
||||
|
||||
let scheme = Arc::clone(
|
||||
scheme::schemes()
|
||||
.get(self.scheme).ok_or(Error::new(EBADF))?
|
||||
);
|
||||
let scheme = scheme::schemes()
|
||||
.get(self.scheme).ok_or(Error::new(EBADF))?
|
||||
.clone();
|
||||
|
||||
scheme.close(self.number)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ impl UnmapResult {
|
||||
};
|
||||
|
||||
let funmap_result = crate::scheme::schemes()
|
||||
.get(scheme_id).map(Arc::clone).ok_or(Error::new(ENODEV))
|
||||
.get(scheme_id).cloned().ok_or(Error::new(ENODEV))
|
||||
.and_then(|scheme| scheme.kfunmap(number, base_offset, self.size, self.flags));
|
||||
|
||||
if let Ok(fd) = Arc::try_unwrap(description) {
|
||||
|
||||
+3
-5
@@ -151,11 +151,9 @@ pub fn sync(reg_key: RegKey) -> Result<EventFlags> {
|
||||
}
|
||||
}
|
||||
|
||||
let scheme = {
|
||||
let schemes = scheme::schemes();
|
||||
let scheme = schemes.get(reg_key.scheme).ok_or(Error::new(EBADF))?;
|
||||
Arc::clone(scheme)
|
||||
};
|
||||
let scheme = scheme::schemes()
|
||||
.get(reg_key.scheme).ok_or(Error::new(EBADF))?
|
||||
.clone();
|
||||
|
||||
scheme.fevent(reg_key.number, flags)
|
||||
}
|
||||
|
||||
+1
-3
@@ -78,7 +78,7 @@ pub fn register_kstop() -> bool {
|
||||
}
|
||||
|
||||
impl AcpiScheme {
|
||||
pub fn new(id: SchemeId) -> Self {
|
||||
pub fn init(id: SchemeId) {
|
||||
// NOTE: This __must__ be called from the main kernel context, while initializing all
|
||||
// schemes. If it is called by any other context, then all ACPI data will probably not even
|
||||
// be mapped.
|
||||
@@ -109,8 +109,6 @@ impl AcpiScheme {
|
||||
if !data_init || !id_init {
|
||||
log::error!("AcpiScheme::init called multiple times");
|
||||
}
|
||||
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -42,9 +42,8 @@ pub fn debug_notify() {
|
||||
pub struct DebugScheme;
|
||||
|
||||
impl DebugScheme {
|
||||
pub fn new(scheme_id: SchemeId) -> Self {
|
||||
pub fn init(scheme_id: SchemeId) {
|
||||
SCHEME_ID.call_once(|| scheme_id);
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+85
-25
@@ -38,7 +38,7 @@ use self::root::RootScheme;
|
||||
use self::serio::SerioScheme;
|
||||
use self::sys::SysScheme;
|
||||
use self::time::TimeScheme;
|
||||
use self::user::UserInner;
|
||||
use self::user::{UserInner, UserScheme};
|
||||
|
||||
/// When compiled with the "acpi" feature - `acpi:` - allows drivers to read a limited set of ACPI tables.
|
||||
#[cfg(all(feature = "acpi", any(target_arch = "x86", target_arch = "x86_64")))]
|
||||
@@ -108,7 +108,7 @@ impl<'a> Iterator for SchemeIter<'a> {
|
||||
|
||||
/// Scheme list type
|
||||
pub struct SchemeList {
|
||||
map: BTreeMap<SchemeId, Arc<dyn KernelScheme>>,
|
||||
map: BTreeMap<SchemeId, KernelSchemes>,
|
||||
names: BTreeMap<SchemeNamespace, BTreeMap<Box<str>, SchemeId>>,
|
||||
next_ns: usize,
|
||||
next_id: usize
|
||||
@@ -136,9 +136,12 @@ impl SchemeList {
|
||||
|
||||
//TODO: Only memory: is in the null namespace right now. It should be removed when
|
||||
//anonymous mmap's are implemented
|
||||
self.insert(ns, "memory", |_| Arc::new(MemoryScheme::new())).unwrap();
|
||||
self.insert(ns, "thisproc", |_| Arc::new(ProcScheme::restricted())).unwrap();
|
||||
self.insert(ns, "pipe", |scheme_id| PipeScheme::new(scheme_id)).unwrap();
|
||||
self.insert(ns, "memory", |_| KernelSchemes::Memory).unwrap();
|
||||
self.insert(ns, "thisproc", |_| KernelSchemes::Proc(Arc::new(ProcScheme::restricted()))).unwrap();
|
||||
self.insert(ns, "pipe", |scheme_id| {
|
||||
PipeScheme::init(scheme_id);
|
||||
KernelSchemes::Pipe
|
||||
}).unwrap();
|
||||
}
|
||||
|
||||
/// Initialize a new namespace
|
||||
@@ -147,13 +150,16 @@ impl SchemeList {
|
||||
self.next_ns += 1;
|
||||
self.names.insert(ns, BTreeMap::new());
|
||||
|
||||
self.insert(ns, "", |scheme_id| Arc::new(RootScheme::new(ns, scheme_id))).unwrap();
|
||||
self.insert(ns, "event", |_| Arc::new(EventScheme)).unwrap();
|
||||
self.insert(ns, "itimer", |_| Arc::new(ITimerScheme::new())).unwrap();
|
||||
self.insert(ns, "memory", |_| Arc::new(MemoryScheme::new())).unwrap();
|
||||
self.insert(ns, "pipe", |scheme_id| PipeScheme::new(scheme_id)).unwrap();
|
||||
self.insert(ns, "sys", |_| Arc::new(SysScheme::new())).unwrap();
|
||||
self.insert(ns, "time", |scheme_id| Arc::new(TimeScheme::new(scheme_id))).unwrap();
|
||||
self.insert(ns, "", |scheme_id| KernelSchemes::Root(Arc::new(RootScheme::new(ns, scheme_id)))).unwrap();
|
||||
self.insert(ns, "event", |_| KernelSchemes::Event).unwrap();
|
||||
self.insert(ns, "itimer", |_| KernelSchemes::ITimer(Arc::new(ITimerScheme::new()))).unwrap();
|
||||
self.insert(ns, "memory", |_| KernelSchemes::Memory).unwrap();
|
||||
self.insert(ns, "pipe", |scheme_id| {
|
||||
PipeScheme::init(scheme_id);
|
||||
KernelSchemes::Pipe
|
||||
}).unwrap();
|
||||
self.insert(ns, "sys", |_| KernelSchemes::Sys(Arc::new(SysScheme::new()))).unwrap();
|
||||
self.insert(ns, "time", |scheme_id| KernelSchemes::Time(Arc::new(TimeScheme::new(scheme_id)))).unwrap();
|
||||
|
||||
ns
|
||||
}
|
||||
@@ -164,17 +170,28 @@ impl SchemeList {
|
||||
let ns = self.new_ns();
|
||||
|
||||
// These schemes should only be available on the root
|
||||
#[cfg(all(feature = "acpi", any(target_arch = "x86", target_arch = "x86_64")))] {
|
||||
self.insert(ns, "kernel.acpi", |scheme_id| Arc::new(AcpiScheme::new(scheme_id))).unwrap();
|
||||
}
|
||||
#[cfg(all(any(target_arch = "aarch64")))] {
|
||||
#[cfg(all(feature = "acpi", any(target_arch = "x86", target_arch = "x86_64")))]
|
||||
self.insert(ns, "kernel.acpi", |scheme_id| {
|
||||
AcpiScheme::init(scheme_id);
|
||||
KernelSchemes::Acpi
|
||||
}).unwrap();
|
||||
|
||||
#[cfg(all(any(target_arch = "aarch64")))]
|
||||
{
|
||||
self.insert(ns, "kernel.dtb", |scheme_id| Arc::new(DtbScheme::new(scheme_id))).unwrap();
|
||||
}
|
||||
self.insert(ns, "debug", |scheme_id| Arc::new(DebugScheme::new(scheme_id))).unwrap();
|
||||
self.insert(ns, "irq", |scheme_id| Arc::new(IrqScheme::new(scheme_id))).unwrap();
|
||||
self.insert(ns, "proc", |scheme_id| Arc::new(ProcScheme::new(scheme_id))).unwrap();
|
||||
self.insert(ns, "thisproc", |_| Arc::new(ProcScheme::restricted())).unwrap();
|
||||
self.insert(ns, "serio", |scheme_id| Arc::new(SerioScheme::new(scheme_id))).unwrap();
|
||||
|
||||
self.insert(ns, "debug", |scheme_id| {
|
||||
DebugScheme::init(scheme_id);
|
||||
KernelSchemes::Debug
|
||||
}).unwrap();
|
||||
self.insert(ns, "irq", |scheme_id| KernelSchemes::Irq(Arc::new(IrqScheme::new(scheme_id)))).unwrap();
|
||||
self.insert(ns, "proc", |scheme_id| KernelSchemes::Proc(Arc::new(ProcScheme::new(scheme_id)))).unwrap();
|
||||
self.insert(ns, "thisproc", |_| KernelSchemes::Proc(Arc::new(ProcScheme::restricted()))).unwrap();
|
||||
self.insert(ns, "serio", |scheme_id| {
|
||||
SerioScheme::init(scheme_id);
|
||||
KernelSchemes::Serio
|
||||
}).unwrap();
|
||||
}
|
||||
|
||||
pub fn make_ns(&mut self, from: SchemeNamespace, names: impl IntoIterator<Item = Box<str>>) -> Result<SchemeNamespace> {
|
||||
@@ -206,11 +223,11 @@ impl SchemeList {
|
||||
}
|
||||
|
||||
/// Get the nth scheme.
|
||||
pub fn get(&self, id: SchemeId) -> Option<&Arc<dyn KernelScheme>> {
|
||||
pub fn get(&self, id: SchemeId) -> Option<&KernelSchemes> {
|
||||
self.map.get(&id)
|
||||
}
|
||||
|
||||
pub fn get_name(&self, ns: SchemeNamespace, name: &str) -> Option<(SchemeId, &Arc<dyn KernelScheme>)> {
|
||||
pub fn get_name(&self, ns: SchemeNamespace, name: &str) -> Option<(SchemeId, &KernelSchemes)> {
|
||||
if let Some(names) = self.names.get(&ns) {
|
||||
if let Some(&id) = names.get(name) {
|
||||
return self.get(id).map(|scheme| (id, scheme));
|
||||
@@ -220,11 +237,11 @@ impl SchemeList {
|
||||
}
|
||||
|
||||
/// Create a new scheme.
|
||||
pub fn insert(&mut self, ns: SchemeNamespace, name: &str, scheme_fn: impl FnOnce(SchemeId) -> Arc<dyn KernelScheme>) -> Result<SchemeId> {
|
||||
pub fn insert(&mut self, ns: SchemeNamespace, name: &str, scheme_fn: impl FnOnce(SchemeId) -> KernelSchemes) -> Result<SchemeId> {
|
||||
self.insert_and_pass(ns, name, |id| (scheme_fn(id), ())).map(|(id, ())| id)
|
||||
}
|
||||
|
||||
pub fn insert_and_pass<T>(&mut self, ns: SchemeNamespace, name: &str, scheme_fn: impl FnOnce(SchemeId) -> (Arc<dyn KernelScheme>, T)) -> Result<(SchemeId, T)> {
|
||||
pub fn insert_and_pass<T>(&mut self, ns: SchemeNamespace, name: &str, scheme_fn: impl FnOnce(SchemeId) -> (KernelSchemes, T)) -> Result<(SchemeId, T)> {
|
||||
if let Some(names) = self.names.get(&ns) {
|
||||
if names.contains_key(name) {
|
||||
return Err(Error::new(EEXIST));
|
||||
@@ -402,3 +419,46 @@ pub fn calc_seek_offset(cur_pos: usize, rel_pos: isize, whence: usize, len: usiz
|
||||
_ => return Err(Error::new(EINVAL)),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum KernelSchemes {
|
||||
Debug,
|
||||
Event,
|
||||
Irq(Arc<IrqScheme>),
|
||||
ITimer(Arc<ITimerScheme>),
|
||||
Memory,
|
||||
Pipe,
|
||||
Proc(Arc<ProcScheme>),
|
||||
Root(Arc<RootScheme>),
|
||||
Serio,
|
||||
Sys(Arc<SysScheme>),
|
||||
Time(Arc<TimeScheme>),
|
||||
User(UserScheme),
|
||||
|
||||
#[cfg(all(feature = "acpi", any(target_arch = "x86", target_arch = "x86_64")))]
|
||||
Acpi,
|
||||
}
|
||||
|
||||
impl core::ops::Deref for KernelSchemes {
|
||||
type Target = dyn KernelScheme;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match self {
|
||||
Self::Debug => &DebugScheme,
|
||||
Self::Event => &EventScheme,
|
||||
Self::Irq(scheme) => &**scheme,
|
||||
Self::ITimer(scheme) => &**scheme,
|
||||
Self::Memory => &MemoryScheme,
|
||||
Self::Pipe => &PipeScheme,
|
||||
Self::Proc(scheme) => &**scheme,
|
||||
Self::Root(scheme) => &**scheme,
|
||||
Self::Serio => &SerioScheme,
|
||||
Self::Sys(scheme) => &**scheme,
|
||||
Self::Time(scheme) => &**scheme,
|
||||
Self::User(scheme) => scheme,
|
||||
|
||||
#[cfg(all(feature = "acpi", any(target_arch = "x86", target_arch = "x86_64")))]
|
||||
Self::Acpi => &AcpiScheme,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-6
@@ -17,14 +17,14 @@ use super::{KernelScheme, OpenResult, CallerCtx};
|
||||
|
||||
// TODO: Preallocate a number of scheme IDs, since there can only be *one* root namespace, and
|
||||
// therefore only *one* pipe scheme.
|
||||
static THE_PIPE_SCHEME: Once<(SchemeId, Arc<dyn KernelScheme>)> = Once::new();
|
||||
static SCHEME_ID: Once<SchemeId> = Once::new();
|
||||
static PIPE_NEXT_ID: AtomicUsize = AtomicUsize::new(1);
|
||||
|
||||
// TODO: SLOB?
|
||||
static PIPES: RwLock<BTreeMap<usize, Arc<Pipe>>> = RwLock::new(BTreeMap::new());
|
||||
|
||||
pub fn pipe_scheme_id() -> SchemeId {
|
||||
THE_PIPE_SCHEME.get().expect("pipe scheme must be initialized").0
|
||||
*SCHEME_ID.get().expect("pipe scheme must be initialized")
|
||||
}
|
||||
|
||||
const MAX_QUEUE_SIZE: usize = 65536;
|
||||
@@ -57,10 +57,8 @@ pub fn pipe(flags: usize) -> Result<(usize, usize)> {
|
||||
pub struct PipeScheme;
|
||||
|
||||
impl PipeScheme {
|
||||
pub fn new(scheme_id: SchemeId) -> Arc<dyn KernelScheme> {
|
||||
Arc::clone(&THE_PIPE_SCHEME.call_once(|| {
|
||||
(scheme_id, Arc::new(Self))
|
||||
}).1)
|
||||
pub fn init(scheme_id: SchemeId) {
|
||||
SCHEME_ID.call_once(|| scheme_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -30,7 +30,7 @@ use core::{
|
||||
};
|
||||
use spin::{Once, RwLock};
|
||||
|
||||
use super::{OpenResult, CallerCtx};
|
||||
use super::{OpenResult, CallerCtx, KernelSchemes};
|
||||
|
||||
fn read_from(dst: UserSliceWo, src: &[u8], offset: &mut usize) -> Result<usize> {
|
||||
let avail_src = src.get(*offset..).unwrap_or(&[]);
|
||||
@@ -1248,11 +1248,11 @@ fn inherit_context() -> Result<ContextId> {
|
||||
|
||||
Ok(new_id)
|
||||
}
|
||||
fn extract_scheme_number(fd: usize) -> Result<(Arc<dyn KernelScheme>, usize)> {
|
||||
fn extract_scheme_number(fd: usize) -> Result<(KernelSchemes, usize)> {
|
||||
let (scheme_id, number) = match &*context::contexts().current().ok_or(Error::new(ESRCH))?.read().get_file(FileHandle::from(fd)).ok_or(Error::new(EBADF))?.description.read() {
|
||||
desc => (desc.scheme, desc.number)
|
||||
};
|
||||
let scheme = Arc::clone(scheme::schemes().get(scheme_id).ok_or(Error::new(ENODEV))?);
|
||||
let scheme = scheme::schemes().get(scheme_id).ok_or(Error::new(ENODEV))?.clone();
|
||||
|
||||
Ok((scheme, number))
|
||||
}
|
||||
|
||||
+2
-2
@@ -17,7 +17,7 @@ use crate::scheme::{self, SchemeNamespace, SchemeId};
|
||||
use crate::scheme::user::{UserInner, UserScheme};
|
||||
use crate::syscall::usercopy::{UserSliceWo, UserSliceRo};
|
||||
|
||||
use super::{KernelScheme, CallerCtx, OpenResult, calc_seek_offset};
|
||||
use super::{KernelScheme, KernelSchemes, CallerCtx, OpenResult, calc_seek_offset};
|
||||
|
||||
struct FolderInner {
|
||||
data: Box<[u8]>,
|
||||
@@ -96,7 +96,7 @@ impl KernelScheme for RootScheme {
|
||||
|
||||
let (_scheme_id, inner) = schemes.insert_and_pass(self.scheme_ns, path, |scheme_id| {
|
||||
let inner = Arc::new(UserInner::new(self.scheme_id, scheme_id, id, path_box, flags, context));
|
||||
(Arc::new(UserScheme::new(Arc::downgrade(&inner))), inner)
|
||||
(KernelSchemes::User(UserScheme::new(Arc::downgrade(&inner))), inner)
|
||||
})?;
|
||||
|
||||
inner
|
||||
|
||||
+1
-2
@@ -42,9 +42,8 @@ pub fn serio_input(index: usize, data: u8) {
|
||||
pub struct SerioScheme;
|
||||
|
||||
impl SerioScheme {
|
||||
pub fn new(scheme_id: SchemeId) -> Self {
|
||||
pub fn init(scheme_id: SchemeId) {
|
||||
SCHEME_ID.call_once(|| scheme_id);
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -750,6 +750,7 @@ fn page_range_containing(base: usize, size: usize) -> (Page, usize, usize) {
|
||||
}
|
||||
|
||||
/// `UserInner` has to be wrapped
|
||||
#[derive(Clone)]
|
||||
pub struct UserScheme {
|
||||
inner: Weak<UserInner>
|
||||
}
|
||||
|
||||
+11
-14
@@ -23,7 +23,7 @@ pub fn file_op_generic_ext<T>(fd: FileHandle, op: impl FnOnce(&dyn KernelScheme,
|
||||
};
|
||||
let FileDescription { scheme: scheme_id, number, .. } = *file.description.read();
|
||||
|
||||
let scheme = Arc::clone(scheme::schemes().get(scheme_id).ok_or(Error::new(EBADF))?);
|
||||
let scheme = scheme::schemes().get(scheme_id).ok_or(Error::new(EBADF))?.clone();
|
||||
|
||||
op(&*scheme, scheme_id, &ctx, number)
|
||||
}
|
||||
@@ -64,7 +64,7 @@ pub fn open(raw_path: UserSliceRo, flags: usize) -> Result<FileHandle> {
|
||||
let (scheme_id, scheme) = {
|
||||
let schemes = scheme::schemes();
|
||||
let (scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?;
|
||||
(scheme_id, Arc::clone(scheme))
|
||||
(scheme_id, scheme.clone())
|
||||
};
|
||||
|
||||
match scheme.kopen(reference, flags, CallerCtx { uid, gid, pid })? {
|
||||
@@ -104,7 +104,7 @@ pub fn rmdir(raw_path: UserSliceRo) -> Result<()> {
|
||||
let scheme = {
|
||||
let schemes = scheme::schemes();
|
||||
let (_scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?;
|
||||
Arc::clone(scheme)
|
||||
scheme.clone()
|
||||
};
|
||||
scheme.rmdir(reference, caller_ctx)
|
||||
}
|
||||
@@ -127,7 +127,7 @@ pub fn unlink(raw_path: UserSliceRo) -> Result<()> {
|
||||
let scheme = {
|
||||
let schemes = scheme::schemes();
|
||||
let (_scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?;
|
||||
Arc::clone(scheme)
|
||||
scheme.clone()
|
||||
};
|
||||
scheme.unlink(reference, caller_ctx)
|
||||
}
|
||||
@@ -158,11 +158,9 @@ fn duplicate_file(fd: FileHandle, user_buf: UserSliceRo) -> Result<FileDescripto
|
||||
let description = file.description.read();
|
||||
|
||||
let new_description = {
|
||||
let scheme = {
|
||||
let schemes = scheme::schemes();
|
||||
let scheme = schemes.get(description.scheme).ok_or(Error::new(EBADF))?;
|
||||
Arc::clone(scheme)
|
||||
};
|
||||
let scheme = scheme::schemes()
|
||||
.get(description.scheme).ok_or(Error::new(EBADF))?
|
||||
.clone();
|
||||
|
||||
match scheme.kdup(description.number, user_buf, caller_ctx)? {
|
||||
OpenResult::SchemeLocal(number) => Arc::new(RwLock::new(FileDescription {
|
||||
@@ -250,11 +248,10 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize) -> Result<usize> {
|
||||
|
||||
// Communicate fcntl with scheme
|
||||
if cmd != F_DUPFD && cmd != F_GETFD && cmd != F_SETFD {
|
||||
let scheme = {
|
||||
let schemes = scheme::schemes();
|
||||
let scheme = schemes.get(description.scheme).ok_or(Error::new(EBADF))?;
|
||||
Arc::clone(scheme)
|
||||
};
|
||||
let scheme = scheme::schemes()
|
||||
.get(description.scheme).ok_or(Error::new(EBADF))?
|
||||
.clone();
|
||||
|
||||
scheme.fcntl(description.number, cmd, arg)?;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user