diff --git a/src/lib.rs b/src/lib.rs index 3c30ad7..4658250 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,7 @@ pub mod interrupts; pub mod gdt; pub mod memory; pub mod allocator; +pub mod task; extern crate alloc; diff --git a/src/main.rs b/src/main.rs index f873e59..8f207f4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ extern crate alloc; use alloc::{boxed::Box, vec, vec::Vec, rc::Rc}; use core::panic::PanicInfo; use rust_os::println; +use rust_os::task::{Task, simple_executor::SimpleExecutor}; use bootloader::{BootInfo, entry_point}; use x86_64::VirtAddr; @@ -30,23 +31,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(); @@ -55,6 +42,15 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { rust_os::hlt_loop(); } +async fn async_number() -> u32 { + 42 +} + +async fn example_task() { + let number = async_number().await; + println!("async number: {}", number); +} + #[cfg(not(test))] #[panic_handler] fn panic(info: &PanicInfo) -> ! { diff --git a/src/task/mod.rs b/src/task/mod.rs new file mode 100644 index 0000000..5844ae9 --- /dev/null +++ b/src/task/mod.rs @@ -0,0 +1,21 @@ +use core::{future::Future, pin::Pin}; +use alloc::boxed::Box; +use core::task::{Context, Poll}; + +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) + } +} \ No newline at end of file diff --git a/src/task/simple_executor.rs b/src/task/simple_executor.rs new file mode 100644 index 0000000..5b26aa7 --- /dev/null +++ b/src/task/simple_executor.rs @@ -0,0 +1,44 @@ +use super::Task; +use alloc::collections::VecDeque; +use core::task::{Waker, RawWaker, RawWakerVTable, Context, Poll}; + +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 = dummy_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), + } + } + } +} + +fn dummy_raw_waker() -> RawWaker { + fn no_op(_: *const ()) {} + fn clone(_: *const ()) -> RawWaker { + dummy_raw_waker() + } + + let vtable = &RawWakerVTable::new(clone, no_op, no_op, no_op); + RawWaker::new(0 as *const (), vtable) +} + +fn dummy_waker() -> Waker { + unsafe { Waker::from_raw(dummy_raw_waker()) } +}