diff --git a/src/lib.rs b/src/lib.rs index e79038ae..2ce93a66 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ #![feature(const_fn)] #![feature(alloc_layout_extra)] #![feature(const_in_array_repeat_expressions)] +#![feature(wake_trait)] #![test_runner(crate::test_runner)] #![reexport_test_harness_main = "test_main"] @@ -18,6 +19,7 @@ pub mod gdt; pub mod interrupts; pub mod memory; pub mod serial; +pub mod task; pub mod vga_buffer; pub fn init() { diff --git a/src/main.rs b/src/main.rs index 84d42343..40da8c06 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,6 @@ extern crate alloc; -use alloc::{boxed::Box, rc::Rc, vec, vec::Vec}; use blog_os::println; use bootloader::{entry_point, BootInfo}; use core::panic::PanicInfo; @@ -16,6 +15,7 @@ entry_point!(kernel_main); fn kernel_main(boot_info: &'static BootInfo) -> ! { use blog_os::allocator; use blog_os::memory::{self, BootInfoFrameAllocator}; + use blog_os::task::{simple_executor::SimpleExecutor, Task}; use x86_64::VirtAddr; println!("Hello World{}", "!"); @@ -27,29 +27,9 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { allocator::init_heap(&mut mapper, &mut frame_allocator).expect("heap initialization failed"); - // allocate a number on the heap - let heap_value = Box::new(41); - println!("heap_value at {:p}", heap_value); - - // create a dynamically sized vector - let mut vec = Vec::new(); - for i in 0..500 { - vec.push(i); - } - println!("vec at {:p}", vec.as_slice()); - - // create a reference counted vector -> will be freed when count reaches 0 - let reference_counted = Rc::new(vec![1, 2, 3]); - let cloned_reference = reference_counted.clone(); - println!( - "current reference count is {}", - Rc::strong_count(&cloned_reference) - ); - core::mem::drop(reference_counted); - println!( - "reference count is {} now", - Rc::strong_count(&cloned_reference) - ); + let mut executor = SimpleExecutor::new(); + executor.spawn(Task::new(example_task())); + executor.run(); #[cfg(test)] test_main(); @@ -58,6 +38,15 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { blog_os::hlt_loop(); } +async fn async_number() -> u32 { + 42 +} + +async fn example_task() { + let number = async_number().await; + println!("async number: {}", number); +} + /// This function is called on panic. #[cfg(not(test))] #[panic_handler] diff --git a/src/task/mod.rs b/src/task/mod.rs new file mode 100644 index 00000000..d55e2a4e --- /dev/null +++ b/src/task/mod.rs @@ -0,0 +1,21 @@ +use alloc::boxed::Box; +use core::task::{Context, Poll}; +use core::{future::Future, pin::Pin}; + +pub mod simple_executor; + +pub struct Task { + future: Pin>>, +} + +impl Task { + pub fn new(future: impl Future + 'static) -> Task { + Task { + future: Box::pin(future), + } + } + + fn poll(&mut self, context: &mut Context) -> Poll<()> { + self.future.as_mut().poll(context) + } +} diff --git a/src/task/simple_executor.rs b/src/task/simple_executor.rs new file mode 100644 index 00000000..d20699e0 --- /dev/null +++ b/src/task/simple_executor.rs @@ -0,0 +1,44 @@ +use super::Task; +use alloc::{collections::VecDeque, sync::Arc, task::Wake}; +use core::task::{Context, Poll, Waker}; + +pub struct SimpleExecutor { + task_queue: VecDeque, +} + +impl SimpleExecutor { + pub fn new() -> SimpleExecutor { + SimpleExecutor { + task_queue: VecDeque::new(), + } + } + + pub fn spawn(&mut self, task: Task) { + self.task_queue.push_back(task) + } + + pub fn run(&mut self) { + while let Some(mut task) = self.task_queue.pop_front() { + let waker = DummyWaker.to_waker(); + let mut context = Context::from_waker(&waker); + match task.poll(&mut context) { + Poll::Ready(()) => {} // task done + Poll::Pending => self.task_queue.push_back(task), + } + } + } +} + +struct DummyWaker; + +impl Wake for DummyWaker { + fn wake(self: Arc) { + // do nothing + } +} + +impl DummyWaker { + fn to_waker(self) -> Waker { + Waker::from(Arc::new(self)) + } +}