tack inplace hbvm
This commit is contained in:
parent
282688d48b
commit
2744e8e67b
23
Cargo.lock
generated
23
Cargo.lock
generated
|
@ -5,9 +5,10 @@ version = 3
|
|||
[[package]]
|
||||
name = "able_graphics_library"
|
||||
version = "0.1.2"
|
||||
source = "git+https://git.ablecorp.us/ableos/ableos_userland#70a65fc10d2caafe370be90eb0e31aa7d9347218"
|
||||
source = "git+https://git.ablecorp.us/ableos/ableos_userland#f433484f2f56a4e8f77b1f39680b88c3d1e27830"
|
||||
dependencies = [
|
||||
"embedded-graphics",
|
||||
"log",
|
||||
"versioning",
|
||||
]
|
||||
|
||||
|
@ -140,9 +141,9 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "clparse"
|
||||
version = "0.1.0"
|
||||
source = "git+https://git.ablecorp.us/ableos/ableos_userland#70a65fc10d2caafe370be90eb0e31aa7d9347218"
|
||||
source = "git+https://git.ablecorp.us/ableos/ableos_userland#f433484f2f56a4e8f77b1f39680b88c3d1e27830"
|
||||
dependencies = [
|
||||
"hashbrown 0.13.2",
|
||||
"hashbrown 0.12.3",
|
||||
"log",
|
||||
"toml",
|
||||
]
|
||||
|
@ -364,6 +365,15 @@ dependencies = [
|
|||
"ahash 0.8.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hbvm"
|
||||
version = "0.1.0"
|
||||
source = "git+https://git.ablecorp.us/ableos/holey-bytes#76302b4ca8aeda6597ee51cb1cf5f59a5d385c4f"
|
||||
dependencies = [
|
||||
"hashbrown 0.13.2",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
|
@ -457,7 +467,8 @@ dependencies = [
|
|||
"derive_more",
|
||||
"embedded-graphics",
|
||||
"error-stack 0.3.1",
|
||||
"hashbrown 0.13.2",
|
||||
"hashbrown 0.12.3",
|
||||
"hbvm",
|
||||
"limine",
|
||||
"log",
|
||||
"rdrand",
|
||||
|
@ -822,7 +833,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
|||
[[package]]
|
||||
name = "versioning"
|
||||
version = "0.1.3"
|
||||
source = "git+https://git.ablecorp.us/ableos/ableos_userland#70a65fc10d2caafe370be90eb0e31aa7d9347218"
|
||||
source = "git+https://git.ablecorp.us/ableos/ableos_userland#f433484f2f56a4e8f77b1f39680b88c3d1e27830"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
@ -1110,7 +1121,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "xml"
|
||||
version = "0.1.0"
|
||||
source = "git+https://git.ablecorp.us/ableos/ableos_userland#70a65fc10d2caafe370be90eb0e31aa7d9347218"
|
||||
source = "git+https://git.ablecorp.us/ableos/ableos_userland#f433484f2f56a4e8f77b1f39680b88c3d1e27830"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
|
|
@ -3,5 +3,4 @@ TODO:
|
|||
|
||||
# Compiling
|
||||
1. `git submodule --update init`
|
||||
1. Add [this binary](https://git.ablecorp.us/AbleOS/ableos/src/commit/e6c8d184d42961cf3cfa2e4aa319fc86c8880585/test.wasm) to the root.
|
||||
1. `cargo repbuild`
|
||||
|
|
|
@ -6,7 +6,7 @@ resolver = "2"
|
|||
|
||||
[dependencies]
|
||||
|
||||
|
||||
hbvm = { git = "https://git.ablecorp.us/ableos/holey-bytes" }
|
||||
embedded-graphics = "0.7.1"
|
||||
|
||||
|
||||
|
|
|
@ -47,7 +47,8 @@ SECTIONS
|
|||
/* Align initial kernel heap to page boundary */
|
||||
. = ALIGN(4K);
|
||||
PROVIDE(_initial_kernel_heap_start = .);
|
||||
PROVIDE(_initial_kernel_heap_size = 1024 * 1024);
|
||||
/* PROVIDE(_initial_kernel_heap_size = 1024 * 1024); */
|
||||
PROVIDE(_initial_kernel_heap_size = 1024 * 4096);
|
||||
. += _initial_kernel_heap_size;
|
||||
} :data
|
||||
}
|
||||
|
|
|
@ -39,6 +39,8 @@ struct Allocator(Mutex<Option<Heap>>);
|
|||
|
||||
unsafe impl GlobalAlloc for Allocator {
|
||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||
// log::info!("Global allocation");
|
||||
|
||||
let mut lock = self.0.lock();
|
||||
let allocator = lock.as_mut().expect("heap allocator should be initialized");
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ use {
|
|||
pub static DISPLAY: Lazy<Mutex<Display>> = Lazy::new(|| {
|
||||
static FB_REQ: FramebufferRequest = FramebufferRequest::new(0);
|
||||
let fb1: &NonNullPtr<Framebuffer> = &FB_REQ.get_response().get().unwrap().framebuffers()[0];
|
||||
|
||||
{
|
||||
use crate::alloc::string::ToString;
|
||||
let mut dt = DEVICE_TREE.lock();
|
||||
|
@ -22,8 +23,13 @@ pub static DISPLAY: Lazy<Mutex<Display>> = Lazy::new(|| {
|
|||
disp.set_attribute("bits per pixel", fb1.bpp);
|
||||
dt.devices.insert("Displays".to_string(), alloc::vec![disp]);
|
||||
}
|
||||
let size: usize = (fb1.width * fb1.height).try_into().unwrap();
|
||||
let back_buffer: alloc::vec::Vec<u32> = alloc::vec![0; 800*600];
|
||||
|
||||
let m = Mutex::new(Display {
|
||||
fb: fb1.address.as_ptr().unwrap().cast(),
|
||||
// bb: fb1.address.as_ptr().unwrap().cast(),
|
||||
bb: back_buffer.as_slice().as_ptr() as *mut u32,
|
||||
size: Size::new(fb1.width as u32, fb1.height as u32),
|
||||
color: Rgb888::WHITE,
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@ use {
|
|||
uart_16550::SerialPort,
|
||||
};
|
||||
|
||||
static SERIAL_CONSOLE: Mutex<SerialPort> = Mutex::new(unsafe { SerialPort::new(0x3F8) });
|
||||
pub static SERIAL_CONSOLE: Mutex<SerialPort> = Mutex::new(unsafe { SerialPort::new(0x3F8) });
|
||||
static TERMINAL_LOGGER: Lazy<Mutex<TermLogger>> = Lazy::new(|| Mutex::new(TermLogger::new()));
|
||||
|
||||
pub fn init() {
|
||||
|
@ -17,8 +17,10 @@ pub fn init() {
|
|||
|
||||
pub fn log(args: core::fmt::Arguments<'_>) -> core::fmt::Result {
|
||||
x86_64::instructions::interrupts::without_interrupts(|| {
|
||||
TERMINAL_LOGGER.lock().write_fmt(args)?;
|
||||
SERIAL_CONSOLE.lock().write_fmt(args)
|
||||
// TERMINAL_LOGGER.lock().write_fmt(args)?;
|
||||
let mut sc = SERIAL_CONSOLE.lock();
|
||||
sc.write_fmt(args)?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -8,9 +8,9 @@ pub mod memory;
|
|||
|
||||
mod cpuid;
|
||||
mod gdt;
|
||||
mod graphics;
|
||||
pub mod graphics;
|
||||
pub(crate) mod interrupts;
|
||||
mod logging;
|
||||
pub mod logging;
|
||||
pub mod pci;
|
||||
pub mod virtio;
|
||||
|
||||
|
@ -114,11 +114,56 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
|||
graphics::init();
|
||||
let mut dis = DISPLAY.lock();
|
||||
use {able_graphics_library::raw_pixel, embedded_graphics::prelude::RgbColor};
|
||||
dis.set_color(Rgb888::GREEN);
|
||||
dis.line(1, 1, 700, 1000, 1);
|
||||
// dis.line(10, 10, 100, 10, 10);
|
||||
// dis.line(100, 10, 1, 1, 10);
|
||||
// dis.set_color(Rgb888::GREEN);
|
||||
// dis.line(400, 400, 700, 100, 50);
|
||||
|
||||
// dis.set_color(Rgb888::new(100, 23, 100));
|
||||
|
||||
// dis.line(100, 100, 400, 400, 3);
|
||||
|
||||
// dis.line(100, 100, 700, 100, 1);
|
||||
dis.set_color(Rgb888::YELLOW);
|
||||
let thick = 3;
|
||||
let p1 = (400, 30);
|
||||
let p2 = (200, 150);
|
||||
let p3 = (600, 150);
|
||||
let p4 = (200, 350);
|
||||
let p5 = (600, 350);
|
||||
let p6 = (400, 470);
|
||||
|
||||
{
|
||||
//HEXAGON
|
||||
|
||||
dis.line(p1.0, p1.1, p2.0, p2.1, thick);
|
||||
dis.line(p1.0, p1.1, p3.0, p3.1, thick);
|
||||
dis.line(p2.0, p2.1, p4.0, p4.1, thick);
|
||||
dis.line(p3.0, p3.1, p5.0, p5.1, thick);
|
||||
dis.line(p6.0, p6.1, p4.0, p4.1, thick);
|
||||
dis.line(p6.0, p6.1, p5.0, p5.1, thick);
|
||||
}
|
||||
{
|
||||
dis.line(600, 150, 200, 350, thick);
|
||||
dis.line(600, 350, 400, 250, thick);
|
||||
}
|
||||
|
||||
{
|
||||
dis.set_color(Rgb888::WHITE);
|
||||
let hp1 = (350, 150);
|
||||
let hp2 = (350, 350);
|
||||
let hp3 = (450, 250);
|
||||
let hp4 = (350, 250);
|
||||
let hp5 = (450, 150);
|
||||
let hp6 = (450, 350);
|
||||
|
||||
dis.line(hp1.0, hp1.1, hp2.0, hp2.1, thick);
|
||||
dis.line(hp3.0, hp3.1, hp4.0, hp4.1, thick);
|
||||
dis.line(hp5.0, hp5.1, hp6.0, hp6.1, thick);
|
||||
}
|
||||
|
||||
dis.swap_buffers();
|
||||
}
|
||||
|
||||
let rand = xml::XMLElement::new("Random");
|
||||
|
||||
crate::kmain::kmain(
|
||||
KFILE_REQ
|
||||
|
@ -144,7 +189,7 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
|||
}),
|
||||
)
|
||||
}
|
||||
|
||||
use embedded_graphics::prelude::WebColors;
|
||||
/// Spin loop
|
||||
pub fn sloop() -> ! {
|
||||
loop {
|
||||
|
|
|
@ -23,10 +23,22 @@ pub fn init() {
|
|||
let id = device_info.device_id.id;
|
||||
use Vendor::*;
|
||||
let (dev_type, dev_name) = match (vendor, id) {
|
||||
(Qemu, 4369) => ("GPUs", "QEMU VGA"),
|
||||
(VirtIO, 4176) => ("GPUs", "VirtIO PCI GPU"),
|
||||
(CirrusLogic, 184) => ("GPUs", "Cirrus SVGA"), //GD 5446?
|
||||
(_, _) => ("Unidentified PCI", "UNKNOWN DEVICE"),
|
||||
};
|
||||
// let (dev_type, dev_name) = match device_info.full_class {
|
||||
// PciFullClass::Unclassified_NonVgaCompatible => todo!(),
|
||||
// PciFullClass::Unclassified_VgaCompatible => todo!(),
|
||||
|
||||
// PciFullClass::Display_VGA => ("GPUs", "VGA Device"),
|
||||
// PciFullClass::Display_XGA => ("GPUs", "XGA Device"),
|
||||
// PciFullClass::Display_3D => ("GPUs", "3D Device"),
|
||||
// PciFullClass::Display_Other => ("GPUs", "Other"),
|
||||
|
||||
// _ => ("Unidentified PCI", "UNKNOWN DEVICE"),
|
||||
// };
|
||||
|
||||
let mut dev = xml::XMLElement::new(dev_name);
|
||||
let mut pci_info = xml::XMLElement::new("PCI Info");
|
||||
|
|
|
@ -3,6 +3,7 @@ use alloc::{string::String, vec::Vec};
|
|||
use {crate::alloc::string::ToString, core::fmt, hashbrown::HashMap};
|
||||
pub type Device = xml::XMLElement;
|
||||
|
||||
// TODO: alphabatize this list
|
||||
#[derive(Debug)]
|
||||
pub struct DeviceTree {
|
||||
pub devices: HashMap<String, Vec<Device>>,
|
||||
|
|
57
kernel/src/host_functions.rs
Normal file
57
kernel/src/host_functions.rs
Normal file
|
@ -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) {}
|
15
kernel/src/ipc/buffer.rs
Normal file
15
kernel/src/ipc/buffer.rs
Normal file
|
@ -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 {}
|
3
kernel/src/ipc/message.rs
Normal file
3
kernel/src/ipc/message.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
use alloc::vec::Vec;
|
||||
|
||||
pub type Message = Vec<u8>;
|
24
kernel/src/ipc/mod.rs
Normal file
24
kernel/src/ipc/mod.rs
Normal file
|
@ -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(),
|
||||
};
|
||||
}
|
|
@ -7,7 +7,13 @@ use {
|
|||
spin::{Lazy, Mutex},
|
||||
};
|
||||
|
||||
use crate::device_tree::DeviceTree;
|
||||
use {embedded_graphics::pixelcolor::Rgb888, hbvm::engine::Engine};
|
||||
|
||||
use crate::{
|
||||
arch::{graphics::DISPLAY, logging::SERIAL_CONSOLE},
|
||||
device_tree::DeviceTree,
|
||||
// host_functions::read_device_tree,
|
||||
};
|
||||
|
||||
use crate::alloc::string::ToString;
|
||||
|
||||
|
@ -39,10 +45,40 @@ pub fn kmain(cmdline: &str, bootstrap: Option<&'static [u8]>) -> ! {
|
|||
let mut dt = DEVICE_TREE.lock();
|
||||
|
||||
info!("Device Tree {}", &dt);
|
||||
crate::arch::sloop()
|
||||
|
||||
let bytes = alloc::vec![0];
|
||||
let mut prog = Engine::new(bytes);
|
||||
// prog.enviroment_call_table[0] = read_device_tree;
|
||||
prog.run();
|
||||
prog.dump();
|
||||
|
||||
// TODO: change this to a driver
|
||||
{
|
||||
let mut buf = [8; 128 * 4];
|
||||
|
||||
let mut sc = SERIAL_CONSOLE.lock();
|
||||
loop {
|
||||
let byte = sc.receive();
|
||||
if byte == b'\r' {
|
||||
sc.send(b'\n');
|
||||
}
|
||||
sc.send(byte);
|
||||
}
|
||||
}
|
||||
|
||||
crate::arch::sloop()
|
||||
}
|
||||
use embedded_graphics::prelude::RgbColor;
|
||||
|
||||
use hbvm::bytecode::ops::Operations::*;
|
||||
pub static DEVICE_TREE: Lazy<Mutex<DeviceTree>> = Lazy::new(|| {
|
||||
let mut dt = DeviceTree::new();
|
||||
Mutex::new(dt)
|
||||
});
|
||||
|
||||
#[test_case]
|
||||
fn trivial_assertion() {
|
||||
trace!("trivial assertion... ");
|
||||
assert_eq!(1, 1);
|
||||
info!("[ok]");
|
||||
}
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
ptr_sub_ptr
|
||||
)]
|
||||
#![no_std]
|
||||
#![feature(custom_test_frameworks)]
|
||||
#![test_runner(crate::test_runner)]
|
||||
|
||||
// #![deny(missing_docs)]
|
||||
|
||||
extern crate alloc;
|
||||
|
@ -18,10 +21,11 @@ mod allocator;
|
|||
mod arch;
|
||||
pub mod device_tree;
|
||||
pub mod handle;
|
||||
pub mod host_functions;
|
||||
pub mod ipc;
|
||||
mod kmain;
|
||||
mod logger;
|
||||
mod memory;
|
||||
mod task;
|
||||
pub mod utils;
|
||||
|
||||
use versioning::Version;
|
||||
|
@ -50,3 +54,11 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
|
|||
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn test_runner(tests: &[&dyn Fn()]) {
|
||||
println!("Running {} tests", tests.len());
|
||||
for test in tests {
|
||||
test();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 a new issue