Context list class, static context ID magic
This commit is contained in:
parent
9cd48a36a5
commit
3b8f396229
|
@ -13,7 +13,6 @@ spin = "*"
|
||||||
|
|
||||||
[dependencies.goblin]
|
[dependencies.goblin]
|
||||||
git = "https://github.com/m4b/goblin.git"
|
git = "https://github.com/m4b/goblin.git"
|
||||||
crate-type = ["lib"]
|
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["no_mach", "no_mach32", "no_pe", "no_pe32", "no_endian_fd", "pure"]
|
features = ["no_mach", "no_mach32", "no_pe", "no_pe32", "no_endian_fd", "pure"]
|
||||||
|
|
||||||
|
|
|
@ -1,29 +1,71 @@
|
||||||
//! Context management
|
//! Context management
|
||||||
|
|
||||||
use alloc::arc::Arc;
|
|
||||||
use collections::{BTreeMap, Vec};
|
use collections::{BTreeMap, Vec};
|
||||||
|
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
|
||||||
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||||
|
|
||||||
|
use syscall::{Error, Result};
|
||||||
|
|
||||||
/// File operations
|
/// File operations
|
||||||
pub mod file;
|
pub mod file;
|
||||||
|
|
||||||
|
/// Limit on number of contexts
|
||||||
|
pub const CONTEXT_MAX_CONTEXTS: usize = 65536;
|
||||||
|
|
||||||
/// Maximum context files
|
/// Maximum context files
|
||||||
pub const CONTEXT_MAX_FILES: usize = 65536;
|
pub const CONTEXT_MAX_FILES: usize = 65536;
|
||||||
|
|
||||||
/// Context ID
|
|
||||||
pub type ContextId = u16;
|
|
||||||
|
|
||||||
/// Context list type
|
/// Context list type
|
||||||
pub type ContextList = BTreeMap<ContextId, Arc<RwLock<Context>>>;
|
pub struct ContextList {
|
||||||
|
map: BTreeMap<usize, RwLock<Context>>,
|
||||||
|
next_id: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ContextList {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
ContextList {
|
||||||
|
map: BTreeMap::new(),
|
||||||
|
next_id: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self, id: usize) -> Option<&RwLock<Context>> {
|
||||||
|
self.map.get(&id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn current(&self) -> Option<&RwLock<Context>> {
|
||||||
|
self.map.get(&CONTEXT_ID.load(Ordering::SeqCst))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_context(&mut self) -> Result<(usize, &RwLock<Context>)> {
|
||||||
|
if self.next_id >= CONTEXT_MAX_CONTEXTS {
|
||||||
|
self.next_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while self.map.contains_key(&self.next_id) {
|
||||||
|
self.next_id += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.next_id >= CONTEXT_MAX_CONTEXTS {
|
||||||
|
return Err(Error::TryAgain);
|
||||||
|
}
|
||||||
|
|
||||||
|
let id = self.next_id;
|
||||||
|
self.next_id += 1;
|
||||||
|
assert!(self.map.insert(id, RwLock::new(Context::new())).is_none());
|
||||||
|
Ok((id, self.map.get(&id).expect("failed to insert new context")))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Contexts list
|
/// Contexts list
|
||||||
static CONTEXTS: Once<RwLock<ContextList>> = Once::new();
|
static CONTEXTS: Once<RwLock<ContextList>> = Once::new();
|
||||||
|
|
||||||
|
#[thread_local]
|
||||||
|
static CONTEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT;
|
||||||
|
|
||||||
/// Initialize contexts, called if needed
|
/// Initialize contexts, called if needed
|
||||||
fn init_contexts() -> RwLock<ContextList> {
|
fn init_contexts() -> RwLock<ContextList> {
|
||||||
let mut map: ContextList = BTreeMap::new();
|
RwLock::new(ContextList::new())
|
||||||
map.insert(0, Arc::new(RwLock::new(Context::new())));
|
|
||||||
RwLock::new(map)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the global schemes list, const
|
/// Get the global schemes list, const
|
||||||
|
|
|
@ -70,6 +70,7 @@
|
||||||
#![feature(const_fn)]
|
#![feature(const_fn)]
|
||||||
#![feature(drop_types_in_const)]
|
#![feature(drop_types_in_const)]
|
||||||
#![feature(question_mark)]
|
#![feature(question_mark)]
|
||||||
|
#![feature(thread_local)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
use arch::interrupt;
|
use arch::interrupt;
|
||||||
|
|
|
@ -8,7 +8,7 @@ use super::{Error, Result};
|
||||||
/// Read syscall
|
/// Read syscall
|
||||||
pub fn read(fd: usize, buf: &mut [u8]) -> Result<usize> {
|
pub fn read(fd: usize, buf: &mut [u8]) -> Result<usize> {
|
||||||
println!("Read {}: {}", fd, buf.len());
|
println!("Read {}: {}", fd, buf.len());
|
||||||
if let Some(context_lock) = context::contexts().get(&0) {
|
if let Some(context_lock) = context::contexts().current() {
|
||||||
let context = context_lock.read();
|
let context = context_lock.read();
|
||||||
if let Some(file) = context.files.get(fd) {
|
if let Some(file) = context.files.get(fd) {
|
||||||
println!("{:?}", file);
|
println!("{:?}", file);
|
||||||
|
@ -24,7 +24,7 @@ pub fn read(fd: usize, buf: &mut [u8]) -> Result<usize> {
|
||||||
/// Write syscall
|
/// Write syscall
|
||||||
pub fn write(fd: usize, buf: &[u8]) -> Result<usize> {
|
pub fn write(fd: usize, buf: &[u8]) -> Result<usize> {
|
||||||
println!("Write {}: {}", fd, buf.len());
|
println!("Write {}: {}", fd, buf.len());
|
||||||
if let Some(context_lock) = context::contexts().get(&0) {
|
if let Some(context_lock) = context::contexts().current() {
|
||||||
let context = context_lock.read();
|
let context = context_lock.read();
|
||||||
if let Some(file) = context.files.get(fd) {
|
if let Some(file) = context.files.get(fd) {
|
||||||
println!("{:?}: {:?}", file, ::core::str::from_utf8(buf));
|
println!("{:?}: {:?}", file, ::core::str::from_utf8(buf));
|
||||||
|
@ -57,7 +57,7 @@ pub fn open(path: &[u8], flags: usize) -> Result<usize> {
|
||||||
}
|
}
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
if let Some(context_lock) = context::contexts().get(&0) {
|
if let Some(context_lock) = context::contexts().current() {
|
||||||
let mut context = context_lock.write();
|
let mut context = context_lock.write();
|
||||||
if let Some(fd) = context.add_file(::context::file::File {
|
if let Some(fd) = context.add_file(::context::file::File {
|
||||||
scheme: 0,
|
scheme: 0,
|
||||||
|
|
|
@ -12,73 +12,61 @@ pub mod fs;
|
||||||
pub mod process;
|
pub mod process;
|
||||||
|
|
||||||
/// System call list
|
/// System call list
|
||||||
|
/// See http://syscalls.kernelgrok.com/ for numbers
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
|
#[repr(C)]
|
||||||
pub enum Call {
|
pub enum Call {
|
||||||
/// Exit syscall
|
/// Exit syscall
|
||||||
Exit,
|
Exit = 1,
|
||||||
/// Read syscall
|
/// Read syscall
|
||||||
Read,
|
Read = 3,
|
||||||
/// Write syscall
|
/// Write syscall
|
||||||
Write,
|
Write = 4,
|
||||||
/// Open syscall
|
/// Open syscall
|
||||||
Open,
|
Open = 5,
|
||||||
/// Close syscall
|
/// Close syscall
|
||||||
Close,
|
Close = 6,
|
||||||
/// Execute syscall
|
/// Execute syscall
|
||||||
Exec,
|
Exec = 11,
|
||||||
/// Unknown syscall
|
|
||||||
Unknown
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert numbers to calls
|
/// Convert numbers to calls
|
||||||
/// See http://syscalls.kernelgrok.com/
|
/// See http://syscalls.kernelgrok.com/
|
||||||
impl From<usize> for Call {
|
impl Call {
|
||||||
fn from(number: usize) -> Call {
|
fn from(number: usize) -> Result<Call> {
|
||||||
match number {
|
match number {
|
||||||
1 => Call::Exit,
|
1 => Ok(Call::Exit),
|
||||||
3 => Call::Read,
|
3 => Ok(Call::Read),
|
||||||
4 => Call::Write,
|
4 => Ok(Call::Write),
|
||||||
5 => Call::Open,
|
5 => Ok(Call::Open),
|
||||||
6 => Call::Close,
|
6 => Ok(Call::Close),
|
||||||
11 => Call::Exec,
|
11 => Ok(Call::Exec),
|
||||||
_ => Call::Unknown
|
_ => Err(Error::NoCall)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The error number for an invalid value
|
/// The error number for an invalid value
|
||||||
|
/// See http://www-numi.fnal.gov/offline_software/srt_public_context/WebDocs/Errors/unix_system_errors.html for numbers
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
|
#[repr(C)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// Operation not permitted
|
/// Operation not permitted
|
||||||
NotPermitted,
|
NotPermitted = 1,
|
||||||
/// No such file or directory
|
/// No such file or directory
|
||||||
NoEntry,
|
NoEntry = 2,
|
||||||
/// No such process
|
/// No such process
|
||||||
NoProcess,
|
NoProcess = 3,
|
||||||
/// Bad file number
|
/// Bad file number
|
||||||
BadFile,
|
BadFile = 9,
|
||||||
|
/// Try again
|
||||||
|
TryAgain = 11,
|
||||||
/// Invalid argument
|
/// Invalid argument
|
||||||
InvalidValue,
|
InvalidValue = 22,
|
||||||
/// Too many open files
|
/// Too many open files
|
||||||
TooManyFiles,
|
TooManyFiles = 24,
|
||||||
/// Syscall not implemented
|
/// Syscall not implemented
|
||||||
NoCall
|
NoCall = 38
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert errors to numbers
|
|
||||||
/// See http://www-numi.fnal.gov/offline_software/srt_public_context/WebDocs/Errors/unix_system_errors.html
|
|
||||||
impl From<Error> for usize {
|
|
||||||
fn from(err: Error) -> usize {
|
|
||||||
match err {
|
|
||||||
Error::NotPermitted => 1,
|
|
||||||
Error::NoEntry => 2,
|
|
||||||
Error::NoProcess => 3,
|
|
||||||
Error::BadFile => 9,
|
|
||||||
Error::InvalidValue => 22,
|
|
||||||
Error::TooManyFiles => 24,
|
|
||||||
Error::NoCall => 38
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Result<T> = ::core::result::Result<T, Error>;
|
pub type Result<T> = ::core::result::Result<T, Error>;
|
||||||
|
@ -95,22 +83,21 @@ pub fn convert_slice_mut<T>(ptr: *mut T, len: usize) -> Result<&'static mut [T]>
|
||||||
Ok(unsafe { slice::from_raw_parts_mut(ptr, len) })
|
Ok(unsafe { slice::from_raw_parts_mut(ptr, len) })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle(a: usize, b: usize, c: usize, d: usize, e: usize, _f: usize) -> ::core::result::Result<usize, usize> {
|
pub fn handle(a: usize, b: usize, c: usize, d: usize, e: usize, _f: usize) -> Result<usize> {
|
||||||
match Call::from(a) {
|
match Call::from(a)? {
|
||||||
Call::Exit => exit(b),
|
Call::Exit => exit(b),
|
||||||
Call::Read => read(b, convert_slice_mut(c as *mut u8, d)?),
|
Call::Read => read(b, convert_slice_mut(c as *mut u8, d)?),
|
||||||
Call::Write => write(b, convert_slice(c as *const u8, d)?),
|
Call::Write => write(b, convert_slice(c as *const u8, d)?),
|
||||||
Call::Open => open(convert_slice(b as *const u8, c)?, d),
|
Call::Open => open(convert_slice(b as *const u8, c)?, d),
|
||||||
Call::Close => close(b),
|
Call::Close => close(b),
|
||||||
Call::Exec => exec(convert_slice(b as *const u8, c)?, convert_slice(d as *const [usize; 2], e)?),
|
Call::Exec => exec(convert_slice(b as *const u8, c)?, convert_slice(d as *const [usize; 2], e)?)
|
||||||
Call::Unknown => Err(Error::NoCall)
|
}
|
||||||
}.map_err(|err| err.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> usize {
|
pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> usize {
|
||||||
match handle(a, b, c, d, e, f) {
|
match handle(a, b, c, d, e, f) {
|
||||||
Ok(value) => value,
|
Ok(value) => value,
|
||||||
Err(value) => !value
|
Err(value) => !(value as usize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue