From 94a1a0fa0c2166328c10257280dd63dd97cd60d5 Mon Sep 17 00:00:00 2001 From: ticki Date: Mon, 29 Aug 2016 11:58:31 +0200 Subject: [PATCH] Newtype file descriptors. To avoid various bugs regarding the typing of file descriptors, we newtype them into a simple wrapper type. - Document some stuff. --- kernel/context/mod.rs | 12 +++++++++++- kernel/scheme/debug.rs | 8 ++++---- kernel/scheme/mod.rs | 15 +++++++++------ 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/kernel/context/mod.rs b/kernel/context/mod.rs index 5487780..f669a2d 100644 --- a/kernel/context/mod.rs +++ b/kernel/context/mod.rs @@ -25,6 +25,7 @@ pub struct ContextList { } impl ContextList { + /// Create a new context list. pub fn new() -> Self { ContextList { map: BTreeMap::new(), @@ -32,14 +33,17 @@ impl ContextList { } } + /// Get the nth context. pub fn get(&self, id: usize) -> Option<&RwLock> { self.map.get(&id) } + /// Get the current context. pub fn current(&self) -> Option<&RwLock> { self.map.get(&CONTEXT_ID.load(Ordering::SeqCst)) } + /// Create a new context. pub fn new_context(&mut self) -> Result<&RwLock> { if self.next_id >= CONTEXT_MAX_CONTEXTS { self.next_id = 1; @@ -55,10 +59,13 @@ impl ContextList { let id = self.next_id; self.next_id += 1; + assert!(self.map.insert(id, RwLock::new(Context::new(id))).is_none()); - Ok(self.map.get(&id).expect("failed to insert new context")) + + Ok(self.map.get(&id).expect("Failed to insert new context. ID is out of bounds.")) } + /// Spawn a context from a function. pub fn spawn(&mut self, func: extern fn()) -> Result<&RwLock> { let context_lock = self.new_context()?; { @@ -107,6 +114,9 @@ pub fn contexts_mut() -> RwLockWriteGuard<'static, ContextList> { } /// Switch to the next context +/// +/// # Safety +/// /// Do not call this while holding locks! pub unsafe fn context_switch() { // current.arch.switch_to(&mut next.arch); diff --git a/kernel/scheme/debug.rs b/kernel/scheme/debug.rs index 0555b09..5767507 100644 --- a/kernel/scheme/debug.rs +++ b/kernel/scheme/debug.rs @@ -1,7 +1,7 @@ use core::str; use syscall::Result; -use super::Scheme; +use super::{Scheme, Fd}; pub struct DebugScheme; @@ -14,21 +14,21 @@ impl Scheme for DebugScheme { /// Read the file `number` into the `buffer` /// /// Returns the number of bytes read - fn read(&mut self, _file: usize, _buffer: &mut [u8]) -> Result { + fn read(&mut self, _file: Fd, _buffer: &mut [u8]) -> Result { Ok(0) } /// Write the `buffer` to the `file` /// /// Returns the number of bytes written - fn write(&mut self, _file: usize, buffer: &[u8]) -> Result { + fn write(&mut self, _file: Fd, buffer: &[u8]) -> Result { //TODO: Write bytes, do not convert to str print!("{}", unsafe { str::from_utf8_unchecked(buffer) }); Ok(buffer.len()) } /// Close the file `number` - fn close(&mut self, _file: usize) -> Result<()> { + fn close(&mut self, _file: Fd) -> Result<()> { Ok(()) } } diff --git a/kernel/scheme/mod.rs b/kernel/scheme/mod.rs index d01931c..2e1c015 100644 --- a/kernel/scheme/mod.rs +++ b/kernel/scheme/mod.rs @@ -17,8 +17,11 @@ use syscall::Result; use self::debug::DebugScheme; +pub use self::fd::Fd; + /// Debug scheme pub mod debug; +mod fd; /// Scheme list type pub type SchemeList = BTreeMap, Arc>>>; @@ -50,16 +53,16 @@ pub trait Scheme { /// Returns a file descriptor or an error fn open(&mut self, path: &[u8], flags: usize) -> Result; - /// Read the file `number` into the `buffer` + /// Read from some file descriptor into the `buffer` /// /// Returns the number of bytes read - fn read(&mut self, file: usize, buffer: &mut [u8]) -> Result; + fn read(&mut self, fd: Fd, buffer: &mut [u8]) -> Result; - /// Write the `buffer` to the `file` + /// Write the `buffer` to the file descriptor /// /// Returns the number of bytes written - fn write(&mut self, file: usize, buffer: &[u8]) -> Result; + fn write(&mut self, fd: Fd, buffer: &[u8]) -> Result; - /// Close the file `number` - fn close(&mut self, file: usize) -> Result<()>; + /// Close the file descriptor + fn close(&mut self, fd: Fd) -> Result<()>; }