Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add some syscalls and add stdin #131

Merged
merged 22 commits into from
Aug 11, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions linux-object/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ hashbrown = "0.7"
zircon-object = { path = "../zircon-object", features = ["elf"] }
kernel-hal = { path = "../kernel-hal" }
downcast-rs = { git = "https://github.com/rcore-os/downcast-rs", rev = "a632ce1", default-features = false }
lazy_static = { version = "1.4", features = ["spin_no_std"] }
rcore-fs = { git = "https://github.com/rcore-os/rcore-fs", rev = "e17b27b" }
rcore-fs-sfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "e17b27b" }
rcore-fs-ramfs = { git = "https://github.com/rcore-os/rcore-fs", rev = "e17b27b" }
Expand Down
5 changes: 3 additions & 2 deletions linux-object/src/fs/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,9 @@ impl File {
match self.inode.read_at(offset as usize, buf) {
Ok(read_len) => return Ok(read_len),
Err(FsError::Again) => {
//thread::yield_now();
unimplemented!()
// thread::yield_now();
// unimplemented!()
self.poll()?;
}
Err(err) => return Err(err.into()),
}
Expand Down
142 changes: 77 additions & 65 deletions linux-object/src/fs/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,78 +2,90 @@
#![allow(unsafe_code)]

use super::ioctl::*;
use alloc::collections::VecDeque;
use alloc::sync::Arc;
use core::any::Any;
use lazy_static::lazy_static;
use rcore_fs::vfs::*;
//use spin::Mutex;
use spin::Mutex;

//#[derive(Default)]
//pub struct Stdin {
// buf: Mutex<VecDeque<char>>,
// pub pushed: Condvar,
//}
//
//impl Stdin {
// pub fn push(&self, c: char) {
// self.buf.lock().push_back(c);
// self.pushed.notify_one();
// }
// pub fn pop(&self) -> char {
// loop {
// let mut buf_lock = self.buf.lock();
// match buf_lock.pop_front() {
// Some(c) => return c,
// None => {
// self.pushed.wait(buf_lock);
// }
// }
// }
// }
// pub fn can_read(&self) -> bool {
// return self.buf.lock().len() > 0;
// }
//}
lazy_static! {
pub static ref STDIN: Arc<Stdin> = Default::default();
pub static ref STDOUT: Arc<Stdout> = Default::default();
}

#[derive(Default)]
pub struct Stdin {
buf: Mutex<VecDeque<char>>,
// TODO: add signal
}

impl Stdin {
pub fn push(&self, c: char) {
self.buf.lock().push_back(c);
// self.pushed.notify_one();
}
pub fn pop(&self) -> char {
loop {
let mut buf_lock = self.buf.lock();
if let Some(c) = buf_lock.pop_front() {
return c;
} else {
// self.pushed.wait(buf_lock);
}
}
}
pub fn can_read(&self) -> bool {
self.buf.lock().len() > 0
}
}

#[derive(Default)]
pub struct Stdout;

//impl INode for Stdin {
// fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
// if self.can_read() {
// buf[0] = self.pop() as u8;
// Ok(1)
// } else {
// Err(FsError::Again)
// }
// }
// fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result<usize> {
// unimplemented!()
// }
// fn poll(&self) -> Result<PollStatus> {
// Ok(PollStatus {
// read: self.can_read(),
// write: false,
// error: false,
// })
// }
// fn io_control(&self, cmd: u32, data: usize) -> Result<()> {
// match cmd as usize {
// TCGETS | TIOCGWINSZ | TIOCSPGRP => {
// // pretend to be tty
// Ok(())
// }
// TIOCGPGRP => {
// // pretend to be have a tty process group
// // TODO: verify pointer
// unsafe { *(data as *mut u32) = 0 };
// Ok(())
// }
// _ => Err(FsError::NotSupported),
// }
// }
// fn as_any_ref(&self) -> &dyn Any {
// self
// }
//}
impl INode for Stdin {
fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result<usize> {
if self.can_read() {
buf[0] = self.pop() as u8;
Ok(1)
} else {
let mut buffer = [0; 255];
let len = kernel_hal::serial_read(&mut buffer);
for c in &buffer[..len] {
self.push((*c).into());
}
Err(FsError::Again)
}
}
fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result<usize> {
unimplemented!()
}
fn poll(&self) -> Result<PollStatus> {
Ok(PollStatus {
read: self.can_read(),
write: false,
error: false,
})
}
fn io_control(&self, cmd: u32, data: usize) -> Result<()> {
match cmd as usize {
TCGETS | TIOCGWINSZ | TIOCSPGRP => {
// pretend to be tty
Ok(())
}
TIOCGPGRP => {
// pretend to be have a tty process group
// TODO: verify pointer
unsafe { *(data as *mut u32) = 0 };
Ok(())
}
_ => Err(FsError::NotSupported),
}
}
fn as_any_ref(&self) -> &dyn Any {
self
}
}

impl INode for Stdout {
fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result<usize> {
Expand Down
4 changes: 2 additions & 2 deletions linux-object/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ impl LinuxProcess {
/// Create a new process.
pub fn new(rootfs: Arc<dyn FileSystem>) -> Self {
let stdin = File::new(
Arc::new(Stdout), // FIXME: stdin
STDIN.clone(), // FIXME: stdin
OpenOptions {
read: true,
write: false,
Expand All @@ -160,7 +160,7 @@ impl LinuxProcess {
String::from("/dev/stdin"),
) as Arc<dyn FileLike>;
let stdout = File::new(
Arc::new(Stdout), // TODO: open from '/dev/stdout'
STDOUT.clone(), // TODO: open from '/dev/stdout'
OpenOptions {
read: false,
write: true,
Expand Down
38 changes: 38 additions & 0 deletions linux-syscall/src/file/poll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,41 @@
//! - select4
//! - poll, ppoll
//! - epoll: create, ctl, wait

use super::*;

impl Syscall<'_> {
/// Wait for some event on a file descriptor
pub fn sys_poll(
&mut self,
_ufds: UserInOutPtr<PollFd>,
_nfds: usize,
_timeout_msecs: usize,
) -> SysResult {
// TODO
Ok(0)
}
}

#[repr(C)]
#[derive(Debug)]
pub struct PollFd {
fd: u32,
yukiiiteru marked this conversation as resolved.
Show resolved Hide resolved
events: PollEvents,
revents: PollEvents,
}

bitflags! {
pub struct PollEvents: u16 {
/// There is data to read.
const IN = 0x0001;
/// Writing is now possible.
const OUT = 0x0004;
/// Error condition (return only)
const ERR = 0x0008;
/// Hang up (return only)
const HUP = 0x0010;
/// Invalid request: fd not open (return only)
const INVAL = 0x0020;
}
}
6 changes: 3 additions & 3 deletions linux-syscall/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ impl Syscall<'_> {
Sys::TKILL => self.unimplemented("tkill", Ok(0)),

// time
// Sys::NANOSLEEP => self.sys_nanosleep(a0.into()),
Sys::NANOSLEEP => self.sys_nanosleep(a0.into()).await,
Sys::SETITIMER => self.unimplemented("setitimer", Ok(0)),
// Sys::GETTIMEOFDAY => self.sys_gettimeofday(a0.into(), a1.into()),
Sys::CLOCK_GETTIME => self.sys_clock_gettime(a0, a1.into()),
Expand Down Expand Up @@ -218,7 +218,7 @@ impl Syscall<'_> {
Sys::MEMBARRIER => self.unimplemented("membarrier", Ok(0)),
// Sys::PRLIMIT64 => self.sys_prlimit64(a0, a1, a2.into(), a3.into()),
// Sys::REBOOT => self.sys_reboot(a0 as u32, a1 as u32, a2 as u32, a3.into()),
// Sys::GETRANDOM => self.sys_getrandom(a0.into(), a1 as usize, a2 as u32),
Sys::GETRANDOM => self.sys_getrandom(a0.into(), a1 as usize, a2 as u32),
Sys::RT_SIGQUEUEINFO => self.unimplemented("rt_sigqueueinfo", Ok(0)),

// kernel module
Expand All @@ -243,7 +243,7 @@ impl Syscall<'_> {
Sys::OPEN => self.sys_open(a0.into(), a1, a2),
Sys::STAT => self.sys_stat(a0.into(), a1.into()),
Sys::LSTAT => self.sys_lstat(a0.into(), a1.into()),
// Sys::POLL => self.sys_poll(a0.into(), a1, a2),
Sys::POLL => self.sys_poll(a0.into(), a1, a2),
Sys::ACCESS => self.sys_access(a0.into(), a1),
// Sys::PIPE => self.sys_pipe(a0.into()),
// Sys::SELECT => self.sys_select(a0, a1.into(), a2.into(), a3.into(), a4.into()),
Expand Down
17 changes: 17 additions & 0 deletions linux-syscall/src/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,23 @@ impl Syscall<'_> {
}
}
}

#[allow(unsafe_code)]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
yukiiiteru marked this conversation as resolved.
Show resolved Hide resolved
/// fills the buffer pointed to by `buf` with up to `buflen` random bytes.
/// - `buf` - buffer that needed to fill
/// - `buflen` - length of buffer
/// - `flag` - a bit mask that can contain zero or more of the following values ORed together:
/// - GRND_RANDOM
/// - GRND_NONBLOCK
/// - returns the number of bytes that were copied to the buffer buf.
pub fn sys_getrandom(&mut self, mut buf: UserOutPtr<u8>, len: usize, _flag: u32) -> SysResult {
// info!("getrandom: buf: {:?}, len: {:?}, falg {:?}", buf, len, flag);
let mut buffer = vec![0u8; len];
kernel_hal::fill_random(&mut buffer);
buf.write_array(&buffer[..len])?;
Ok(len)
}
}

bitflags! {
Expand Down
65 changes: 57 additions & 8 deletions linux-syscall/src/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

use super::*;
use bitflags::bitflags;
use core::fmt::{Debug, Formatter, Result};
use core::time::Duration;
use linux_object::fs::INodeExt;
use linux_object::loader::LinuxElfLoader;
use linux_object::thread::ThreadExt;
Expand Down Expand Up @@ -251,14 +253,24 @@ impl Syscall<'_> {
Err(LxError::ENOSYS)
}

// pub fn sys_nanosleep(&self, req: *const TimeSpec) -> SysResult {
// let time = unsafe { *self.vm().check_read_ptr(req)? };
// info!("nanosleep: time: {:#?}", time);
// // TODO: handle spurious wakeup
// thread::sleep(time.to_duration());
// Ok(0)
// }
//
/// Allows the calling thread to sleep for
/// an interval specified with nanosecond precision
pub async fn sys_nanosleep(&self, deadline: Deadline) -> SysResult {
yukiiiteru marked this conversation as resolved.
Show resolved Hide resolved
info!("nanosleep: deadline={:?}", deadline);
if deadline.0 <= 0 {
kernel_hal::yield_now().await;
} else {
self.thread
.blocking_run(
kernel_hal::sleep_until(deadline.into()),
ThreadState::BlockedSleeping,
Duration::from_nanos(u64::max_value()),
)
.await?;
}
Ok(0)
}

// pub fn sys_set_priority(&self, priority: usize) -> SysResult {
// let pid = thread::current().id();
// thread_manager().set_priority(pid, priority as u8);
Expand Down Expand Up @@ -359,3 +371,40 @@ impl RegExt for GeneralRegs {
GeneralRegs { rax: 0, ..*regs }
}
}

#[repr(transparent)]
pub struct Deadline(i64);

impl From<usize> for Deadline {
fn from(x: usize) -> Self {
Deadline(x as i64)
}
}

impl Deadline {
pub fn is_positive(&self) -> bool {
self.0.is_positive()
}

pub fn forever() -> Self {
Deadline(i64::max_value())
}
}

impl From<Deadline> for Duration {
fn from(deadline: Deadline) -> Self {
Duration::from_nanos(deadline.0.max(0) as u64)
}
}

impl Debug for Deadline {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
if self.0 <= 0 {
write!(f, "NoWait")
} else if self.0 == i64::max_value() {
write!(f, "Forever")
} else {
write!(f, "At({:?})", Duration::from_nanos(self.0 as u64))
}
}
}