Verified Commit 49e424d8 authored by jD91mZM2's avatar jD91mZM2
Browse files

Add separate scheme for fmap

parent f9ed9ab2
Pipeline #2331 passed with stage
in 1 minute and 1 second
[package]
name = "ipcd"
version = "0.1.0"
edition = "2018"
[dependencies]
redox_syscall = "0.1.40"
extern crate syscall;
use std::{
fs::File,
io::{self, prelude::*},
......
extern crate syscall;
use std::{
fs::File,
io::{self, prelude::*},
......
extern crate syscall;
use std::{
fs::File,
io::{self, prelude::*},
......
use std::{
fs::File,
io,
os::unix::io::AsRawFd,
slice
};
fn from_syscall_error(error: syscall::Error) -> io::Error {
io::Error::from_raw_os_error(error.errno as i32)
}
fn main() -> Result<(), io::Error> {
let file1 = File::open("shm:example")?;
let file2 = File::open("shm:example")?;
let one = unsafe {
slice::from_raw_parts_mut(
syscall::fmap(file1.as_raw_fd(), 0, 128).map_err(from_syscall_error)? as *mut u8,
128
)
};
let two = unsafe {
slice::from_raw_parts_mut(
syscall::fmap(file2.as_raw_fd(), 64, 64).map_err(from_syscall_error)? as *mut u8,
64
)
};
println!("Testing writing between");
for i in 0..128 {
one[i as usize] = i;
}
for i in 0..64 {
assert_eq!(two[i as usize], 64 + i);
}
println!("Testing fpath");
let mut buf = [0; 128];
let len = syscall::fpath(file1.as_raw_fd(), &mut buf).map_err(from_syscall_error)?;
assert_eq!(&buf[..len], b"shm:example");
Ok(())
}
use std::{
fs::File,
io,
mem,
os::unix::io::AsRawFd,
thread,
time::Duration
};
fn from_syscall_error(error: syscall::Error) -> io::Error {
io::Error::from_raw_os_error(error.errno as i32)
}
fn main() -> Result<(), io::Error> {
let file = File::open("shm:counter")?;
println!("Reading from map... ");
let counter = unsafe {
&mut *(syscall::fmap(file.as_raw_fd(), 0, mem::size_of::<usize>()).map_err(from_syscall_error)? as *mut usize)
};
println!("Read value {}", counter);
*counter += 1;
println!("Increased value to {}", counter);
loop {
thread::sleep(Duration::from_secs(std::u64::MAX));
}
}
extern crate syscall;
use std::{
fs::File,
io::{self, prelude::*},
......
use post_fevent;
use crate::post_fevent;
use std::{
collections::BTreeMap,
cmp,
collections::HashMap,
fs::File,
io,
mem
......@@ -69,12 +70,12 @@ impl Handle {
}
#[derive(Default)]
pub struct IpcScheme {
handles: BTreeMap<usize, Handle>,
listeners: BTreeMap<String, usize>,
pub struct ChanScheme {
handles: HashMap<usize, Handle>,
listeners: HashMap<String, usize>,
next_id: usize
}
impl IpcScheme {
impl ChanScheme {
pub fn post_fevents(&mut self, file: &mut File) -> io::Result<()> {
for (id, handle) in &mut self.handles {
match handle.extra {
......@@ -116,7 +117,7 @@ fn connect(target: &mut Handle, new_id: usize) -> Result<()> {
target.remote = Connection::Open(new_id);
Ok(())
}
impl SchemeBlockMut for IpcScheme {
impl SchemeBlockMut for ChanScheme {
fn open(&mut self, path: &[u8], flags: usize, _uid: u32, _gid: u32) -> Result<Option<usize>> {
let path = ::std::str::from_utf8(path).or(Err(Error::new(EPERM)))?;
......@@ -155,7 +156,7 @@ impl SchemeBlockMut for IpcScheme {
if let Connection::Open(remote_id) = remote {
let new_id = self.next_id;
let mut clone = self.handles.get_mut(&id).map(Handle::accept).unwrap();
let clone = self.handles.get_mut(&id).map(Handle::accept).unwrap();
{
// This might fail if the remote side closed early
......@@ -174,7 +175,7 @@ impl SchemeBlockMut for IpcScheme {
}
},
b"connect" => {
let mut new = Handle::default();
let new = Handle::default();
let new_id = self.next_id;
{
......@@ -217,7 +218,7 @@ impl SchemeBlockMut for IpcScheme {
(handle.flags, handle.remote)
};
if let Connection::Open(remote_id) = remote {
let mut remote = self.handles.get_mut(&remote_id).unwrap();
let remote = self.handles.get_mut(&remote_id).unwrap();
match remote.extra {
Extra::Client(ref mut client) => {
client.buffer.extend(buf);
......@@ -247,7 +248,7 @@ impl SchemeBlockMut for IpcScheme {
};
if !client.buffer.is_empty() {
let len = buf.len().min(client.buffer.len());
let len = cmp::min(buf.len(), client.buffer.len());
buf[..len].copy_from_slice(&client.buffer[..len]);
client.buffer.drain(..len);
Ok(Some(len))
......
extern crate syscall;
use std::{
collections::VecDeque,
fs::File,
io::{self, prelude::*}
io::{self, prelude::*},
os::unix::io::AsRawFd
};
use syscall::SchemeBlockMut;
use syscall::{flag::*, Event, Packet, SchemeBlockMut, SchemeMut};
mod scheme;
mod chan;
mod shm;
use scheme::IpcScheme;
use self::chan::ChanScheme;
use self::shm::ShmScheme;
fn from_syscall_error(error: syscall::Error) -> io::Error {
io::Error::from_raw_os_error(error.errno as i32)
}
fn main() -> Result<(), Box<::std::error::Error>> {
const TOKEN_CHAN: usize = 0;
const TOKEN_SHM: usize = 1;
fn main() -> Result<(), Box<dyn ::std::error::Error>> {
if unsafe { syscall::clone(0) }.map_err(from_syscall_error)? != 0 {
return Ok(());
}
let mut scheme_file = File::create(":chan")?;
let mut scheme = IpcScheme::default();
// Create event listener for both files
let mut event_file = File::open("event:")?;
let mut chan_file = File::create(":chan")?;
event_file.write(&Event {
id: chan_file.as_raw_fd() as usize,
flags: EVENT_READ,
data: TOKEN_CHAN
})?;
let mut shm_file = File::create(":shm")?;
event_file.write(&Event {
id: shm_file.as_raw_fd() as usize,
flags: EVENT_READ,
data: TOKEN_SHM
})?;
let mut chan = ChanScheme::default();
let mut shm = ShmScheme::default();
let mut todo = VecDeque::with_capacity(16);
syscall::setrens(0, 0).map_err(from_syscall_error)?;
loop {
let mut event = syscall::Packet::default();
scheme_file.read(&mut event)?;
// New event has to be handled first so any previous event
// that is now updated gets processed after.
todo.push_front(event);
let mut error = None;
todo.retain(|event| {
if let Some(a) = scheme.handle(&event) {
// Send event back with new ID
let mut event = *event;
event.a = a;
if let Err(err) = scheme_file.write(&event) {
error = Some(err);
let mut event = Event::default();
event_file.read(&mut event)?;
match event.data {
TOKEN_CHAN => {
let mut packet = Packet::default();
chan_file.read(&mut packet)?;
// Put new packet first in the queue
todo.push_front(packet);
let mut error: Option<io::Error> = None;
// Process queue, delete finished items
todo.retain(|packet| {
if let Some(status) = chan.handle(&packet) {
// Send packet back with new ID
let mut packet = *packet;
packet.a = status;
if let Err(err) = chan_file.write(&packet) {
error = Some(err);
}
return false;
}
true
});
if let Some(err) = error {
return Err(Box::new(err));
}
return false;
}
true
});
// Handle fevents
chan.post_fevents(&mut chan_file)?;
},
TOKEN_SHM => {
let mut packet = Packet::default();
shm_file.read(&mut packet)?;
if let Some(err) = error {
return Err(Box::new(err));
}
// Handle packet and update `a` to be status code
shm.handle(&mut packet);
scheme.post_fevents(&mut scheme_file)?;
shm_file.write(&packet)?;
},
_ => ()
}
}
}
fn post_fevent(file: &mut File, id: usize, flag: usize) -> io::Result<()> {
......
use std::{
cmp,
collections::{HashMap, hash_map::Entry},
rc::Rc
};
use syscall::{error::*, Error, SchemeMut, Result};
#[derive(Default)]
pub struct ShmHandle {
buffer: Option<Box<[u8]>>,
refs: usize
}
#[derive(Default)]
pub struct ShmScheme {
maps: HashMap<Rc<str>, ShmHandle>,
handles: HashMap<usize, Rc<str>>,
next_id: usize
}
impl SchemeMut for ShmScheme {
fn open(&mut self, path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
let path = std::str::from_utf8(path).or(Err(Error::new(EPERM)))?.into();
let entry = self.maps.entry(Rc::clone(&path)).or_insert(ShmHandle::default());
entry.refs += 1;
self.handles.insert(self.next_id, path);
let id = self.next_id;
self.next_id += 1;
Ok(id)
}
fn fmap(&mut self, id: usize, offset: usize, len: usize) -> Result<usize> {
let path = self.handles.get(&id).ok_or(Error::new(EBADF))?;
match self.maps.get_mut(path).expect("handle pointing to nothing").buffer {
Some(ref mut buf) => {
if offset + len != buf.len() {
return Err(Error::new(ERANGE));
}
Ok(buf[offset..].as_mut_ptr() as usize)
},
ref mut buf @ None => {
*buf = Some(vec![0; offset+len].into_boxed_slice());
Ok(buf.as_mut().unwrap()[offset..].as_mut_ptr() as usize)
}
}
}
fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
// Write scheme name
const PREFIX: &[u8] = b"shm:";
let len = cmp::min(PREFIX.len(), buf.len());
buf[..len].copy_from_slice(&PREFIX[..len]);
if len < PREFIX.len() {
return Ok(len);
}
// Write path
let path = self.handles.get(&id).ok_or(Error::new(EBADF))?;
let len = cmp::min(path.len(), buf.len() - PREFIX.len());
buf[PREFIX.len()..][..len].copy_from_slice(&path.as_bytes()[..len]);
Ok(PREFIX.len() + len)
}
fn close(&mut self, id: usize) -> Result<usize> {
let path = self.handles.remove(&id).ok_or(Error::new(EBADF))?;
let mut entry = match self.maps.entry(path) {
Entry::Occupied(entry) => entry,
Entry::Vacant(_) => panic!("handle pointing to nothing")
};
entry.get_mut().refs -= 1;
if entry.get().refs == 0 {
// There is no other reference to this entry, drop
entry.remove_entry();
}
Ok(0)
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment