1
0
mirror of https://github.com/rcore-os/rCore.git synced 2024-11-22 08:06:17 +04:00
This commit is contained in:
function2-llx 2020-05-30 04:23:04 +08:00
parent d70b920b1c
commit 0d3c207cd2
14 changed files with 223 additions and 37 deletions

View File

@ -8,17 +8,25 @@ use rcore_fs::vfs::*;
use crate::fs::ioctl::*;
use crate::sync::Condvar;
use crate::sync::SpinNoIrqLock as Mutex;
use spin::RwLock;
#[derive(Default)]
pub struct Stdin {
buf: Mutex<VecDeque<char>>,
pub pushed: Condvar,
winsize: RwLock<Winsize>,
termios: RwLock<Termois>,
}
impl Stdin {
pub fn push(&self, c: char) {
self.buf.lock().push_back(c);
self.pushed.notify_one();
let lflag = LocalModes::from_bits_truncate(self.termios.read().lflag);
if lflag.contains(LocalModes::ISIG) && [0x3, 0o34, 0o32, 0o31].contains(&(c as i32)) {
} else {
self.buf.lock().push_back(c);
self.pushed.notify_one();
}
}
pub fn pop(&self) -> char {
#[cfg(feature = "board_k210")]
@ -46,7 +54,9 @@ impl Stdin {
}
#[derive(Default)]
pub struct Stdout;
pub struct Stdout {
winsize: RwLock<Winsize>,
}
lazy_static! {
pub static ref STDIN: Arc<Stdin> = Arc::new(Stdin::default());
@ -74,8 +84,19 @@ impl INode for Stdin {
}
fn io_control(&self, cmd: u32, data: usize) -> Result<usize> {
match cmd as usize {
TCGETS | TCSETS | TIOCGWINSZ => {
// pretend to be tty
TIOCGWINSZ => {
let winsize = data as *mut Winsize;
unsafe { *winsize = *self.winsize.read(); }
Ok(0)
}
TCGETS => {
let termois = data as *mut Termois;
unsafe { *termois = *self.termios.read(); }
Ok(0)
}
TCSETS => {
let termois = data as *const Termois;
unsafe { *self.termios.write() = *termois; }
Ok(0)
}
TIOCGPGRP => {
@ -120,7 +141,12 @@ impl INode for Stdout {
}
fn io_control(&self, cmd: u32, data: usize) -> Result<usize> {
match cmd as usize {
TCSETS | TCGETS | TIOCGWINSZ | TIOCSPGRP => {
TIOCGWINSZ => {
let winsize = data as *mut Winsize;
unsafe { *winsize = *self.winsize.read(); }
Ok(0)
}
TCSETS | TCGETS | TIOCSPGRP => {
// pretend to be tty
Ok(0)
}

View File

@ -2,10 +2,19 @@ use core::any::Any;
use rcore_fs::vfs::*;
pub use super::{STDIN, STDOUT};
use crate::syscall::SysError;
use rcore_fs::vfs::FsError::NotSupported;
use rcore_thread::std_thread::current;
use crate::processor;
use crate::process::current_thread;
use spin::RwLock;
use crate::fs::ioctl::*;
/// Ref: [https://linux.die.net/man/4/tty]
// Ref: [https://linux.die.net/man/4/tty]
#[derive(Default)]
pub struct TtyINode;
pub struct TtyINode {
foreground_pgid: RwLock<i32>,
}
impl INode for TtyINode {
/// Read bytes at `offset` into `buf`, return the number of bytes read.
@ -27,6 +36,25 @@ impl INode for TtyINode {
})
}
fn io_control(&self, cmd: u32, data: usize) -> Result<usize> {
let cmd = cmd as usize;
match cmd {
TIOCGPGRP => {
// TODO: check the pointer?
let argp = data as *mut i32; // pid_t
unsafe { *argp = *self.foreground_pgid.read() };
Ok(0)
}
TIOCSPGRP => {
let fpgid = unsafe { *(data as *const i32) };
*self.foreground_pgid.write() = fpgid;
info!("tty: set foreground process group to {}", fpgid);
Ok(0)
}
_ => Err(NotSupported)
}
}
/// Get metadata of the INode
fn metadata(&self) -> Result<Metadata> {
Ok(Metadata {

View File

@ -12,9 +12,11 @@ pub const F_SETLKW: usize = 7; /* Set record locking info (blocking). */
const F_LINUX_SPECIFIC_BASE: usize = 1024;
pub const FD_CLOEXEC: usize = 1;
pub const F_DUPFD_CLOEXEC: usize = F_LINUX_SPECIFIC_BASE + 6;
pub const O_NONBLOCK: usize = 04000;
pub const O_CLOEXEC: usize = 02000000; /* set close_on_exec */
pub const O_NONBLOCK: usize = 0o4000;
pub const O_APPEND: usize = 0o2000;
pub const O_CLOEXEC: usize = 0o2000000; /* set close_on_exec */
pub const AT_SYMLINK_NOFOLLOW: usize = 0x100;

View File

@ -15,6 +15,7 @@ use crate::sync::SpinLock as Mutex;
use crate::syscall::SysError::{EAGAIN, ESPIPE};
use bitflags::_core::cell::Cell;
use spin::RwLock;
use crate::fs::fcntl::{O_NONBLOCK, O_APPEND};
enum Flock {
None = 0,
@ -92,11 +93,17 @@ impl FileHandle {
}
pub fn set_options(&self, arg: usize) {
if arg & 0x800 > 0 {
self.description.write().options.nonblock = true;
}
let options = &mut self.description.write().options;
options.nonblock = (arg & O_NONBLOCK) != 0;
// TODO: handle append
// options.append = (arg & O_APPEND) != 0;
}
// pub fn get_options(&self) -> usize {
// let options = self.description.read().options;
// let mut ret = 0 as usize;
// }
pub fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
let len = self.read_at(self.description.read().offset as usize, buf)?;
self.description.write().offset += len as u64;

View File

@ -47,17 +47,12 @@ impl FileLike {
Ok(len)
}
pub fn ioctl(&mut self, request: usize, arg1: usize, arg2: usize, arg3: usize) -> SysResult {
match request {
// TODO: place flags & path in FileLike instead of FileHandle/Socket
FIOCLEX => Ok(0),
FIONBIO => Ok(0),
_ => match self {
FileLike::File(file) => file.io_control(request as u32, arg1).map_err(Into::into),
FileLike::Socket(socket) => socket.ioctl(request, arg1, arg2, arg3),
FileLike::EpollInstance(_) => {
return Err(SysError::ENOSYS);
}
},
match self {
FileLike::File(file) => file.io_control(request as u32, arg1).map_err(Into::into),
FileLike::Socket(socket) => socket.ioctl(request, arg1, arg2, arg3),
FileLike::EpollInstance(_) => {
return Err(SysError::ENOSYS);
}
}
}
pub fn mmap(&mut self, area: MMapArea) -> SysResult {

View File

@ -3,6 +3,9 @@
// higher 2 bits: 01 = write, 10 = read
#![allow(dead_code)]
use bitflags::*;
#[cfg(not(target_arch = "mips"))]
pub const TCGETS: usize = 0x5401;
#[cfg(target_arch = "mips")]
@ -44,3 +47,62 @@ pub const FIOCLEX: usize = 0x6601;
// rustc using pipe and ioctl pipe file with this request id
// for non-blocking/blocking IO control setting
pub const FIONBIO: usize = 0x5421;
bitflags! {
pub struct LocalModes : u32 {
const ISIG = 0o000001;
const ICANON = 0o000002;
const ECHO = 0o000010;
const ECHOE = 0o000020;
const ECHOK = 0o000040;
const ECHONL = 0o000100;
const NOFLSH = 0o000200;
const TOSTOP = 0o000400;
const IEXTEN = 0o100000;
const XCASE = 0o000004;
const ECHOCTL = 0o001000;
const ECHOPRT = 0o002000;
const ECHOKE = 0o004000;
const FLUSHO = 0o010000;
const PENDIN = 0o040000;
const EXTPROC = 0o200000;
}
}
// Ref: https://www.man7.org/linux/man-pages/man3/termios.3.html
#[repr(C)]
#[derive(Clone, Copy)]
pub struct Termois {
pub iflag: u32,
pub oflag: u32,
pub cflag: u32,
pub lflag: u32,
pub line: u8,
pub cc: [u8; 32],
pub ispeed: u32,
pub ospeed: u32,
}
impl Default for Termois {
fn default() -> Self {
Termois {
iflag: 27906,
oflag: 5,
cflag: 1215,
lflag: 35387,
line: 0,
cc: [3, 28, 127, 21, 4, 0, 1, 0, 17, 19, 26, 255, 18, 15, 23, 22, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
ispeed: 0,
ospeed: 0,
}
}
}
#[repr(C)]
#[derive(Clone, Copy, Default)]
pub struct Winsize {
row: u16,
ws_col: u16,
xpixel: u16,
ypixel: u16,
}

View File

@ -23,7 +23,7 @@ pub mod epoll;
pub mod fcntl;
mod file;
mod file_like;
mod ioctl;
pub mod ioctl;
mod pipe;
mod pseudo;

View File

@ -56,7 +56,7 @@ impl Pid {
/// Return whether this pid represents the init process
pub fn is_init(&self) -> bool {
self.0 == 0
self.0 == 1
}
}
@ -77,6 +77,7 @@ pub struct Process {
// relationship
pub pid: Pid, // i.e. tgid, usually the tid of first thread
pub pgid: i32,
// avoid deadlock, put pid out
pub parent: (Pid, Weak<Mutex<Process>>),
pub children: Vec<(Pid, Weak<Mutex<Process>>)>,
@ -141,6 +142,7 @@ impl Thread {
semaphores: SemProc::default(),
futexes: BTreeMap::default(),
pid: Pid(0),
pgid: -1, // kernel thread do not have a process?
parent: (Pid(0), Weak::new()),
children: Vec::new(),
threads: Vec::new(),
@ -333,6 +335,7 @@ impl Thread {
futexes: BTreeMap::default(),
semaphores: SemProc::default(),
pid: Pid(0),
pgid: 0,
parent: (Pid(0), Weak::new()),
children: Vec::new(),
threads: Vec::new(),
@ -363,6 +366,7 @@ impl Thread {
futexes: BTreeMap::default(),
semaphores: proc.semaphores.clone(),
pid: Pid(0),
pgid: proc.pgid,
parent: (proc.pid.clone(), Arc::downgrade(&self.proc)),
children: Vec::new(),
threads: Vec::new(),
@ -415,8 +419,8 @@ impl Process {
fn add_to_table(mut self) -> Arc<Mutex<Self>> {
let mut process_table = PROCESSES.write();
// assign pid
let pid = (0..).find(|i| process_table.get(i).is_none()).unwrap();
// assign pid, do not start from 0
let pid = (1..).find(|i| process_table.get(i).is_none()).unwrap();
self.pid = Pid(pid);
// put to process table

View File

@ -142,6 +142,7 @@ impl Condvar {
let mut queue = self.wait_queue.lock();
if let Some(t) = queue.front() {
self.epoll_callback(t);
// info!("nofity thread: {}", t.id());
t.unpark();
queue.pop_front();
}

View File

@ -18,7 +18,7 @@ use bitvec::prelude::{BitSlice, BitVec, Lsb0};
use super::*;
use crate::fs::epoll::EpollInstance;
use crate::fs::fcntl::{O_CLOEXEC, O_NONBLOCK};
use crate::fs::fcntl::{O_CLOEXEC, O_NONBLOCK, F_SETFD, FD_CLOEXEC};
use crate::fs::FileLike;
use crate::process::Process;
use crate::syscall::SysError::{EINVAL, ESPIPE};
@ -861,9 +861,25 @@ impl Syscall<'_> {
"ioctl: fd: {}, request: {:#x}, args: {:#x} {:#x} {:#x}",
fd, request, arg1, arg2, arg3
);
let mut proc = self.process();
let file_like = proc.get_file_like(fd)?;
file_like.ioctl(request, arg1, arg2, arg3)
use crate::fs::ioctl::*;
match request {
FIOCLEX => self.sys_fcntl(fd, F_SETFD, FD_CLOEXEC),
FIONCLEX => self.sys_fcntl(fd, F_SETFD, 0),
FIONBIO => {
let data = arg1 as *const i32;
let val = unsafe { *data };
if val == 0 {
self.sys_fcntl(fd, F_SETFD, 0)
} else {
self.sys_fcntl(fd, F_SETFD, O_NONBLOCK)
}
}
_ => {
let mut proc = self.process();
let file_like = proc.get_file_like(fd)?;
file_like.ioctl(request, arg1, arg2, arg3)
}
}
}
pub fn sys_chdir(&mut self, path: *const u8) -> SysResult {
@ -1270,6 +1286,9 @@ impl Syscall<'_> {
file.set_options(arg);
Ok(0)
}
F_GETFL => {
self.unimplemented("F_GETFL", Ok(0))
}
F_DUPFD_CLOEXEC => {
info!("fcntl: dupfd_cloexec: arg: {:#x}", arg);
// let file_like = proc.get_file_like(fd1)?.clone();

View File

@ -329,10 +329,10 @@ impl Syscall<'_> {
SYS_SETUID => self.unimplemented("setuid", Ok(0)),
SYS_GETEUID => self.unimplemented("geteuid", Ok(0)),
SYS_GETEGID => self.unimplemented("getegid", Ok(0)),
SYS_SETPGID => self.unimplemented("setpgid", Ok(0)),
SYS_GETPPID => self.sys_getppid(),
SYS_SETSID => self.unimplemented("setsid", Ok(0)),
SYS_GETPGID => self.unimplemented("getpgid", Ok(0)),
SYS_GETPGID => self.sys_getpgid(args[0]),
SYS_SETPGID => self.sys_setpgid(args[0], args[1]),
SYS_GETGROUPS => self.unimplemented("getgroups", Ok(0)),
SYS_RT_SIGTIMEDWAIT => self.unimplemented("rt_sigtimedwait", Ok(0)),
SYS_SETGROUPS => self.unimplemented("setgroups", Ok(0)),

View File

@ -2,6 +2,8 @@
use super::*;
use crate::fs::FileLike;
use alloc::sync::Weak;
use crate::syscall::SysError::ESRCH;
impl Syscall<'_> {
/// Fork the current process. Return the child's PID.
@ -10,7 +12,7 @@ impl Syscall<'_> {
let pid = new_thread.proc.lock().pid.get();
let tid = thread_manager().add(new_thread);
thread_manager().detach(tid);
info!("fork: {} -> {}", thread::current().id(), pid);
info!("fork: {} -> {}", self.thread.proc.lock().pid, pid);
Ok(pid)
}
@ -266,6 +268,43 @@ impl Syscall<'_> {
Ok(self.process().pid.get())
}
pub fn sys_getpgid(&self, mut pid: usize) -> SysResult {
if pid == 0 {
pid = self.process().pid.get();
}
info!("getpgid: get pgid of process {}", pid);
let process_table = PROCESSES.read();
// let process_table: BTreeMap<usize, Weak<Mutex<Process>>> = BTreeMap::new();
let proc = process_table.get(&pid);
if (proc.is_some()) {
let lock = proc.unwrap().upgrade().unwrap();
let proc = lock.lock();
// let proc = proc.unwrap().upgrade().unwrap().lock();
Ok(proc.pgid as usize)
} else {
Err(ESRCH)
}
}
pub fn sys_setpgid(&self, mut pid: usize, pgid: usize) -> SysResult {
if pid == 0 {
pid = self.process().pid.get();
}
info!("setpgid: set pgid of process {} to {}", pid, pgid);
let process_table = PROCESSES.read();
// let process_table: BTreeMap<usize, Weak<Mutex<Process>>> = BTreeMap::new();
let proc = process_table.get(&pid);
if (proc.is_some()) {
// TODO: check process pid is the child of calling process
let lock = proc.unwrap().upgrade().unwrap();
let mut proc = lock.lock();
proc.pgid = pgid as i32;
Ok(0)
} else {
Err(ESRCH)
}
}
/// Get the current thread id
pub fn sys_gettid(&mut self) -> SysResult {
info!("gettid");

View File

@ -50,7 +50,9 @@ impl Syscall<'_> {
*oldset = self.thread.sig_mask;
}
if !set.is_null() {
let set = *unsafe { self.vm().check_read_ptr(set)? };
// let set = *unsafe { self.vm().check_read_ptr(set)? };
let set = unsafe { self.vm().check_read_ptr(set)? };
let set = *set; // prevent deadlock when page fault
const BLOCK: usize = 0;
const UNBLOCK: usize = 1;
const SETMASK: usize = 2;

View File

@ -1,9 +1,10 @@
use crate::arch::cpu;
use crate::arch::interrupt::TrapFrame;
use crate::arch::interrupt::{TrapFrame, syscall};
use crate::consts::INFORM_PER_MSEC;
use crate::process::*;
use crate::sync::Condvar;
use rcore_thread::std_thread as thread;
use rcore_thread::std_thread::current;
pub static mut TICK: usize = 0;