redox/kernel/scheme/user.rs

127 lines
3.4 KiB
Rust
Raw Normal View History

use collections::{BTreeMap, VecDeque};
2016-09-20 05:24:54 +02:00
use core::sync::atomic::{AtomicUsize, Ordering};
use core::{mem, usize};
use spin::RwLock;
2016-09-20 05:24:54 +02:00
use context;
use syscall::{convert_to_result, Call, Error, Result};
use super::Scheme;
2016-09-20 05:24:54 +02:00
#[derive(Copy, Clone, Debug)]
#[repr(packed)]
pub struct Packet {
pub id: usize,
pub a: usize,
pub b: usize,
pub c: usize,
pub d: usize
}
/// UserScheme has to be wrapped
pub struct UserScheme {
2016-09-20 05:24:54 +02:00
next_id: AtomicUsize,
todo: RwLock<VecDeque<Packet>>,
done: RwLock<BTreeMap<usize, usize>>
}
impl UserScheme {
fn call(&self, a: Call, b: usize, c: usize, d: usize) -> Result<usize> {
2016-09-20 05:24:54 +02:00
let id = self.next_id.fetch_add(1, Ordering::SeqCst);
self.todo.write().push_back(Packet {
id: id,
a: a as usize,
b: b,
c: c,
d: d
});
loop {
if let Some(a) = self.done.write().remove(&id) {
return convert_to_result(a);
}
unsafe { context::switch(); }
}
}
}
impl Scheme for UserScheme {
2016-09-20 05:24:54 +02:00
fn open(&self, path: &[u8], flags: usize) -> Result<usize> {
self.call(Call::Open, path.as_ptr() as usize, path.len(), flags)
}
2016-09-20 05:24:54 +02:00
fn dup(&self, file: usize) -> Result<usize> {
if file == usize::MAX {
Ok(file)
} else {
2016-09-20 05:24:54 +02:00
self.call(Call::Dup, file, 0, 0)
}
}
2016-09-20 05:24:54 +02:00
fn read(&self, file: usize, buf: &mut [u8]) -> Result<usize> {
if file == usize::MAX {
let packet_size = mem::size_of::<Packet>();
let len = buf.len()/packet_size;
if len > 0 {
loop {
let mut i = 0;
{
let mut todo = self.todo.write();
while ! todo.is_empty() && i < len {
unsafe { *(buf.as_mut_ptr() as *mut Packet).offset(i as isize) = todo.pop_front().unwrap(); }
i += 1;
}
}
if i > 0 {
return Ok(i * packet_size);
} else {
unsafe { context::switch(); }
}
}
} else {
Ok(0)
}
} else {
self.call(Call::Read, file, buf.as_mut_ptr() as usize, buf.len())
}
}
2016-09-20 05:24:54 +02:00
fn write(&self, file: usize, buf: &[u8]) -> Result<usize> {
if file == usize::MAX {
let packet_size = mem::size_of::<Packet>();
let len = buf.len()/packet_size;
let mut i = 0;
while i < len {
let packet = unsafe { *(buf.as_ptr() as *const Packet).offset(i as isize) };
self.done.write().insert(packet.id, packet.a);
2016-09-20 05:24:54 +02:00
i += 1;
}
2016-09-20 05:24:54 +02:00
Ok(i * packet_size)
} else {
self.call(Call::Write, file, buf.as_ptr() as usize, buf.len())
}
}
2016-09-20 05:24:54 +02:00
fn fsync(&self, file: usize) -> Result<()> {
if file == usize::MAX {
Ok(())
} else {
2016-09-20 05:24:54 +02:00
self.call(Call::FSync, file, 0, 0).and(Ok(()))
}
}
2016-09-20 05:24:54 +02:00
fn close(&self, file: usize) -> Result<()> {
if file == usize::MAX {
println!("Close user scheme");
Ok(())
} else {
self.call(Call::Close, file, 0, 0).and(Ok(()))
}
}
}