Merge branch 'cap2' of https://github.com/Yoric/redox into Yoric-cap2
This commit is contained in:
commit
297b6e09fc
108
kernel/common/int_like.rs
Normal file
108
kernel/common/int_like.rs
Normal 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
3
kernel/common/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#[macro_use]
|
||||||
|
#[macro_export]
|
||||||
|
pub mod int_like;
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
});
|
});
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)?),
|
||||||
|
|
|
@ -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> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue