Merge branch 'cap2' of https://github.com/Yoric/redox into Yoric-cap2

This commit is contained in:
Jeremy Soller 2016-11-15 14:05:43 -07:00
commit 297b6e09fc
18 changed files with 254 additions and 108 deletions

108
kernel/common/int_like.rs Normal file
View file

@ -0,0 +1,108 @@
//! Helpers used to define types that are backed by integers (typically `usize`),
//! without compromising safety.
//!
//! # Example
//!
//! ```
//! /// Define an opaque type `Pid` backed by a `usize`.
//! int_like!(Pid, usize);
//!
//! const ZERO: Pid = Pid::from(0);
//! ```
//!
//! # Example
//!
//! ```
//! /// Define opaque types `Pid` and `AtomicPid`, backed respectively by a `usize`
//! /// and a `AtomicUsize`.
//!
//! int_like!(Pid, AtomicPid, usize, AtomicUsize);
//!
//! const ZERO: Pid = Pid::from(0);
//! let ATOMIC_PID: AtomicPid = AtomicPid::default();
//! ```
#[macro_export]
macro_rules! int_like {
($new_type_name:ident, $backing_type: ident) => {
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
pub struct $new_type_name($backing_type);
impl $new_type_name {
pub const fn into(self) -> $backing_type {
self.0
}
pub const fn from(x: $backing_type) -> Self {
$new_type_name(x)
}
}
};
($new_type_name:ident, $new_atomic_type_name: ident, $backing_type:ident, $backing_atomic_type:ident) => {
int_like!($new_type_name, $backing_type);
/// A mutable holder for T that can safely be shared among threads.
/// Runtime equivalent to using `AtomicUsize`, just type-safer.
pub struct $new_atomic_type_name {
container: $backing_atomic_type,
}
impl $new_atomic_type_name {
pub const fn new(x: $new_type_name) -> Self {
$new_atomic_type_name {
container: $backing_atomic_type::new(x.into())
}
}
pub const fn default() -> Self {
Self::new($new_type_name::from(0))
}
pub fn load(&self, order: ::core::sync::atomic::Ordering) -> $new_type_name {
$new_type_name::from(self.container.load(order))
}
pub fn store(&self, val: $new_type_name, order: ::core::sync::atomic::Ordering) {
self.container.store(val.into(), order)
}
#[allow(dead_code)]
pub fn swap(&self, val: $new_type_name, order: ::core::sync::atomic::Ordering) -> $new_type_name {
$new_type_name::from(self.container.swap(val.into(), order))
}
#[allow(dead_code)]
pub fn compare_and_swap(&self, current: $new_type_name, new: $new_type_name, order: ::core::sync::atomic::Ordering) -> $new_type_name {
$new_type_name::from(self.container.compare_and_swap(current.into(), new.into(), order))
}
#[allow(dead_code)]
pub fn compare_exchange(&self, current: $new_type_name, new: $new_type_name, success: ::core::sync::atomic::Ordering, failure: ::core::sync::atomic::Ordering) -> ::core::result::Result<$new_type_name, $new_type_name> {
match self.container.compare_exchange(current.into(), new.into(), success, failure) {
Ok(result) => Ok($new_type_name::from(result)),
Err(result) => Err($new_type_name::from(result))
}
}
#[allow(dead_code)]
pub fn compare_exchange_weak(&self, current: $new_type_name, new: $new_type_name, success: ::core::sync::atomic::Ordering, failure: ::core::sync::atomic::Ordering) -> ::core::result::Result<$new_type_name, $new_type_name> {
match self.container.compare_exchange_weak(current.into(), new.into(), success, failure) {
Ok(result) => Ok($new_type_name::from(result)),
Err(result) => Err($new_type_name::from(result))
}
}
}
}
}
#[cfg(test)]
fn test() {
use core::mem::size_of;
use ::core::sync::atomic::AtomicUsize;
// Generate type `usize_like`.
int_like!(UsizeLike, usize);
const ZERO: UsizeLike = UsizeLike::from(0);
assert_eq!(size_of::<UsizeLike>(), size_of::<usize>());
// Generate types `usize_like` and `AtomicUsize`.
int_like!(UsizeLike2, AtomicUsizeLike, usize, AtomicUsize);
assert_eq!(size_of::<UsizeLike2>(), size_of::<usize>());
assert_eq!(size_of::<AtomicUsizeLike>(), size_of::<AtomicUsize>());
}

3
kernel/common/mod.rs Normal file
View file

@ -0,0 +1,3 @@
#[macro_use]
#[macro_export]
pub mod int_like;

View file

@ -6,9 +6,14 @@ use spin::Mutex;
use arch; use arch;
use context::file::File; use context::file::File;
use context::memory::{Grant, Memory, SharedMemory, Tls}; use context::memory::{Grant, Memory, SharedMemory, Tls};
use scheme::FileHandle;
use syscall::data::Event; use syscall::data::Event;
use sync::{WaitMap, WaitQueue}; use sync::{WaitMap, WaitQueue};
/// Unique identifier for a context (i.e. `pid`).
use ::core::sync::atomic::AtomicUsize;
int_like!(ContextId, AtomicContextId, usize, AtomicUsize);
/// The status of a context - used for scheduling /// The status of a context - used for scheduling
/// See syscall::process::waitpid and the sync module for examples of usage /// See syscall::process::waitpid and the sync module for examples of usage
#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Eq, PartialEq)]
@ -22,9 +27,9 @@ pub enum Status {
#[derive(Debug)] #[derive(Debug)]
pub struct Context { pub struct Context {
/// The ID of this context /// The ID of this context
pub id: usize, pub id: ContextId,
/// The ID of the parent context /// The ID of the parent context
pub ppid: usize, pub ppid: ContextId,
/// The real user id /// The real user id
pub ruid: u32, pub ruid: u32,
/// The real group id /// The real group id
@ -42,7 +47,7 @@ pub struct Context {
/// Context is halting parent /// Context is halting parent
pub vfork: bool, pub vfork: bool,
/// Context is being waited on /// Context is being waited on
pub waitpid: Arc<WaitMap<usize, usize>>, pub waitpid: Arc<WaitMap<ContextId, usize>>,
/// Context should wake up at specified time /// Context should wake up at specified time
pub wake: Option<(u64, u64)>, pub wake: Option<(u64, u64)>,
/// The architecture specific context /// The architecture specific context
@ -75,10 +80,10 @@ pub struct Context {
impl Context { impl Context {
/// Create a new context /// Create a new context
pub fn new(id: usize) -> Context { pub fn new(id: ContextId) -> Context {
Context { Context {
id: id, id: id,
ppid: 0, ppid: ContextId::from(0),
ruid: 0, ruid: 0,
rgid: 0, rgid: 0,
euid: 0, euid: 0,
@ -180,28 +185,28 @@ impl Context {
/// Add a file to the lowest available slot. /// Add a file to the lowest available slot.
/// Return the file descriptor number or None if no slot was found /// Return the file descriptor number or None if no slot was found
pub fn add_file(&self, file: File) -> Option<usize> { pub fn add_file(&self, file: File) -> Option<FileHandle> {
let mut files = self.files.lock(); let mut files = self.files.lock();
for (i, mut file_option) in files.iter_mut().enumerate() { for (i, mut file_option) in files.iter_mut().enumerate() {
if file_option.is_none() { if file_option.is_none() {
*file_option = Some(file); *file_option = Some(file);
return Some(i); return Some(FileHandle::from(i));
} }
} }
let len = files.len(); let len = files.len();
if len < super::CONTEXT_MAX_FILES { if len < super::CONTEXT_MAX_FILES {
files.push(Some(file)); files.push(Some(file));
Some(len) Some(FileHandle::from(len))
} else { } else {
None None
} }
} }
/// Get a file /// Get a file
pub fn get_file(&self, i: usize) -> Option<File> { pub fn get_file(&self, i: FileHandle) -> Option<File> {
let files = self.files.lock(); let files = self.files.lock();
if i < files.len() { if i.into() < files.len() {
files[i] files[i.into()]
} else { } else {
None None
} }
@ -209,10 +214,10 @@ impl Context {
/// Remove a file /// Remove a file
// TODO: adjust files vector to smaller size if possible // TODO: adjust files vector to smaller size if possible
pub fn remove_file(&self, i: usize) -> Option<File> { pub fn remove_file(&self, i: FileHandle) -> Option<File> {
let mut files = self.files.lock(); let mut files = self.files.lock();
if i < files.len() { if i.into() < files.len() {
files[i].take() files[i.into()].take()
} else { } else {
None None
} }

View file

@ -3,6 +3,7 @@ use collections::BTreeMap;
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
use context; use context;
use scheme::{FileHandle, SchemeId};
use sync::WaitQueue; use sync::WaitQueue;
use syscall::data::Event; use syscall::data::Event;
@ -10,14 +11,14 @@ type EventList = Weak<WaitQueue<Event>>;
#[derive(PartialEq, Eq, PartialOrd, Ord)] #[derive(PartialEq, Eq, PartialOrd, Ord)]
pub struct RegKey { pub struct RegKey {
scheme_id: usize, scheme_id: SchemeId,
event_id: usize, event_id: usize,
} }
#[derive(PartialEq, Eq, PartialOrd, Ord)] #[derive(PartialEq, Eq, PartialOrd, Ord)]
pub struct ProcessKey { pub struct ProcessKey {
context_id: usize, context_id: context::context::ContextId,
fd: usize, fd: FileHandle,
} }
type Registry = BTreeMap<RegKey, BTreeMap<ProcessKey, EventList>>; type Registry = BTreeMap<RegKey, BTreeMap<ProcessKey, EventList>>;
@ -39,7 +40,7 @@ pub fn registry_mut() -> RwLockWriteGuard<'static, Registry> {
REGISTRY.call_once(init_registry).write() REGISTRY.call_once(init_registry).write()
} }
pub fn register(fd: usize, scheme_id: usize, event_id: usize) -> bool { pub fn register(fd: FileHandle, scheme_id: SchemeId, event_id: usize) -> bool {
let (context_id, events) = { let (context_id, events) = {
let contexts = context::contexts(); let contexts = context::contexts();
let context_lock = contexts.current().expect("event::register: No context"); let context_lock = contexts.current().expect("event::register: No context");
@ -66,7 +67,7 @@ pub fn register(fd: usize, scheme_id: usize, event_id: usize) -> bool {
} }
} }
pub fn unregister(fd: usize, scheme_id: usize, event_id: usize) { pub fn unregister(fd: FileHandle, scheme_id: SchemeId, event_id: usize) {
let mut registry = registry_mut(); let mut registry = registry_mut();
let mut remove = false; let mut remove = false;
@ -91,7 +92,7 @@ pub fn unregister(fd: usize, scheme_id: usize, event_id: usize) {
} }
} }
pub fn trigger(scheme_id: usize, event_id: usize, flags: usize, data: usize) { pub fn trigger(scheme_id: SchemeId, event_id: usize, flags: usize, data: usize) {
let registry = registry(); let registry = registry();
let key = RegKey { let key = RegKey {
scheme_id: scheme_id, scheme_id: scheme_id,
@ -101,7 +102,7 @@ pub fn trigger(scheme_id: usize, event_id: usize, flags: usize, data: usize) {
for entry in event_lists.iter() { for entry in event_lists.iter() {
if let Some(event_list) = entry.1.upgrade() { if let Some(event_list) = entry.1.upgrade() {
event_list.send(Event { event_list.send(Event {
id: (entry.0).fd, id: (entry.0).fd.into(),
flags: flags, flags: flags,
data: data data: data
}); });

View file

@ -1,11 +1,13 @@
//! File struct //! File struct
use scheme::SchemeId;
/// A file /// A file
//TODO: Close on exec //TODO: Close on exec
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct File { pub struct File {
/// The scheme that this file refers to /// The scheme that this file refers to
pub scheme: usize, pub scheme: SchemeId,
/// The number the scheme uses to refer to this file /// The number the scheme uses to refer to this file
pub number: usize, pub number: usize,
/// If events are on, this is the event ID /// If events are on, this is the event ID

View file

@ -7,11 +7,11 @@ use spin::RwLock;
use arch; use arch;
use syscall::error::{Result, Error, EAGAIN}; use syscall::error::{Result, Error, EAGAIN};
use super::context::Context; use super::context::{Context, ContextId};
/// Context list type /// Context list type
pub struct ContextList { pub struct ContextList {
map: BTreeMap<usize, Arc<RwLock<Context>>>, map: BTreeMap<ContextId, Arc<RwLock<Context>>>,
next_id: usize next_id: usize
} }
@ -25,7 +25,7 @@ impl ContextList {
} }
/// Get the nth context. /// Get the nth context.
pub fn get(&self, id: usize) -> Option<&Arc<RwLock<Context>>> { pub fn get(&self, id: ContextId) -> Option<&Arc<RwLock<Context>>> {
self.map.get(&id) self.map.get(&id)
} }
@ -34,7 +34,7 @@ impl ContextList {
self.map.get(&super::CONTEXT_ID.load(Ordering::SeqCst)) self.map.get(&super::CONTEXT_ID.load(Ordering::SeqCst))
} }
pub fn iter(&self) -> ::collections::btree_map::Iter<usize, Arc<RwLock<Context>>> { pub fn iter(&self) -> ::collections::btree_map::Iter<ContextId, Arc<RwLock<Context>>> {
self.map.iter() self.map.iter()
} }
@ -44,7 +44,7 @@ impl ContextList {
self.next_id = 1; self.next_id = 1;
} }
while self.map.contains_key(&self.next_id) { while self.map.contains_key(&ContextId::from(self.next_id)) {
self.next_id += 1; self.next_id += 1;
} }
@ -52,7 +52,7 @@ impl ContextList {
return Err(Error::new(EAGAIN)); return Err(Error::new(EAGAIN));
} }
let id = self.next_id; let id = ContextId::from(self.next_id);
self.next_id += 1; self.next_id += 1;
assert!(self.map.insert(id, Arc::new(RwLock::new(Context::new(id)))).is_none()); assert!(self.map.insert(id, Arc::new(RwLock::new(Context::new(id)))).is_none());
@ -85,7 +85,7 @@ impl ContextList {
Ok(context_lock) Ok(context_lock)
} }
pub fn remove(&mut self, id: usize) -> Option<Arc<RwLock<Context>>> { pub fn remove(&mut self, id: ContextId) -> Option<Arc<RwLock<Context>>> {
self.map.remove(&id) self.map.remove(&id)
} }
} }

View file

@ -1,11 +1,12 @@
//! Context management //! Context management
use alloc::boxed::Box; use alloc::boxed::Box;
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; use core::sync::atomic::Ordering;
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
pub use self::context::{Context, Status}; pub use self::context::{Context, Status};
pub use self::list::ContextList; pub use self::list::ContextList;
pub use self::switch::switch; pub use self::switch::switch;
pub use context::context::ContextId;
/// Context struct /// Context struct
mod context; mod context;
@ -35,7 +36,7 @@ pub const CONTEXT_MAX_FILES: usize = 65536;
static CONTEXTS: Once<RwLock<ContextList>> = Once::new(); static CONTEXTS: Once<RwLock<ContextList>> = Once::new();
#[thread_local] #[thread_local]
static CONTEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT; static CONTEXT_ID: context::AtomicContextId = context::AtomicContextId::default();
pub fn init() { pub fn init() {
let mut contexts = contexts_mut(); let mut contexts = contexts_mut();
@ -69,6 +70,6 @@ pub fn contexts_mut() -> RwLockWriteGuard<'static, ContextList> {
CONTEXTS.call_once(init_contexts).write() CONTEXTS.call_once(init_contexts).write()
} }
pub fn context_id() -> usize { pub fn context_id() -> context::ContextId {
CONTEXT_ID.load(Ordering::SeqCst) CONTEXT_ID.load(Ordering::SeqCst)
} }

View file

@ -43,6 +43,12 @@ extern crate goblin;
extern crate spin; extern crate spin;
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use scheme::FileHandle;
#[macro_use]
#[macro_export]
/// Shared data structures
pub mod common;
/// Context management /// Context management
pub mod context; pub mod context;
@ -87,9 +93,9 @@ pub fn cpu_count() -> usize {
pub extern fn userspace_init() { pub extern fn userspace_init() {
assert_eq!(syscall::chdir(b"initfs:bin"), Ok(0)); assert_eq!(syscall::chdir(b"initfs:bin"), Ok(0));
assert_eq!(syscall::open(b"debug:", 0), Ok(0)); assert_eq!(syscall::open(b"debug:", 0).map(FileHandle::into), Ok(0));
assert_eq!(syscall::open(b"debug:", 0), Ok(1)); assert_eq!(syscall::open(b"debug:", 0).map(FileHandle::into), Ok(1));
assert_eq!(syscall::open(b"debug:", 0), Ok(2)); assert_eq!(syscall::open(b"debug:", 0).map(FileHandle::into), Ok(2));
syscall::exec(b"initfs:bin/init", &[]).expect("failed to execute initfs:init"); syscall::exec(b"initfs:bin/init", &[]).expect("failed to execute initfs:init");
@ -99,7 +105,7 @@ pub extern fn userspace_init() {
/// Allow exception handlers to send signal to arch-independant kernel /// Allow exception handlers to send signal to arch-independant kernel
#[no_mangle] #[no_mangle]
pub extern fn ksignal(signal: usize) { pub extern fn ksignal(signal: usize) {
println!("SIGNAL {}, CPU {}, PID {}", signal, cpu_id(), context::context_id()); println!("SIGNAL {}, CPU {}, PID {:?}", signal, cpu_id(), context::context_id());
{ {
let contexts = context::contexts(); let contexts = context::contexts();
if let Some(context_lock) = contexts.current() { if let Some(context_lock) = contexts.current() {

View file

@ -1,14 +1,15 @@
use core::str; use core::str;
use core::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; use core::sync::atomic::Ordering;
use spin::Once; use spin::Once;
use context; use context;
use scheme::*;
use sync::WaitQueue; use sync::WaitQueue;
use syscall::error::*; use syscall::error::*;
use syscall::flag::EVENT_READ; use syscall::flag::EVENT_READ;
use syscall::scheme::Scheme; use syscall::scheme::Scheme;
pub static DEBUG_SCHEME_ID: AtomicUsize = ATOMIC_USIZE_INIT; pub static DEBUG_SCHEME_ID: AtomicSchemeId = ATOMIC_SCHEMEID_INIT;
/// Input queue /// Input queue
static INPUT: Once<WaitQueue<u8>> = Once::new(); static INPUT: Once<WaitQueue<u8>> = Once::new();

View file

@ -1,14 +1,15 @@
use core::{mem, str}; use core::{mem, str};
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; use core::sync::atomic::Ordering;
use spin::Mutex; use spin::Mutex;
use arch::interrupt::irq::acknowledge; use arch::interrupt::irq::acknowledge;
use context; use context;
use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT};
use syscall::error::*; use syscall::error::*;
use syscall::flag::EVENT_READ; use syscall::flag::EVENT_READ;
use syscall::scheme::Scheme; use syscall::scheme::Scheme;
pub static IRQ_SCHEME_ID: AtomicUsize = ATOMIC_USIZE_INIT; pub static IRQ_SCHEME_ID: AtomicSchemeId = ATOMIC_SCHEMEID_INIT;
/// IRQ queues /// IRQ queues
static ACKS: Mutex<[usize; 16]> = Mutex::new([0; 16]); static ACKS: Mutex<[usize; 16]> = Mutex::new([0; 16]);

View file

@ -9,7 +9,7 @@
use alloc::arc::Arc; use alloc::arc::Arc;
use alloc::boxed::Box; use alloc::boxed::Box;
use collections::BTreeMap; use collections::BTreeMap;
use core::sync::atomic::Ordering; use core::sync::atomic::{AtomicUsize, Ordering};
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
use syscall::error::*; use syscall::error::*;
@ -62,10 +62,19 @@ pub mod zero;
/// Limit on number of schemes /// Limit on number of schemes
pub const SCHEME_MAX_SCHEMES: usize = 65536; pub const SCHEME_MAX_SCHEMES: usize = 65536;
/// Unique identifier for a scheme.
int_like!(SchemeId, AtomicSchemeId, usize, AtomicUsize);
pub const ATOMIC_SCHEMEID_INIT: AtomicSchemeId = AtomicSchemeId::default();
/// Unique identifier for a file descriptor.
int_like!(FileHandle, AtomicFileHandle, usize, AtomicUsize);
/// Scheme list type /// Scheme list type
pub struct SchemeList { pub struct SchemeList {
map: BTreeMap<usize, Arc<Box<Scheme + Send + Sync>>>, map: BTreeMap<SchemeId, Arc<Box<Scheme + Send + Sync>>>,
names: BTreeMap<Box<[u8]>, usize>, names: BTreeMap<Box<[u8]>, SchemeId>,
next_id: usize next_id: usize
} }
@ -79,20 +88,20 @@ impl SchemeList {
} }
} }
pub fn iter(&self) -> ::collections::btree_map::Iter<usize, Arc<Box<Scheme + Send + Sync>>> { pub fn iter(&self) -> ::collections::btree_map::Iter<SchemeId, Arc<Box<Scheme + Send + Sync>>> {
self.map.iter() self.map.iter()
} }
pub fn iter_name(&self) -> ::collections::btree_map::Iter<Box<[u8]>, usize> { pub fn iter_name(&self) -> ::collections::btree_map::Iter<Box<[u8]>, SchemeId> {
self.names.iter() self.names.iter()
} }
/// Get the nth scheme. /// Get the nth scheme.
pub fn get(&self, id: usize) -> Option<&Arc<Box<Scheme + Send + Sync>>> { pub fn get(&self, id: SchemeId) -> Option<&Arc<Box<Scheme + Send + Sync>>> {
self.map.get(&id) self.map.get(&id)
} }
pub fn get_name(&self, name: &[u8]) -> Option<(usize, &Arc<Box<Scheme + Send + Sync>>)> { pub fn get_name(&self, name: &[u8]) -> Option<(SchemeId, &Arc<Box<Scheme + Send + Sync>>)> {
if let Some(&id) = self.names.get(name) { if let Some(&id) = self.names.get(name) {
self.get(id).map(|scheme| (id, scheme)) self.get(id).map(|scheme| (id, scheme))
} else { } else {
@ -101,7 +110,7 @@ impl SchemeList {
} }
/// Create a new scheme. /// Create a new scheme.
pub fn insert(&mut self, name: Box<[u8]>, scheme: Arc<Box<Scheme + Send + Sync>>) -> Result<usize> { pub fn insert(&mut self, name: Box<[u8]>, scheme: Arc<Box<Scheme + Send + Sync>>) -> Result<SchemeId> {
if self.names.contains_key(&name) { if self.names.contains_key(&name) {
return Err(Error::new(EEXIST)); return Err(Error::new(EEXIST));
} }
@ -110,7 +119,7 @@ impl SchemeList {
self.next_id = 1; self.next_id = 1;
} }
while self.map.contains_key(&self.next_id) { while self.map.contains_key(&SchemeId(self.next_id)) {
self.next_id += 1; self.next_id += 1;
} }
@ -118,12 +127,11 @@ impl SchemeList {
return Err(Error::new(EAGAIN)); return Err(Error::new(EAGAIN));
} }
let id = self.next_id; let id = SchemeId(self.next_id);
self.next_id += 1; self.next_id += 1;
assert!(self.map.insert(id, scheme).is_none()); assert!(self.map.insert(id, scheme).is_none());
assert!(self.names.insert(name, id).is_none()); assert!(self.names.insert(name, id).is_none());
Ok(id) Ok(id)
} }
} }

View file

@ -2,6 +2,7 @@ use alloc::arc::{Arc, Weak};
use collections::{BTreeMap, VecDeque}; use collections::{BTreeMap, VecDeque};
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use spin::{Mutex, Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; use spin::{Mutex, Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT};
use sync::WaitCondition; use sync::WaitCondition;
use syscall::error::{Error, Result, EAGAIN, EBADF, EINVAL, EPIPE}; use syscall::error::{Error, Result, EAGAIN, EBADF, EINVAL, EPIPE};
@ -9,7 +10,7 @@ use syscall::flag::{F_GETFL, F_SETFL, O_CLOEXEC, O_NONBLOCK};
use syscall::scheme::Scheme; use syscall::scheme::Scheme;
/// Pipes list /// Pipes list
pub static PIPE_SCHEME_ID: AtomicUsize = ATOMIC_USIZE_INIT; pub static PIPE_SCHEME_ID: AtomicSchemeId = ATOMIC_SCHEMEID_INIT;
static PIPE_NEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT; static PIPE_NEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT;
static PIPES: Once<RwLock<(BTreeMap<usize, Arc<PipeRead>>, BTreeMap<usize, Arc<PipeWrite>>)>> = Once::new(); static PIPES: Once<RwLock<(BTreeMap<usize, Arc<PipeRead>>, BTreeMap<usize, Arc<PipeWrite>>)>> = Once::new();

View file

@ -1,16 +1,16 @@
use alloc::arc::Arc; use alloc::arc::Arc;
use alloc::boxed::Box; use alloc::boxed::Box;
use collections::BTreeMap; use collections::BTreeMap;
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; use core::sync::atomic::{AtomicUsize, Ordering};
use spin::RwLock; use spin::RwLock;
use context; use context;
use syscall::error::*; use syscall::error::*;
use syscall::scheme::Scheme; use syscall::scheme::Scheme;
use scheme; use scheme::{self, AtomicSchemeId, ATOMIC_SCHEMEID_INIT};
use scheme::user::{UserInner, UserScheme}; use scheme::user::{UserInner, UserScheme};
pub static ROOT_SCHEME_ID: AtomicUsize = ATOMIC_USIZE_INIT; pub static ROOT_SCHEME_ID: AtomicSchemeId = ATOMIC_SCHEMEID_INIT;
pub struct RootScheme { pub struct RootScheme {
next_id: AtomicUsize, next_id: AtomicUsize,

View file

@ -83,8 +83,8 @@ pub fn resource() -> Result<Vec<u8>> {
let name = str::from_utf8(&name_bytes).unwrap_or(""); let name = str::from_utf8(&name_bytes).unwrap_or("");
string.push_str(&format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{}\n", string.push_str(&format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{}\n",
context.id, context.id.into(),
context.ppid, context.ppid.into(),
context.euid, context.euid,
context.egid, context.egid,
stat_string, stat_string,

View file

@ -1,6 +1,6 @@
use alloc::arc::{Arc, Weak}; use alloc::arc::{Arc, Weak};
use collections::BTreeMap; use collections::BTreeMap;
use core::sync::atomic::{AtomicUsize, AtomicU64, Ordering}; use core::sync::atomic::{AtomicU64, Ordering};
use core::{mem, slice, usize}; use core::{mem, slice, usize};
use spin::{Mutex, RwLock}; use spin::{Mutex, RwLock};
@ -10,6 +10,7 @@ use arch::paging::temporary_page::TemporaryPage;
use context::{self, Context}; use context::{self, Context};
use context::memory::Grant; use context::memory::Grant;
use scheme::root::ROOT_SCHEME_ID; use scheme::root::ROOT_SCHEME_ID;
use scheme::{AtomicSchemeId, ATOMIC_SCHEMEID_INIT};
use sync::{WaitQueue, WaitMap}; use sync::{WaitQueue, WaitMap};
use syscall::data::{Packet, Stat}; use syscall::data::{Packet, Stat};
use syscall::error::*; use syscall::error::*;
@ -20,7 +21,7 @@ use syscall::scheme::Scheme;
pub struct UserInner { pub struct UserInner {
handle_id: usize, handle_id: usize,
flags: usize, flags: usize,
pub scheme_id: AtomicUsize, pub scheme_id: AtomicSchemeId,
next_id: AtomicU64, next_id: AtomicU64,
context: Weak<RwLock<Context>>, context: Weak<RwLock<Context>>,
todo: WaitQueue<Packet>, todo: WaitQueue<Packet>,
@ -33,7 +34,7 @@ impl UserInner {
UserInner { UserInner {
handle_id: handle_id, handle_id: handle_id,
flags: flags, flags: flags,
scheme_id: AtomicUsize::new(0), scheme_id: ATOMIC_SCHEMEID_INIT,
next_id: AtomicU64::new(1), next_id: AtomicU64::new(1),
context: context, context: context,
todo: WaitQueue::new(), todo: WaitQueue::new(),
@ -52,7 +53,7 @@ impl UserInner {
self.call_inner(Packet { self.call_inner(Packet {
id: self.next_id.fetch_add(1, Ordering::SeqCst), id: self.next_id.fetch_add(1, Ordering::SeqCst),
pid: pid, pid: pid.into(),
uid: uid, uid: uid,
gid: gid, gid: gid,
a: a, a: a,
@ -296,7 +297,7 @@ impl Scheme for UserScheme {
inner.call_inner(Packet { inner.call_inner(Packet {
id: id, id: id,
pid: pid, pid: pid.into(),
uid: uid, uid: uid,
gid: gid, gid: gid,
a: SYS_FMAP, a: SYS_FMAP,

View file

@ -2,13 +2,13 @@
use core::sync::atomic::Ordering; use core::sync::atomic::Ordering;
use context; use context;
use scheme; use scheme::{self, FileHandle};
use syscall; use syscall;
use syscall::data::{Packet, Stat}; use syscall::data::{Packet, Stat};
use syscall::error::*; use syscall::error::*;
use syscall::flag::{MODE_DIR, MODE_FILE}; use syscall::flag::{MODE_DIR, MODE_FILE};
pub fn file_op(a: usize, fd: usize, c: usize, d: usize) -> Result<usize> { pub fn file_op(a: usize, fd: FileHandle, c: usize, d: usize) -> Result<usize> {
let (file, pid, uid, gid) = { let (file, pid, uid, gid) = {
let contexts = context::contexts(); let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
@ -25,7 +25,7 @@ pub fn file_op(a: usize, fd: usize, c: usize, d: usize) -> Result<usize> {
let mut packet = Packet { let mut packet = Packet {
id: 0, id: 0,
pid: pid, pid: pid.into(),
uid: uid, uid: uid,
gid: gid, gid: gid,
a: a, a: a,
@ -39,11 +39,11 @@ pub fn file_op(a: usize, fd: usize, c: usize, d: usize) -> Result<usize> {
Error::demux(packet.a) Error::demux(packet.a)
} }
pub fn file_op_slice(a: usize, fd: usize, slice: &[u8]) -> Result<usize> { pub fn file_op_slice(a: usize, fd: FileHandle, slice: &[u8]) -> Result<usize> {
file_op(a, fd, slice.as_ptr() as usize, slice.len()) file_op(a, fd, slice.as_ptr() as usize, slice.len())
} }
pub fn file_op_mut_slice(a: usize, fd: usize, slice: &mut [u8]) -> Result<usize> { pub fn file_op_mut_slice(a: usize, fd: FileHandle, slice: &mut [u8]) -> Result<usize> {
file_op(a, fd, slice.as_mut_ptr() as usize, slice.len()) file_op(a, fd, slice.as_mut_ptr() as usize, slice.len())
} }
@ -81,7 +81,7 @@ pub fn getcwd(buf: &mut [u8]) -> Result<usize> {
} }
/// Open syscall /// Open syscall
pub fn open(path: &[u8], flags: usize) -> Result<usize> { pub fn open(path: &[u8], flags: usize) -> Result<FileHandle> {
let (path_canon, uid, gid) = { let (path_canon, uid, gid) = {
let contexts = context::contexts(); let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
@ -135,8 +135,8 @@ pub fn pipe2(fds: &mut [usize], flags: usize) -> Result<usize> {
event: None, event: None,
}).ok_or(Error::new(EMFILE))?; }).ok_or(Error::new(EMFILE))?;
fds[0] = read_fd; fds[0] = read_fd.into();
fds[1] = write_fd; fds[1] = write_fd.into();
Ok(0) Ok(0)
} else { } else {
@ -211,7 +211,7 @@ pub fn unlink(path: &[u8]) -> Result<usize> {
} }
/// Close syscall /// Close syscall
pub fn close(fd: usize) -> Result<usize> { pub fn close(fd: FileHandle) -> Result<usize> {
let file = { let file = {
let contexts = context::contexts(); let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
@ -233,7 +233,7 @@ pub fn close(fd: usize) -> Result<usize> {
} }
/// Duplicate file descriptor /// Duplicate file descriptor
pub fn dup(fd: usize, buf: &[u8]) -> Result<usize> { pub fn dup(fd: FileHandle, buf: &[u8]) -> Result<FileHandle> {
let file = { let file = {
let contexts = context::contexts(); let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
@ -262,15 +262,15 @@ pub fn dup(fd: usize, buf: &[u8]) -> Result<usize> {
} }
/// Register events for file /// Register events for file
pub fn fevent(fd: usize, flags: usize) -> Result<usize> { pub fn fevent(fd: FileHandle, flags: usize) -> Result<usize> {
let file = { let file = {
let contexts = context::contexts(); let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read(); let context = context_lock.read();
let mut files = context.files.lock(); let mut files = context.files.lock();
let mut file = files.get_mut(fd).ok_or(Error::new(EBADF))?.ok_or(Error::new(EBADF))?; let mut file = files.get_mut(fd.into()).ok_or(Error::new(EBADF))?.ok_or(Error::new(EBADF))?;
if let Some(event_id) = file.event.take() { if let Some(event_id) = file.event.take() {
println!("{}: {}:{}: events already registered: {}", fd, file.scheme, file.number, event_id); println!("{:?}: {:?}:{}: events already registered: {}", fd, file.scheme, file.number, event_id);
context::event::unregister(fd, file.scheme, event_id); context::event::unregister(fd, file.scheme, event_id);
} }
file.clone() file.clone()
@ -287,7 +287,7 @@ pub fn fevent(fd: usize, flags: usize) -> Result<usize> {
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read(); let context = context_lock.read();
let mut files = context.files.lock(); let mut files = context.files.lock();
let mut file = files.get_mut(fd).ok_or(Error::new(EBADF))?.ok_or(Error::new(EBADF))?; let mut file = files.get_mut(fd.into()).ok_or(Error::new(EBADF))?.ok_or(Error::new(EBADF))?;
file.event = Some(event_id); file.event = Some(event_id);
} }
context::event::register(fd, file.scheme, event_id); context::event::register(fd, file.scheme, event_id);

View file

@ -14,6 +14,9 @@ use self::data::TimeSpec;
use self::error::{Error, Result, ENOSYS}; use self::error::{Error, Result, ENOSYS};
use self::number::*; use self::number::*;
use context::ContextId;
use scheme::FileHandle;
/// Filesystem syscalls /// Filesystem syscalls
pub mod fs; pub mod fs;
@ -34,19 +37,22 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize
#[inline(always)] #[inline(always)]
fn inner(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack: usize) -> Result<usize> { fn inner(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, stack: usize) -> Result<usize> {
match a & SYS_CLASS { match a & SYS_CLASS {
SYS_CLASS_FILE => match a & SYS_ARG { SYS_CLASS_FILE => {
SYS_ARG_SLICE => file_op_slice(a, b, validate_slice(c as *const u8, d)?), let fd = FileHandle::from(b);
SYS_ARG_MSLICE => file_op_mut_slice(a, b, validate_slice_mut(c as *mut u8, d)?), match a & SYS_ARG {
_ => match a { SYS_ARG_SLICE => file_op_slice(a, fd, validate_slice(c as *const u8, d)?),
SYS_CLOSE => close(b), SYS_ARG_MSLICE => file_op_mut_slice(a, fd, validate_slice_mut(c as *mut u8, d)?),
SYS_DUP => dup(b, validate_slice(c as *const u8, d)?), _ => match a {
SYS_FEVENT => fevent(b, c), SYS_CLOSE => close(fd),
SYS_FUNMAP => funmap(b), SYS_DUP => dup(fd, validate_slice(c as *const u8, d)?).map(FileHandle::into),
_ => file_op(a, b, c, d) SYS_FEVENT => fevent(fd, c),
SYS_FUNMAP => funmap(b),
_ => file_op(a, fd, c, d)
}
} }
}, },
SYS_CLASS_PATH => match a { SYS_CLASS_PATH => match a {
SYS_OPEN => open(validate_slice(b as *const u8, c)?, d), SYS_OPEN => open(validate_slice(b as *const u8, c)?, d).map(FileHandle::into),
SYS_MKDIR => mkdir(validate_slice(b as *const u8, c)?, d as u16), SYS_MKDIR => mkdir(validate_slice(b as *const u8, c)?, d as u16),
SYS_RMDIR => rmdir(validate_slice(b as *const u8, c)?), SYS_RMDIR => rmdir(validate_slice(b as *const u8, c)?),
SYS_UNLINK => unlink(validate_slice(b as *const u8, c)?), SYS_UNLINK => unlink(validate_slice(b as *const u8, c)?),
@ -54,13 +60,13 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize
}, },
_ => match a { _ => match a {
SYS_EXIT => exit(b), SYS_EXIT => exit(b),
SYS_WAITPID => waitpid(b, c, d), SYS_WAITPID => waitpid(ContextId::from(b), c, d).map(ContextId::into),
SYS_EXECVE => exec(validate_slice(b as *const u8, c)?, validate_slice(d as *const [usize; 2], e)?), SYS_EXECVE => exec(validate_slice(b as *const u8, c)?, validate_slice(d as *const [usize; 2], e)?),
SYS_CHDIR => chdir(validate_slice(b as *const u8, c)?), SYS_CHDIR => chdir(validate_slice(b as *const u8, c)?),
SYS_GETPID => getpid(), SYS_GETPID => getpid().map(ContextId::into),
SYS_BRK => brk(b), SYS_BRK => brk(b),
SYS_IOPL => iopl(b), SYS_IOPL => iopl(b),
SYS_CLONE => clone(b, stack), SYS_CLONE => clone(b, stack).map(ContextId::into),
SYS_YIELD => sched_yield(), SYS_YIELD => sched_yield(),
SYS_NANOSLEEP => nanosleep(validate_slice(b as *const TimeSpec, 1).map(|req| &req[0])?, validate_slice_mut(c as *mut TimeSpec, 1).ok().map(|rem| &mut rem[0])), SYS_NANOSLEEP => nanosleep(validate_slice(b as *const TimeSpec, 1).map(|req| &req[0])?, validate_slice_mut(c as *mut TimeSpec, 1).ok().map(|rem| &mut rem[0])),
SYS_GETCWD => getcwd(validate_slice_mut(b as *mut u8, c)?), SYS_GETCWD => getcwd(validate_slice_mut(b as *mut u8, c)?),

View file

@ -12,9 +12,10 @@ use arch::paging::{ActivePageTable, InactivePageTable, Page, PhysicalAddress, Vi
use arch::paging::temporary_page::TemporaryPage; use arch::paging::temporary_page::TemporaryPage;
use arch::start::usermode; use arch::start::usermode;
use context; use context;
use context::ContextId;
use context::memory::Grant; use context::memory::Grant;
use elf::{self, program_header}; use elf::{self, program_header};
use scheme; use scheme::{self, FileHandle};
use syscall; use syscall;
use syscall::data::Stat; use syscall::data::Stat;
use syscall::error::*; use syscall::error::*;
@ -53,7 +54,7 @@ pub fn brk(address: usize) -> Result<usize> {
} }
} }
pub fn clone(flags: usize, stack_base: usize) -> Result<usize> { pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
let ppid; let ppid;
let pid; let pid;
{ {
@ -720,10 +721,10 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
if let Some(context_lock) = contexts.get(ppid) { if let Some(context_lock) = contexts.get(ppid) {
let mut context = context_lock.write(); let mut context = context_lock.write();
if ! context.unblock() { if ! context.unblock() {
println!("{} not blocked for exec vfork unblock", ppid); println!("{:?} not blocked for exec vfork unblock", ppid);
} }
} else { } else {
println!("{} not found for exec vfork unblock", ppid); println!("{:?} not found for exec vfork unblock", ppid);
} }
} }
}, },
@ -749,7 +750,7 @@ pub fn exit(status: usize) -> ! {
let mut close_files = Vec::new(); let mut close_files = Vec::new();
let (pid, ppid) = { let (pid, ppid) = {
let mut context = context_lock.write(); let mut context = context_lock.write();
if Arc::strong_count(&context.files) == 1 { if Arc::strong_count(&context.files) == 1 { // FIXME: Looks like a race condition.
mem::swap(context.files.lock().deref_mut(), &mut close_files); mem::swap(context.files.lock().deref_mut(), &mut close_files);
} }
context.files = Arc::new(Mutex::new(Vec::new())); context.files = Arc::new(Mutex::new(Vec::new()));
@ -760,7 +761,7 @@ pub fn exit(status: usize) -> ! {
for (fd, file_option) in close_files.drain(..).enumerate() { for (fd, file_option) in close_files.drain(..).enumerate() {
if let Some(file) = file_option { if let Some(file) = file_option {
if let Some(event_id) = file.event { if let Some(event_id) = file.event {
context::event::unregister(fd, file.scheme, event_id); context::event::unregister(FileHandle::from(fd), file.scheme, event_id);
} }
let scheme_option = { let scheme_option = {
@ -811,7 +812,7 @@ pub fn exit(status: usize) -> ! {
let mut parent = parent_lock.write(); let mut parent = parent_lock.write();
if vfork { if vfork {
if ! parent.unblock() { if ! parent.unblock() {
println!("{} not blocked for exit vfork unblock", ppid); println!("{:?} not blocked for exit vfork unblock", ppid);
} }
} }
parent.waitpid.clone() parent.waitpid.clone()
@ -822,7 +823,7 @@ pub fn exit(status: usize) -> ! {
} }
waitpid.send(pid, status); waitpid.send(pid, status);
} else { } else {
println!("{} not found for exit vfork unblock", ppid); println!("{:?} not found for exit vfork unblock", ppid);
} }
} }
} }
@ -853,7 +854,7 @@ pub fn getgid() -> Result<usize> {
Ok(context.rgid as usize) Ok(context.rgid as usize)
} }
pub fn getpid() -> Result<usize> { pub fn getpid() -> Result<ContextId> {
let contexts = context::contexts(); let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read(); let context = context_lock.read();
@ -872,7 +873,7 @@ pub fn iopl(_level: usize) -> Result<usize> {
Ok(0) Ok(0)
} }
pub fn kill(pid: usize, sig: usize) -> Result<usize> { pub fn kill(pid: ContextId, sig: usize) -> Result<usize> {
use syscall::flag::*; use syscall::flag::*;
let _context_lock = { let _context_lock = {
@ -882,19 +883,19 @@ pub fn kill(pid: usize, sig: usize) -> Result<usize> {
}; };
let term = || { let term = || {
println!("Terminate {}", pid); println!("Terminate {:?}", pid);
}; };
let core = || { let core = || {
println!("Core {}", pid); println!("Core {:?}", pid);
}; };
let stop = || { let stop = || {
println!("Stop {}", pid); println!("Stop {:?}", pid);
}; };
let cont = || { let cont = || {
println!("Continue {}", pid); println!("Continue {:?}", pid);
}; };
match sig { match sig {
@ -1056,7 +1057,7 @@ pub fn virttophys(virtual_address: usize) -> Result<usize> {
} }
} }
fn reap(pid: usize) -> Result<usize> { fn reap(pid: ContextId) -> Result<ContextId> {
// Spin until not running // Spin until not running
let mut running = false; let mut running = false;
while running { while running {
@ -1074,7 +1075,7 @@ fn reap(pid: usize) -> Result<usize> {
contexts.remove(pid).ok_or(Error::new(ESRCH)).and(Ok(pid)) contexts.remove(pid).ok_or(Error::new(ESRCH)).and(Ok(pid))
} }
pub fn waitpid(pid: usize, status_ptr: usize, flags: usize) -> Result<usize> { pub fn waitpid(pid: ContextId, status_ptr: usize, flags: usize) -> Result<ContextId> {
let waitpid = { let waitpid = {
let contexts = context::contexts(); let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
@ -1089,13 +1090,13 @@ pub fn waitpid(pid: usize, status_ptr: usize, flags: usize) -> Result<usize> {
&mut tmp &mut tmp
}; };
if pid == 0 { if pid.into() == 0 {
if flags & WNOHANG == WNOHANG { if flags & WNOHANG == WNOHANG {
if let Some((w_pid, status)) = waitpid.receive_any_nonblock() { if let Some((w_pid, status)) = waitpid.receive_any_nonblock() {
status_slice[0] = status; status_slice[0] = status;
reap(w_pid) reap(w_pid)
} else { } else {
Ok(0) Ok(ContextId::from(0))
} }
} else { } else {
let (w_pid, status) = waitpid.receive_any(); let (w_pid, status) = waitpid.receive_any();
@ -1108,7 +1109,7 @@ pub fn waitpid(pid: usize, status_ptr: usize, flags: usize) -> Result<usize> {
status_slice[0] = status; status_slice[0] = status;
reap(pid) reap(pid)
} else { } else {
Ok(0) Ok(ContextId::from(0))
} }
} else { } else {
let status = waitpid.receive(&pid); let status = waitpid.receive(&pid);
@ -1117,3 +1118,4 @@ pub fn waitpid(pid: usize, status_ptr: usize, flags: usize) -> Result<usize> {
} }
} }
} }