This commit is contained in:
Yifan Wu 2020-12-14 16:18:33 +08:00
parent e93a4a0b76
commit 2d34cab989
14 changed files with 218 additions and 18 deletions

View file

@ -11,10 +11,11 @@ pub trait File : Any + Send + Sync {
}
impl dyn File {
#[allow(unused)]
pub fn downcast_ref<T: File>(&self) -> Option<&T> {
self.as_any_ref().downcast_ref::<T>()
}
}
pub use pipe::{Pipe};
pub use pipe::{Pipe, make_pipe};
pub use stdio::{Stdin, Stdout};

View file

@ -44,7 +44,7 @@ pub struct PipeRingBuffer {
head: usize,
tail: usize,
status: RingBufferStatus,
write_end: Option<Weak<Mutex<Pipe>>>,
write_end: Option<Weak<Pipe>>,
}
impl PipeRingBuffer {
@ -57,7 +57,7 @@ impl PipeRingBuffer {
write_end: None,
}
}
pub fn set_write_end(&mut self, write_end: &Arc<Mutex<Pipe>>) {
pub fn set_write_end(&mut self, write_end: &Arc<Pipe>) {
self.write_end = Some(Arc::downgrade(write_end));
}
pub fn write_byte(&mut self, byte: u8) {
@ -101,14 +101,14 @@ impl PipeRingBuffer {
}
/// Return (read_end, write_end)
pub fn make_pipe() -> (Arc<Mutex<Pipe>>, Arc<Mutex<Pipe>>) {
pub fn make_pipe() -> (Arc<Pipe>, Arc<Pipe>) {
let buffer = Arc::new(Mutex::new(PipeRingBuffer::new()));
let read_end = Arc::new(Mutex::new(
let read_end = Arc::new(
Pipe::read_end_with_buffer(buffer.clone())
));
let write_end = Arc::new(Mutex::new(
);
let write_end = Arc::new(
Pipe::write_end_with_buffer(buffer.clone())
));
);
buffer.lock().set_write_end(&write_end);
(read_end, write_end)
}

View file

@ -1,5 +1,5 @@
use super::File;
use crate::mm::{UserBuffer, UserBufferIterator};
use crate::mm::{UserBuffer};
use crate::sbi::console_getchar;
use crate::task::suspend_current_and_run_next;
use core::any::Any;

View file

@ -164,7 +164,11 @@ pub fn translated_byte_buffer(token: usize, ptr: *const u8, len: usize) -> Vec<&
vpn.step();
let mut end_va: VirtAddr = vpn.into();
end_va = end_va.min(VirtAddr::from(end));
v.push(&mut ppn.get_bytes_array()[start_va.page_offset()..end_va.page_offset()]);
if end_va.page_offset() == 0 {
v.push(&mut ppn.get_bytes_array()[start_va.page_offset()..]);
} else {
v.push(&mut ppn.get_bytes_array()[start_va.page_offset()..end_va.page_offset()]);
}
start = end_va.into();
}
v

View file

@ -1,5 +1,6 @@
use crate::mm::{UserBuffer, translated_byte_buffer};
use crate::mm::{UserBuffer, translated_byte_buffer, translated_refmut};
use crate::task::{current_user_token, current_task};
use crate::fs::{make_pipe};
pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize {
let token = current_user_token();
@ -12,9 +13,9 @@ pub fn sys_write(fd: usize, buf: *const u8, len: usize) -> isize {
let file = file.clone();
// release Task lock manually to avoid deadlock
drop(inner);
file.write(UserBuffer {
buffers: translated_byte_buffer(token, buf, len),
}) as isize
file.write(
UserBuffer::new(translated_byte_buffer(token, buf, len))
) as isize
} else {
-1
}
@ -31,10 +32,37 @@ pub fn sys_read(fd: usize, buf: *const u8, len: usize) -> isize {
let file = file.clone();
// release Task lock manually to avoid deadlock
drop(inner);
file.read(UserBuffer {
buffers: translated_byte_buffer(token, buf, len),
}) as isize
file.read(
UserBuffer::new(translated_byte_buffer(token, buf, len))
) as isize
} else {
-1
}
}
pub fn sys_close(fd: usize) -> isize {
let task = current_task().unwrap();
let mut inner = task.acquire_inner_lock();
if fd >= inner.fd_table.len() {
return -1;
}
if inner.fd_table[fd].is_none() {
return -1;
}
inner.fd_table[fd].take();
0
}
pub fn sys_pipe(pipe: *mut usize) -> isize {
let task = current_task().unwrap();
let token = current_user_token();
let mut inner = task.acquire_inner_lock();
let (pipe_read, pipe_write) = make_pipe();
let read_fd = inner.alloc_fd();
inner.fd_table[read_fd] = Some(pipe_read);
let write_fd = inner.alloc_fd();
inner.fd_table[write_fd] = Some(pipe_write);
*translated_refmut(token, pipe) = read_fd;
*translated_refmut(token, unsafe { pipe.add(1) }) = write_fd;
0
}

View file

@ -1,3 +1,5 @@
const SYSCALL_CLOSE: usize = 57;
const SYSCALL_PIPE: usize = 59;
const SYSCALL_READ: usize = 63;
const SYSCALL_WRITE: usize = 64;
const SYSCALL_EXIT: usize = 93;
@ -16,6 +18,8 @@ use process::*;
pub fn syscall(syscall_id: usize, args: [usize; 3]) -> isize {
match syscall_id {
SYSCALL_CLOSE => sys_close(args[0]),
SYSCALL_PIPE => sys_pipe(args[0] as *mut usize),
SYSCALL_READ => sys_read(args[0], args[1] as *const u8, args[2]),
SYSCALL_WRITE => sys_write(args[0], args[1] as *const u8, args[2]),
SYSCALL_EXIT => sys_exit(args[0] as i32),

View file

@ -45,6 +45,15 @@ impl TaskControlBlockInner {
pub fn is_zombie(&self) -> bool {
self.get_status() == TaskStatus::Zombie
}
pub fn alloc_fd(&mut self) -> usize {
if let Some(fd) = (0..self.fd_table.len())
.find(|fd| self.fd_table[*fd].is_none()) {
fd
} else {
self.fd_table.push(None);
self.fd_table.len() - 1
}
}
}
impl TaskControlBlock {
@ -78,7 +87,11 @@ impl TaskControlBlock {
children: Vec::new(),
exit_code: 0,
fd_table: vec![
// 0 -> stdin
Some(Arc::new(Stdin)),
// 1 -> stdout
Some(Arc::new(Stdout)),
// 2 -> stderr
Some(Arc::new(Stdout)),
],
}),
@ -181,6 +194,7 @@ impl TaskControlBlock {
pub fn getpid(&self) -> usize {
self.pid.0
}
}
#[derive(Copy, Clone, PartialEq)]

View file

@ -108,6 +108,7 @@ pub fn trap_return() -> ! {
}
let restore_va = __restore as usize - __alltraps as usize + TRAMPOLINE;
unsafe {
llvm_asm!("fence.i" :::: "volatile");
llvm_asm!("jr $0" :: "r"(restore_va), "{a0}"(trap_cx_ptr), "{a1}"(user_satp) :: "volatile");
}
panic!("Unreachable in back_to_user!");