Merge branch 'pipe_list_const_fn' into 'master'
Move more of `pipe:`'s initialization to compile time. See merge request redox-os/kernel!182
This commit is contained in:
@@ -4,7 +4,7 @@ use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
use spin::{Mutex, Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
|
||||
use crate::event;
|
||||
use crate::scheme::{AtomicSchemeId, SchemeId};
|
||||
use crate::scheme::SchemeId;
|
||||
use crate::sync::WaitCondition;
|
||||
use crate::syscall::error::{Error, Result, EAGAIN, EBADF, EINTR, EINVAL, EPIPE, ESPIPE};
|
||||
use crate::syscall::flag::{EventFlags, EVENT_READ, EVENT_WRITE, F_GETFL, F_SETFL, O_ACCMODE, O_NONBLOCK, MODE_FIFO};
|
||||
@@ -12,30 +12,21 @@ use crate::syscall::scheme::Scheme;
|
||||
use crate::syscall::data::Stat;
|
||||
|
||||
/// Pipes list
|
||||
pub static PIPE_SCHEME_ID: AtomicSchemeId = AtomicSchemeId::default();
|
||||
// TODO: Preallocate a number of scheme IDs, since there can only be *one* root namespace, and
|
||||
// therefore only *one* pipe scheme.
|
||||
static PIPE_SCHEME_ID: Once<SchemeId> = Once::new();
|
||||
static PIPE_NEXT_ID: AtomicUsize = AtomicUsize::new(0);
|
||||
static PIPES: Once<RwLock<(BTreeMap<usize, Arc<PipeRead>>, BTreeMap<usize, Arc<PipeWrite>>)>> = Once::new();
|
||||
static PIPES: RwLock<(BTreeMap<usize, Arc<PipeRead>>, BTreeMap<usize, Arc<PipeWrite>>)> = RwLock::new((BTreeMap::new(), BTreeMap::new()));
|
||||
|
||||
/// Initialize pipes, called if needed
|
||||
fn init_pipes() -> RwLock<(BTreeMap<usize, Arc<PipeRead>>, BTreeMap<usize, Arc<PipeWrite>>)> {
|
||||
RwLock::new((BTreeMap::new(), BTreeMap::new()))
|
||||
}
|
||||
|
||||
/// Get the global pipes list, const
|
||||
fn pipes() -> RwLockReadGuard<'static, (BTreeMap<usize, Arc<PipeRead>>, BTreeMap<usize, Arc<PipeWrite>>)> {
|
||||
PIPES.call_once(init_pipes).read()
|
||||
}
|
||||
|
||||
/// Get the global pipes list, mutable
|
||||
fn pipes_mut() -> RwLockWriteGuard<'static, (BTreeMap<usize, Arc<PipeRead>>, BTreeMap<usize, Arc<PipeWrite>>)> {
|
||||
PIPES.call_once(init_pipes).write()
|
||||
pub fn pipe_scheme_id() -> Option<SchemeId> {
|
||||
PIPE_SCHEME_ID.get().copied()
|
||||
}
|
||||
|
||||
pub fn pipe(flags: usize) -> (usize, usize) {
|
||||
let mut pipes = pipes_mut();
|
||||
let scheme_id = PIPE_SCHEME_ID.load(Ordering::SeqCst);
|
||||
let read_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
|
||||
let write_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
|
||||
let mut pipes = PIPES.write();
|
||||
let scheme_id = *PIPE_SCHEME_ID.get().expect("pipe scheme not initialized when calling pipe()");
|
||||
let read_id = PIPE_NEXT_ID.fetch_add(1, Ordering::Relaxed);
|
||||
let write_id = PIPE_NEXT_ID.fetch_add(1, Ordering::Relaxed);
|
||||
let read = PipeRead::new(scheme_id, write_id, flags);
|
||||
let write = PipeWrite::new(&read, read_id, flags);
|
||||
pipes.0.insert(read_id, Arc::new(read));
|
||||
@@ -47,7 +38,12 @@ pub struct PipeScheme;
|
||||
|
||||
impl PipeScheme {
|
||||
pub fn new(scheme_id: SchemeId) -> PipeScheme {
|
||||
PIPE_SCHEME_ID.store(scheme_id, Ordering::SeqCst);
|
||||
let mut called = false;
|
||||
PIPE_SCHEME_ID.call_once(|| {
|
||||
called = true;
|
||||
scheme_id
|
||||
});
|
||||
assert!(called, "calling PipeScheme::new more than once");
|
||||
PipeScheme
|
||||
}
|
||||
}
|
||||
@@ -56,7 +52,7 @@ impl Scheme for PipeScheme {
|
||||
fn read(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
// Clone to prevent deadlocks
|
||||
let pipe = {
|
||||
let pipes = pipes();
|
||||
let pipes = PIPES.read();
|
||||
pipes.0.get(&id).map(|pipe| pipe.clone()).ok_or(Error::new(EBADF))?
|
||||
};
|
||||
|
||||
@@ -66,7 +62,7 @@ impl Scheme for PipeScheme {
|
||||
fn write(&self, id: usize, buf: &[u8]) -> Result<usize> {
|
||||
// Clone to prevent deadlocks
|
||||
let pipe = {
|
||||
let pipes = pipes();
|
||||
let pipes = PIPES.read();
|
||||
pipes.1.get(&id).map(|pipe| pipe.clone()).ok_or(Error::new(EBADF))?
|
||||
};
|
||||
|
||||
@@ -74,7 +70,7 @@ impl Scheme for PipeScheme {
|
||||
}
|
||||
|
||||
fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result<usize> {
|
||||
let pipes = pipes();
|
||||
let pipes = PIPES.read();
|
||||
|
||||
if let Some(pipe) = pipes.0.get(&id) {
|
||||
return pipe.fcntl(cmd, arg);
|
||||
@@ -88,7 +84,7 @@ impl Scheme for PipeScheme {
|
||||
}
|
||||
|
||||
fn fevent(&self, id: usize, flags: EventFlags) -> Result<EventFlags> {
|
||||
let pipes = pipes();
|
||||
let pipes = PIPES.read();
|
||||
|
||||
if let Some(pipe) = pipes.0.get(&id) {
|
||||
if flags == EVENT_READ {
|
||||
@@ -111,13 +107,10 @@ impl Scheme for PipeScheme {
|
||||
}
|
||||
|
||||
fn fpath(&self, _id: usize, buf: &mut [u8]) -> Result<usize> {
|
||||
let mut i = 0;
|
||||
let scheme_path = b"pipe:";
|
||||
while i < buf.len() && i < scheme_path.len() {
|
||||
buf[i] = scheme_path[i];
|
||||
i += 1;
|
||||
}
|
||||
Ok(i)
|
||||
let to_copy = core::cmp::min(buf.len(), scheme_path.len());
|
||||
buf[..to_copy].copy_from_slice(&scheme_path[..to_copy]);
|
||||
Ok(to_copy)
|
||||
}
|
||||
|
||||
fn fstat(&self, _id: usize, stat: &mut Stat) -> Result<usize> {
|
||||
@@ -134,7 +127,7 @@ impl Scheme for PipeScheme {
|
||||
}
|
||||
|
||||
fn close(&self, id: usize) -> Result<usize> {
|
||||
let mut pipes = pipes_mut();
|
||||
let mut pipes = PIPES.write();
|
||||
|
||||
drop(pipes.0.remove(&id));
|
||||
drop(pipes.1.remove(&id));
|
||||
|
||||
@@ -162,41 +162,41 @@ pub fn open(path: &str, flags: usize) -> Result<FileHandle> {
|
||||
}
|
||||
|
||||
pub fn pipe2(fds: &mut [usize], flags: usize) -> Result<usize> {
|
||||
if fds.len() >= 2 {
|
||||
let scheme_id = crate::scheme::pipe::PIPE_SCHEME_ID.load(Ordering::SeqCst);
|
||||
let (read_id, write_id) = crate::scheme::pipe::pipe(flags);
|
||||
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
|
||||
let read_fd = context.add_file(FileDescriptor {
|
||||
description: Arc::new(RwLock::new(FileDescription {
|
||||
namespace: context.ens,
|
||||
scheme: scheme_id,
|
||||
number: read_id,
|
||||
flags: O_RDONLY | flags & !O_ACCMODE & !O_CLOEXEC,
|
||||
})),
|
||||
cloexec: flags & O_CLOEXEC == O_CLOEXEC,
|
||||
}).ok_or(Error::new(EMFILE))?;
|
||||
|
||||
let write_fd = context.add_file(FileDescriptor {
|
||||
description: Arc::new(RwLock::new(FileDescription {
|
||||
namespace: context.ens,
|
||||
scheme: scheme_id,
|
||||
number: write_id,
|
||||
flags: O_WRONLY | flags & !O_ACCMODE & !O_CLOEXEC,
|
||||
})),
|
||||
cloexec: flags & O_CLOEXEC == O_CLOEXEC,
|
||||
}).ok_or(Error::new(EMFILE))?;
|
||||
|
||||
fds[0] = read_fd.into();
|
||||
fds[1] = write_fd.into();
|
||||
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(Error::new(EFAULT))
|
||||
if fds.len() < 2 {
|
||||
return Err(Error::new(EFAULT));
|
||||
}
|
||||
|
||||
let scheme_id = crate::scheme::pipe::pipe_scheme_id().ok_or(Error::new(ENODEV))?;
|
||||
let (read_id, write_id) = crate::scheme::pipe::pipe(flags);
|
||||
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
|
||||
let read_fd = context.add_file(FileDescriptor {
|
||||
description: Arc::new(RwLock::new(FileDescription {
|
||||
namespace: context.ens,
|
||||
scheme: scheme_id,
|
||||
number: read_id,
|
||||
flags: O_RDONLY | flags & !O_ACCMODE & !O_CLOEXEC,
|
||||
})),
|
||||
cloexec: flags & O_CLOEXEC == O_CLOEXEC,
|
||||
}).ok_or(Error::new(EMFILE))?;
|
||||
|
||||
let write_fd = context.add_file(FileDescriptor {
|
||||
description: Arc::new(RwLock::new(FileDescription {
|
||||
namespace: context.ens,
|
||||
scheme: scheme_id,
|
||||
number: write_id,
|
||||
flags: O_WRONLY | flags & !O_ACCMODE & !O_CLOEXEC,
|
||||
})),
|
||||
cloexec: flags & O_CLOEXEC == O_CLOEXEC,
|
||||
}).ok_or(Error::new(EMFILE))?;
|
||||
|
||||
fds[0] = read_fd.into();
|
||||
fds[1] = write_fd.into();
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
/// chmod syscall
|
||||
|
||||
Reference in New Issue
Block a user