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 sys_getrandom, add stdin without condvar #130

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
149 changes: 84 additions & 65 deletions linux-object/src/fs/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,77 +3,96 @@

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

//#[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 Condvar
// 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;
}
}

#[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 offset != 0 {
unimplemented!()
}
*/
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
2 changes: 1 addition & 1 deletion linux-syscall/src/lib.rs
Original file line number Diff line number Diff line change
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 as *mut u8, a1 as usize, a2 as u32),
Sys::RT_SIGQUEUEINFO => self.unimplemented("rt_sigqueueinfo", Ok(0)),

// kernel module
Expand Down
48 changes: 26 additions & 22 deletions linux-syscall/src/misc.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#![allow(missing_docs)]

use super::time::TimeSpec;
use super::*;
use bitflags::bitflags;
use kernel_hal::timer_now;
use core::slice::from_raw_parts_mut;

impl Syscall<'_> {
#[cfg(target_arch = "x86_64")]
/// set architecture-specific thread state
/// for x86_64 currently
pub fn sys_arch_prctl(&mut self, code: i32, addr: usize) -> SysResult {
const ARCH_SET_FS: i32 = 0x1002;
match code {
Expand All @@ -18,31 +20,31 @@ impl Syscall<'_> {
}
}

/// get name and information about current kernel
pub fn sys_uname(&self, buf: UserOutPtr<u8>) -> SysResult {
info!("uname: buf={:?}", buf);

let strings = ["Linux", "orz", "0.1.0", "1", "machine", "domain"];
let strings = ["rCore", "orz", "0.1.0", "1", "machine", "domain"];
for (i, &s) in strings.iter().enumerate() {
const OFFSET: usize = 65;
buf.add(i * OFFSET).write_cstring(s)?;
}
Ok(0)
}

/// provides a method for waiting until a certain condition becomes true.
/// - `uaddr` - points to the futex word.
/// - `op` - the operation to perform on the futex
/// - `val` - a value whose meaning and purpose depends on op
/// - `timeout` - not support now
/// TODO: support timeout
pub async fn sys_futex(
&self,
uaddr: usize,
op: u32,
val: i32,
timeout: UserInPtr<TimeSpec>,
) -> SysResult {
bitflags! {
struct FutexFlags: u32 {
const WAIT = 0;
const WAKE = 1;
const PRIVATE = 0x80;
}
}
let op = FutexFlags::from_bits_truncate(op);
info!(
"futex: uaddr: {:#x}, op: {:?}, val: {}, timeout_ptr: {:?}",
Expand Down Expand Up @@ -72,18 +74,20 @@ impl Syscall<'_> {
}
}
}
}

bitflags! {
/// for op argument in futex()
struct FutexFlags: u32 {
/// tests that the value at the futex word pointed
/// to by the address uaddr still contains the expected value val,
/// and if so, then sleeps waiting for a FUTEX_WAKE operation on the futex word.
const WAIT = 0;
/// wakes at most val of the waiters that are waiting on the futex word at the address uaddr.
const WAKE = 1;
/// can be employed with all futex operations, tells the kernel that the futex is process-private and not shared with another process
const PRIVATE = 0x80;
#[allow(unsafe_code)]
pub fn sys_getrandom(&mut self, buf: *mut u8, len: usize, _flag: u32) -> SysResult {
//info!("getrandom: buf: {:?}, len: {:?}, falg {:?}", buf, len,flag);
let slice = unsafe { from_raw_parts_mut(buf, len) };
let mut i = 0;
for elm in slice {
// to prevent overflow
let time = timer_now();
*elm = (i + time.as_nanos() as u8 as u16) as u8;
i += 1;
}

Ok(len)
}

}