parent
1589852743
commit
dac20c94ee
@ -0,0 +1,57 @@
|
||||
use {alloc::collections::VecDeque, hbvm::engine::Engine};
|
||||
|
||||
use {
|
||||
crossbeam_queue::{ArrayQueue, SegQueue},
|
||||
log::trace,
|
||||
};
|
||||
|
||||
use crate::{ipc::message::Message, kmain::DEVICE_TREE};
|
||||
pub enum HostError {
|
||||
MemoryError,
|
||||
}
|
||||
|
||||
pub fn ipc_send(engine: &mut Engine) -> Result<(), HostError> {
|
||||
let handle = engine.registers.f0;
|
||||
let message_start = engine.registers.f1;
|
||||
let message_length = engine.registers.f2;
|
||||
|
||||
let mut ipc_msg: alloc::vec::Vec<u8> = alloc::vec![];
|
||||
|
||||
for x in message_start..message_start + message_length {
|
||||
let byte = engine.read_mem_addr_8(x);
|
||||
match byte {
|
||||
Ok(byte) => ipc_msg.push(byte),
|
||||
Err(_) => return Err(HostError::MemoryError),
|
||||
}
|
||||
}
|
||||
log::trace!("Message bytes {:?}", ipc_msg);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn ipc_recv(engine: &mut Engine) {}
|
||||
|
||||
/// Check f0 for the buffer type
|
||||
/// 0 means an unbound buffer
|
||||
/// 1 means a bound buffer
|
||||
/// Check f1 if the buffer is bound
|
||||
///
|
||||
/// f2 Return a handle to the sender
|
||||
/// f3 returns a handle the the reciever
|
||||
pub fn ipc_mkbuf(engine: &mut Engine) {
|
||||
match engine.registers.f0 as usize {
|
||||
0 => {
|
||||
trace!("Making a new ipc unbound buffer");
|
||||
let buf: SegQueue<Message> = SegQueue::new();
|
||||
}
|
||||
1 => {
|
||||
let buf_len = engine.registers.f1 as usize;
|
||||
trace!("Making a new ipc buffer with capacity {}", buf_len);
|
||||
let buf: ArrayQueue<Message> = ArrayQueue::new(buf_len);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rpc_discover(engine: &mut Engine) {}
|
||||
pub fn rpc_register(engine: &mut Engine) {}
|
||||
pub fn rpc_call(engine: &mut Engine) {}
|
@ -0,0 +1,15 @@
|
||||
use crossbeam_queue::{ArrayQueue, SegQueue};
|
||||
|
||||
use super::message::Message;
|
||||
|
||||
enum BufferTypes {
|
||||
Unbound(SegQueue<Message>),
|
||||
Bound(ArrayQueue<Message>),
|
||||
}
|
||||
|
||||
pub struct IpcBuffer {
|
||||
protocol: Protocol,
|
||||
buffer: BufferTypes,
|
||||
}
|
||||
|
||||
pub struct Protocol {}
|
@ -0,0 +1,3 @@
|
||||
use alloc::vec::Vec;
|
||||
|
||||
pub type Message = Vec<u8>;
|
@ -0,0 +1,24 @@
|
||||
pub mod buffer;
|
||||
pub mod message;
|
||||
|
||||
use alloc::string::ToString;
|
||||
|
||||
pub struct IpcV1 {
|
||||
abc: alloc::string::String,
|
||||
}
|
||||
|
||||
pub struct IpcV2 {
|
||||
abc: alloc::string::String,
|
||||
}
|
||||
|
||||
pub fn IPCV1_to_IPCV2(ipc_v1: IpcV1) -> IpcV2 {
|
||||
return IpcV2 {
|
||||
abc: "abc".to_string(),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn IPCV2_to_IPCV1(ipc_v2: IpcV2) -> IpcV1 {
|
||||
return IpcV1 {
|
||||
abc: "abc".to_string(),
|
||||
};
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
extern crate kernel;
|
||||
|
@ -1,149 +0,0 @@
|
||||
//! Async task and executor
|
||||
|
||||
use alloc::{boxed::Box, collections::BTreeMap, sync::Arc, task::Wake};
|
||||
use core::{
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
task::{Context, Poll, Waker},
|
||||
};
|
||||
use crossbeam_queue::SegQueue;
|
||||
use slab::Slab;
|
||||
use spin::RwLock;
|
||||
|
||||
type TaskQueue = Arc<SegQueue<TaskId>>;
|
||||
type SpawnQueue = Arc<SegQueue<Task>>;
|
||||
|
||||
static SPAWN_QUEUE: RwLock<Option<SpawnQueue>> = RwLock::new(None);
|
||||
|
||||
/// Spawn a new task
|
||||
pub fn spawn(future: impl Future<Output = ()> + Send + 'static) {
|
||||
match &*SPAWN_QUEUE.read() {
|
||||
Some(s) => s.push(Task::new(future)),
|
||||
None => panic!("no task executor is running"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Forcibly yield a task
|
||||
pub fn yield_now() -> impl Future<Output = ()> {
|
||||
struct YieldNow(bool);
|
||||
impl Future for YieldNow {
|
||||
type Output = ();
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
if self.0 {
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
self.0 = true;
|
||||
cx.waker().wake_by_ref();
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
YieldNow(false)
|
||||
}
|
||||
|
||||
/// Tasks executor
|
||||
#[derive(Default)]
|
||||
pub struct Executor {
|
||||
/// All spawned tasks' stash
|
||||
tasks: Slab<Task>,
|
||||
|
||||
/// Awake tasks' queue
|
||||
queue: TaskQueue,
|
||||
|
||||
/// Incoming tasks to enqueue
|
||||
incoming: SpawnQueue,
|
||||
|
||||
/// Wakers
|
||||
wakers: BTreeMap<TaskId, Waker>,
|
||||
}
|
||||
|
||||
impl Executor {
|
||||
/// Spawn a task
|
||||
pub fn spawn(&mut self, future: impl Future<Output = ()> + Send + 'static) {
|
||||
self.queue
|
||||
.push(TaskId(self.tasks.insert(Task::new(future))));
|
||||
}
|
||||
|
||||
/// Spin poll loop until it runs out of tasks
|
||||
pub fn run(&mut self) {
|
||||
// Assign `self.incoming` to global spawn queue to spawn tasks
|
||||
// from within
|
||||
{
|
||||
let mut spawner = SPAWN_QUEUE.write();
|
||||
if spawner.is_some() {
|
||||
panic!("task executor is already running");
|
||||
}
|
||||
|
||||
*spawner = Some(Arc::clone(&self.incoming));
|
||||
}
|
||||
|
||||
// Try to get incoming task, if none available, poll
|
||||
// enqueued one
|
||||
while let Some(id) = self
|
||||
.incoming
|
||||
.pop()
|
||||
.map(|t| TaskId(self.tasks.insert(t)))
|
||||
.or_else(|| self.queue.pop())
|
||||
{
|
||||
let Some(task) = self.tasks.get_mut(id.0) else {
|
||||
panic!("attempted to get non-extant task with id {}", id.0)
|
||||
};
|
||||
|
||||
let mut cx = Context::from_waker(self.wakers.entry(id).or_insert_with(|| {
|
||||
Waker::from(Arc::new(TaskWaker {
|
||||
id,
|
||||
queue: Arc::clone(&self.queue),
|
||||
}))
|
||||
}));
|
||||
|
||||
match task.poll(&mut cx) {
|
||||
Poll::Ready(()) => {
|
||||
// Task done, unregister
|
||||
self.tasks.remove(id.0);
|
||||
self.wakers.remove(&id);
|
||||
}
|
||||
Poll::Pending => (),
|
||||
}
|
||||
}
|
||||
|
||||
*SPAWN_QUEUE.write() = None;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
struct TaskId(usize);
|
||||
|
||||
/// Async task
|
||||
struct Task {
|
||||
future: Pin<Box<dyn Future<Output = ()> + Send>>,
|
||||
}
|
||||
|
||||
impl Task {
|
||||
/// Create a new task from a future
|
||||
fn new(future: impl Future<Output = ()> + Send + 'static) -> Self {
|
||||
Self {
|
||||
future: Box::pin(future),
|
||||
}
|
||||
}
|
||||
|
||||
fn poll(&mut self, cx: &mut Context) -> Poll<()> {
|
||||
self.future.as_mut().poll(cx)
|
||||
}
|
||||
}
|
||||
|
||||
struct TaskWaker {
|
||||
id: TaskId,
|
||||
queue: TaskQueue,
|
||||
}
|
||||
|
||||
impl Wake for TaskWaker {
|
||||
fn wake(self: Arc<Self>) {
|
||||
self.wake_by_ref();
|
||||
}
|
||||
|
||||
fn wake_by_ref(self: &Arc<Self>) {
|
||||
self.queue.push(self.id);
|
||||
}
|
||||
}
|
Loading…
Reference in new issue