Add fcntl
This commit is contained in:
parent
5fd7b2b71d
commit
8b56d14e41
|
@ -4,8 +4,8 @@ use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
|
||||||
use spin::{Mutex, Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
use spin::{Mutex, Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||||
|
|
||||||
use sync::WaitCondition;
|
use sync::WaitCondition;
|
||||||
use syscall::error::{Error, Result, EBADF, EPIPE};
|
use syscall::error::{Error, Result, EBADF, EINVAL, EPIPE};
|
||||||
use syscall::flag::O_NONBLOCK;
|
use syscall::flag::{F_GETFL, F_SETFL, O_NONBLOCK};
|
||||||
use syscall::scheme::Scheme;
|
use syscall::scheme::Scheme;
|
||||||
|
|
||||||
/// Pipes list
|
/// 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 read_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
|
||||||
let write_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 read = PipeRead::new(flags);
|
||||||
let write = PipeWrite::new(&read);
|
let write = PipeWrite::new(flags, &read);
|
||||||
pipes.0.insert(read_id, read);
|
pipes.0.insert(read_id, read);
|
||||||
pipes.1.insert(write_id, write);
|
pipes.1.insert(write_id, write);
|
||||||
(read_id, write_id)
|
(read_id, write_id)
|
||||||
|
@ -42,17 +42,25 @@ pub fn pipe(flags: usize) -> (usize, usize) {
|
||||||
pub struct PipeScheme;
|
pub struct PipeScheme;
|
||||||
|
|
||||||
impl Scheme for 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 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 {
|
if let Some(pipe) = read_option {
|
||||||
let pipe_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
|
let pipe_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
|
||||||
pipes.0.insert(pipe_id, pipe);
|
pipes.0.insert(pipe_id, pipe);
|
||||||
return Ok(pipe_id);
|
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 {
|
if let Some(pipe) = write_option {
|
||||||
let pipe_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
|
let pipe_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
|
||||||
pipes.1.insert(pipe_id, pipe);
|
pipes.1.insert(pipe_id, pipe);
|
||||||
|
@ -63,12 +71,9 @@ impl Scheme for PipeScheme {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
|
fn read(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
|
||||||
let pipe_option = {
|
let pipes = pipes();
|
||||||
let pipes = pipes();
|
|
||||||
pipes.0.get(&id).map(|pipe| pipe.clone())
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(pipe) = pipe_option {
|
if let Some(pipe) = pipes.0.get(&id) {
|
||||||
pipe.read(buf)
|
pipe.read(buf)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::new(EBADF))
|
Err(Error::new(EBADF))
|
||||||
|
@ -76,18 +81,29 @@ impl Scheme for PipeScheme {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write(&self, id: usize, buf: &[u8]) -> Result<usize> {
|
fn write(&self, id: usize, buf: &[u8]) -> Result<usize> {
|
||||||
let pipe_option = {
|
let pipes = pipes();
|
||||||
let pipes = pipes();
|
|
||||||
pipes.1.get(&id).map(|pipe| pipe.clone())
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(pipe) = pipe_option {
|
if let Some(pipe) = pipes.1.get(&id) {
|
||||||
pipe.write(buf)
|
pipe.write(buf)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::new(EBADF))
|
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> {
|
fn fsync(&self, _id: usize) -> Result<usize> {
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
@ -103,9 +119,8 @@ impl Scheme for PipeScheme {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read side of a pipe
|
/// Read side of a pipe
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct PipeRead {
|
pub struct PipeRead {
|
||||||
flags: usize,
|
flags: AtomicUsize,
|
||||||
condition: Arc<WaitCondition>,
|
condition: Arc<WaitCondition>,
|
||||||
vec: Arc<Mutex<VecDeque<u8>>>
|
vec: Arc<Mutex<VecDeque<u8>>>
|
||||||
}
|
}
|
||||||
|
@ -113,12 +128,31 @@ pub struct PipeRead {
|
||||||
impl PipeRead {
|
impl PipeRead {
|
||||||
pub fn new(flags: usize) -> Self {
|
pub fn new(flags: usize) -> Self {
|
||||||
PipeRead {
|
PipeRead {
|
||||||
flags: flags,
|
flags: AtomicUsize::new(flags),
|
||||||
condition: Arc::new(WaitCondition::new()),
|
condition: Arc::new(WaitCondition::new()),
|
||||||
vec: Arc::new(Mutex::new(VecDeque::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> {
|
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||||
loop {
|
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);
|
return Ok(0);
|
||||||
} else {
|
} else {
|
||||||
self.condition.wait();
|
self.condition.wait();
|
||||||
|
@ -149,20 +183,40 @@ impl PipeRead {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read side of a pipe
|
/// Read side of a pipe
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct PipeWrite {
|
pub struct PipeWrite {
|
||||||
|
flags: AtomicUsize,
|
||||||
condition: Arc<WaitCondition>,
|
condition: Arc<WaitCondition>,
|
||||||
vec: Weak<Mutex<VecDeque<u8>>>
|
vec: Weak<Mutex<VecDeque<u8>>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PipeWrite {
|
impl PipeWrite {
|
||||||
pub fn new(read: &PipeRead) -> Self {
|
pub fn new(flags: usize, read: &PipeRead) -> Self {
|
||||||
PipeWrite {
|
PipeWrite {
|
||||||
|
flags: AtomicUsize::new(flags),
|
||||||
condition: read.condition.clone(),
|
condition: read.condition.clone(),
|
||||||
vec: Arc::downgrade(&read.vec),
|
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> {
|
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||||
if let Some(vec_lock) = self.vec.upgrade() {
|
if let Some(vec_lock) = self.vec.upgrade() {
|
||||||
let mut vec = vec_lock.lock();
|
let mut vec = vec_lock.lock();
|
||||||
|
|
|
@ -10,7 +10,7 @@ pub use self::syscall::flag::*;
|
||||||
pub use self::syscall::{
|
pub use self::syscall::{
|
||||||
clock_gettime, clone, execve as exec, exit, futex, getpid, kill, nanosleep, setgid, setuid, waitpid,
|
clock_gettime, clone, execve as exec, exit, futex, getpid, kill, nanosleep, setgid, setuid, waitpid,
|
||||||
chdir, getcwd, open, mkdir, rmdir, unlink, dup, pipe2,
|
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
|
//TODO: Thread local
|
||||||
|
@ -81,7 +81,3 @@ pub extern "C" fn sbrk(n: isize) -> *mut u8 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// } ralloc shims
|
// } ralloc shims
|
||||||
|
|
||||||
pub unsafe fn fcntl(_fd: usize, _cmd: c_int, _arg: c_int) -> c_int {
|
|
||||||
cvt(Err(Error::new(ENOSYS)))
|
|
||||||
}
|
|
||||||
|
|
2
rust
2
rust
|
@ -1 +1 @@
|
||||||
Subproject commit 0bb9a959074bb7f027cf05a240a0044116fa0ab0
|
Subproject commit a0b5dfef2a36a15f76476a9d6bb7184a701d0d3c
|
2
syscall
2
syscall
|
@ -1 +1 @@
|
||||||
Subproject commit 07b50b1a81caf2ce0eae0029dd4385820a5a200e
|
Subproject commit f48cbf22f3cf85e73f2dd778c3764ad430cd30e8
|
Loading…
Reference in a new issue