Add fcntl

This commit is contained in:
Jeremy Soller 2016-11-14 12:15:34 -07:00
parent 5fd7b2b71d
commit 8b56d14e41
4 changed files with 79 additions and 29 deletions

View file

@ -4,8 +4,8 @@ use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use spin::{Mutex, Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
use sync::WaitCondition;
use syscall::error::{Error, Result, EBADF, EPIPE};
use syscall::flag::O_NONBLOCK;
use syscall::error::{Error, Result, EBADF, EINVAL, EPIPE};
use syscall::flag::{F_GETFL, F_SETFL, O_NONBLOCK};
use syscall::scheme::Scheme;
/// Pipes list
@ -33,7 +33,7 @@ pub fn pipe(flags: usize) -> (usize, usize) {
let read_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
let write_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
let read = PipeRead::new(flags);
let write = PipeWrite::new(&read);
let write = PipeWrite::new(flags, &read);
pipes.0.insert(read_id, read);
pipes.1.insert(write_id, write);
(read_id, write_id)
@ -42,17 +42,25 @@ pub fn pipe(flags: usize) -> (usize, usize) {
pub struct PipeScheme;
impl Scheme for PipeScheme {
fn dup(&self, id: usize, _buf: &[u8]) -> Result<usize> {
fn dup(&self, id: usize, buf: &[u8]) -> Result<usize> {
let mut pipes = pipes_mut();
let read_option = pipes.0.get(&id).map(|pipe| pipe.clone());
let read_option = if let Some(pipe) = pipes.0.get(&id) {
Some(pipe.dup(buf)?)
} else {
None
};
if let Some(pipe) = read_option {
let pipe_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
pipes.0.insert(pipe_id, pipe);
return Ok(pipe_id);
}
let write_option = pipes.1.get(&id).map(|pipe| pipe.clone());
let write_option = if let Some(pipe) = pipes.1.get(&id) {
Some(pipe.dup(buf)?)
} else {
None
};
if let Some(pipe) = write_option {
let pipe_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
pipes.1.insert(pipe_id, pipe);
@ -63,12 +71,9 @@ impl Scheme for PipeScheme {
}
fn read(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
let pipe_option = {
let pipes = pipes();
pipes.0.get(&id).map(|pipe| pipe.clone())
};
let pipes = pipes();
if let Some(pipe) = pipe_option {
if let Some(pipe) = pipes.0.get(&id) {
pipe.read(buf)
} else {
Err(Error::new(EBADF))
@ -76,18 +81,29 @@ impl Scheme for PipeScheme {
}
fn write(&self, id: usize, buf: &[u8]) -> Result<usize> {
let pipe_option = {
let pipes = pipes();
pipes.1.get(&id).map(|pipe| pipe.clone())
};
let pipes = pipes();
if let Some(pipe) = pipe_option {
if let Some(pipe) = pipes.1.get(&id) {
pipe.write(buf)
} else {
Err(Error::new(EBADF))
}
}
fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result<usize> {
let pipes = pipes();
if let Some(pipe) = pipes.0.get(&id) {
return pipe.fcntl(cmd, arg);
}
if let Some(pipe) = pipes.1.get(&id) {
return pipe.fcntl(cmd, arg);
}
Err(Error::new(EBADF))
}
fn fsync(&self, _id: usize) -> Result<usize> {
Ok(0)
}
@ -103,9 +119,8 @@ impl Scheme for PipeScheme {
}
/// Read side of a pipe
#[derive(Clone)]
pub struct PipeRead {
flags: usize,
flags: AtomicUsize,
condition: Arc<WaitCondition>,
vec: Arc<Mutex<VecDeque<u8>>>
}
@ -113,12 +128,31 @@ pub struct PipeRead {
impl PipeRead {
pub fn new(flags: usize) -> Self {
PipeRead {
flags: flags,
flags: AtomicUsize::new(flags),
condition: Arc::new(WaitCondition::new()),
vec: Arc::new(Mutex::new(VecDeque::new())),
}
}
fn dup(&self, _buf: &[u8]) -> Result<Self> {
Ok(PipeRead {
flags: AtomicUsize::new(self.flags.load(Ordering::SeqCst)),
condition: self.condition.clone(),
vec: self.vec.clone()
})
}
fn fcntl(&self, cmd: usize, arg: usize) -> Result<usize> {
match cmd {
F_GETFL => Ok(self.flags.load(Ordering::SeqCst)),
F_SETFL => {
self.flags.store(arg, Ordering::SeqCst);
Ok(0)
},
_ => Err(Error::new(EINVAL))
}
}
fn read(&self, buf: &mut [u8]) -> Result<usize> {
loop {
{
@ -139,7 +173,7 @@ impl PipeRead {
}
}
if self.flags & O_NONBLOCK == O_NONBLOCK || Arc::weak_count(&self.vec) == 0 {
if self.flags.load(Ordering::SeqCst) & O_NONBLOCK == O_NONBLOCK || Arc::weak_count(&self.vec) == 0 {
return Ok(0);
} else {
self.condition.wait();
@ -149,20 +183,40 @@ impl PipeRead {
}
/// Read side of a pipe
#[derive(Clone)]
pub struct PipeWrite {
flags: AtomicUsize,
condition: Arc<WaitCondition>,
vec: Weak<Mutex<VecDeque<u8>>>
}
impl PipeWrite {
pub fn new(read: &PipeRead) -> Self {
pub fn new(flags: usize, read: &PipeRead) -> Self {
PipeWrite {
flags: AtomicUsize::new(flags),
condition: read.condition.clone(),
vec: Arc::downgrade(&read.vec),
}
}
fn dup(&self, _buf: &[u8]) -> Result<Self> {
Ok(PipeWrite {
flags: AtomicUsize::new(self.flags.load(Ordering::SeqCst)),
condition: self.condition.clone(),
vec: self.vec.clone()
})
}
fn fcntl(&self, cmd: usize, arg: usize) -> Result<usize> {
match cmd {
F_GETFL => Ok(self.flags.load(Ordering::SeqCst)),
F_SETFL => {
self.flags.store(arg, Ordering::SeqCst);
Ok(0)
},
_ => Err(Error::new(EINVAL))
}
}
fn write(&self, buf: &[u8]) -> Result<usize> {
if let Some(vec_lock) = self.vec.upgrade() {
let mut vec = vec_lock.lock();

View file

@ -10,7 +10,7 @@ pub use self::syscall::flag::*;
pub use self::syscall::{
clock_gettime, clone, execve as exec, exit, futex, getpid, kill, nanosleep, setgid, setuid, waitpid,
chdir, getcwd, open, mkdir, rmdir, unlink, dup, pipe2,
read, write, fpath, fstat, fsync, ftruncate, lseek, close
read, write, fcntl, fpath, fstat, fsync, ftruncate, lseek, close
};
//TODO: Thread local
@ -81,7 +81,3 @@ pub extern "C" fn sbrk(n: isize) -> *mut u8 {
}
}
// } ralloc shims
pub unsafe fn fcntl(_fd: usize, _cmd: c_int, _arg: c_int) -> c_int {
cvt(Err(Error::new(ENOSYS)))
}

2
rust

@ -1 +1 @@
Subproject commit 0bb9a959074bb7f027cf05a240a0044116fa0ab0
Subproject commit a0b5dfef2a36a15f76476a9d6bb7184a701d0d3c

@ -1 +1 @@
Subproject commit 07b50b1a81caf2ce0eae0029dd4385820a5a200e
Subproject commit f48cbf22f3cf85e73f2dd778c3764ad430cd30e8