diff --git a/crates/common/src/executor.rs b/crates/common/src/executor.rs new file mode 100644 index 000000000..2d7babb52 --- /dev/null +++ b/crates/common/src/executor.rs @@ -0,0 +1,34 @@ +//! This module contains utilities for handling async functions in the no_std environment. This allows for usage of +//! async/await syntax for futures in a single thread. + +use alloc::boxed::Box; +use core::{ + future::Future, + task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, +}; + +/// This function busy waits on a future until it is ready. It uses a no-op waker to poll the future in a +/// thread-blocking loop. +pub fn block_on(f: impl Future) -> T { + let mut f = Box::pin(f); + + // Construct a no-op waker. + fn noop_clone(_: *const ()) -> RawWaker { + noop_raw_waker() + } + fn noop(_: *const ()) {} + fn noop_raw_waker() -> RawWaker { + let vtable = &RawWakerVTable::new(noop_clone, noop, noop, noop); + RawWaker::new(core::ptr::null(), vtable) + } + let waker = unsafe { Waker::from_raw(noop_raw_waker()) }; + let mut context = Context::from_waker(&waker); + + loop { + // Safety: This is safe because we only poll the future once per loop iteration, + // and we do not move the future after pinning it. + if let Poll::Ready(v) = f.as_mut().poll(&mut context) { + return v; + } + } +} diff --git a/crates/common/src/lib.rs b/crates/common/src/lib.rs index 066804130..c7d1e39de 100644 --- a/crates/common/src/lib.rs +++ b/crates/common/src/lib.rs @@ -10,6 +10,8 @@ #![cfg_attr(target_arch = "mips", feature(asm_experimental_arch))] #![no_std] +extern crate alloc; + pub mod io; pub mod malloc; @@ -20,6 +22,9 @@ pub use traits::BasicKernelInterface; mod types; pub use types::{FileDescriptor, RegisterSize}; +mod executor; +pub use executor::block_on; + #[cfg(target_arch = "mips")] pub(crate) mod cannon;