From 8b56d14e41dfeee1967246c5f8746566845202e3 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 14 Nov 2016 12:15:34 -0700 Subject: [PATCH] Add fcntl --- kernel/scheme/pipe.rs | 98 +++++++++++++++++++++++++-------- libstd_real/libc/src/syscall.rs | 6 +- rust | 2 +- syscall | 2 +- 4 files changed, 79 insertions(+), 29 deletions(-) diff --git a/kernel/scheme/pipe.rs b/kernel/scheme/pipe.rs index 49d4895..86db679 100644 --- a/kernel/scheme/pipe.rs +++ b/kernel/scheme/pipe.rs @@ -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 { + fn dup(&self, id: usize, buf: &[u8]) -> Result { 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 { - 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 { - 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 { + 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 { 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, vec: Arc>> } @@ -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 { + 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 { + 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 { 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, vec: Weak>> } 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 { + 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 { + 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 { if let Some(vec_lock) = self.vec.upgrade() { let mut vec = vec_lock.lock(); diff --git a/libstd_real/libc/src/syscall.rs b/libstd_real/libc/src/syscall.rs index e24c58e..60e3589 100644 --- a/libstd_real/libc/src/syscall.rs +++ b/libstd_real/libc/src/syscall.rs @@ -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))) -} diff --git a/rust b/rust index 0bb9a95..a0b5dfe 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 0bb9a959074bb7f027cf05a240a0044116fa0ab0 +Subproject commit a0b5dfef2a36a15f76476a9d6bb7184a701d0d3c diff --git a/syscall b/syscall index 07b50b1..f48cbf2 160000 --- a/syscall +++ b/syscall @@ -1 +1 @@ -Subproject commit 07b50b1a81caf2ce0eae0029dd4385820a5a200e +Subproject commit f48cbf22f3cf85e73f2dd778c3764ad430cd30e8