diff --git a/error/src/lib.rs b/error/src/lib.rs index dbb3f6f..1f63038 100644 --- a/error/src/lib.rs +++ b/error/src/lib.rs @@ -16,5 +16,6 @@ pub enum Errno { NotImplemented, OutOfMemory, TimedOut, + TooManyDescriptors, WouldBlock, } diff --git a/init/src/main.rs b/init/src/main.rs index cf68ab7..237de55 100644 --- a/init/src/main.rs +++ b/init/src/main.rs @@ -7,12 +7,27 @@ extern crate libusr; #[no_mangle] fn main() -> i32 { + let mut buf = [0; 128]; + loop { - println!("Hello to stdout"); - trace!("Hello from userspace"); + let count = unsafe { + libusr::sys::sys_read(0, buf.as_mut_ptr(), buf.len()) + }; + if count < 0 { + trace!("Read from stdio failed"); + break; + } + let count = count as usize; + + if let Ok(s) = core::str::from_utf8(&buf[..count]) { + println!("Got string {:?}", s); + } else { + println!("Got string (non-utf8) {:?}", &buf[..count]); + } unsafe { libusr::sys::sys_ex_nanosleep(1_000_000_000, core::ptr::null_mut()); } } + -1 } diff --git a/kernel/src/dev/tty.rs b/kernel/src/dev/tty.rs index f7f0f2d..7f2a636 100644 --- a/kernel/src/dev/tty.rs +++ b/kernel/src/dev/tty.rs @@ -106,6 +106,7 @@ impl CharRing { }; if byte == b'\n' || byte == b'\r' { + dev.write(true, b"\r\n").ok(); break; } diff --git a/kernel/src/proc/mod.rs b/kernel/src/proc/mod.rs index 0fe6641..261784f 100644 --- a/kernel/src/proc/mod.rs +++ b/kernel/src/proc/mod.rs @@ -95,9 +95,9 @@ pub unsafe fn enter(initrd: Option<(usize, usize)>) -> ! { // Open stdout { let mut io = proc.io.lock(); - let node = io.ioctx.as_ref().unwrap().find(None, "/dev/uart0", true).unwrap(); + let node = io.ioctx().find(None, "/dev/uart0", true).unwrap(); // TODO fd cloning? - io.files.push(node.open().unwrap()); + io.place_file(node.open().unwrap()).unwrap(); } Process::execve(|space| elf::load_elf(space, &mut file), 0).unwrap(); diff --git a/kernel/src/proc/process.rs b/kernel/src/proc/process.rs index c2230a2..0212af5 100644 --- a/kernel/src/proc/process.rs +++ b/kernel/src/proc/process.rs @@ -6,7 +6,7 @@ use crate::mem::{ }; use crate::proc::{PROCESSES, SCHED}; use crate::sync::IrqSafeSpinLock; -use alloc::{vec::Vec, rc::Rc}; +use alloc::{rc::Rc, collections::BTreeMap}; use core::cell::UnsafeCell; use core::fmt; use core::sync::atomic::{AtomicU32, Ordering}; @@ -53,9 +53,11 @@ struct ProcessInner { /// pub struct ProcessIo { /// - pub ioctx: Option, + ioctx: Option, /// - pub files: Vec, + files: BTreeMap, + /// + file_bitmap: u64, } /// Structure describing an operating system process @@ -134,6 +136,41 @@ impl fmt::Display for Pid { } } +impl ProcessIo { + /// + pub fn file(&mut self, idx: usize) -> Result<&mut File, Errno> { + self.files.get_mut(&idx).ok_or(Errno::InvalidFile) + } + + /// + pub fn ioctx(&mut self) -> &mut Ioctx { + self.ioctx.as_mut().unwrap() + } + + /// + pub fn place_file(&mut self, file: File) -> Result { + for bit in 0..64 { + if self.file_bitmap & (1 << bit) == 0 { + if self.files.insert(bit, file).is_some() { + panic!("Open file bitmap is broken"); + } + self.file_bitmap |= 1 << bit; + return Ok(bit); + } + } + Err(Errno::TooManyDescriptors) + } + + /// + pub fn new() -> Self { + Self { + files: BTreeMap::new(), + file_bitmap: 0, + ioctx: None + } + } +} + impl Process { const USTACK_VIRT_TOP: usize = 0x100000000; const USTACK_PAGES: usize = 4; @@ -223,10 +260,7 @@ impl Process { let id = Pid::new_kernel(); let res = Rc::new(Self { ctx: UnsafeCell::new(Context::kernel(entry as usize, arg)), - io: IrqSafeSpinLock::new(ProcessIo { - ioctx: None, - files: Vec::new(), - }), + io: IrqSafeSpinLock::new(ProcessIo::new()), inner: IrqSafeSpinLock::new(ProcessInner { id, exit: None, diff --git a/kernel/src/syscall.rs b/kernel/src/syscall.rs index 45e4d8e..97848c0 100644 --- a/kernel/src/syscall.rs +++ b/kernel/src/syscall.rs @@ -115,25 +115,23 @@ pub unsafe fn syscall(num: usize, args: &[usize]) -> Result { let proc = Process::current(); let mut io = proc.io.lock(); - let node = io.ioctx.as_ref().unwrap().find(None, path, true)?; + let node = io.ioctx().find(None, path, true)?; // TODO check access - io.files.push(node.open()?); - - Ok(io.files.len() - 1) + io.place_file(node.open()?) } abi::SYS_READ => { let proc = Process::current(); let mut io = proc.io.lock(); let buf = validate_user_ptr(args[1], args[2])?; - io.files[args[0]].read(buf) + io.file(args[0])?.read(buf) } abi::SYS_WRITE => { let proc = Process::current(); let mut io = proc.io.lock(); let buf = validate_user_ptr(args[1], args[2])?; - io.files[args[0]].write(buf) + io.file(args[0])?.write(buf) } // Extra system calls