Remove the async-support crate
diff --git a/Cargo.toml b/Cargo.toml
index eb56daa..0f3a704 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,7 +12,6 @@
__internal_disable_gpio_in_integration_test = []
[dependencies]
-core = { package = "async-support", path = "async-support" }
libtock-core = { path = "core" }
libtock_codegen = { path = "codegen" }
futures = { version = "0.3.1", default-features = false, features = ["unstable", "cfg-target-has-atomic"] }
@@ -58,7 +57,6 @@
[workspace]
members = [
- "async-support",
"codegen",
"core",
"test-runner"
diff --git a/async-support/Cargo.toml b/async-support/Cargo.toml
deleted file mode 100644
index 9287c6b..0000000
--- a/async-support/Cargo.toml
+++ /dev/null
@@ -1,8 +0,0 @@
-[package]
-name = "async-support"
-version = "0.1.0"
-authors = ["Woyten <woyten.tielesch@online.de>"]
-edition = "2018"
-description = "`libtock` specific patch of `core` for `async`-`await` syntax in a `#![no_std]` environment. It implements the methods `core::future::poll_with_tls_context` and `core::future::from_generator` which are currently missing in `core`."
-
-[dependencies]
diff --git a/async-support/src/lib.rs b/async-support/src/lib.rs
deleted file mode 100644
index afe1c4a..0000000
--- a/async-support/src/lib.rs
+++ /dev/null
@@ -1,109 +0,0 @@
-#![feature(generator_trait)]
-#![no_std]
-
-pub use core::*;
-
-pub mod future {
- pub use core::future::Future;
- use core::ops::Generator;
- use core::pin::Pin;
- use core::task::Poll;
-
- pub fn poll_with_tls_context<F>(f: Pin<&mut F>) -> Poll<F::Output>
- where
- F: Future,
- {
- crate::executor::poll(f)
- }
-
- pub fn from_generator<G: Generator<Yield = ()>>(
- generator: G,
- ) -> impl Future<Output = G::Return> {
- crate::executor::from_generator(generator)
- }
-}
-
-pub mod executor {
- use core::future::Future;
- use core::ops::Generator;
- use core::ops::GeneratorState;
- use core::pin::Pin;
- use core::ptr;
- use core::task::Context;
- use core::task::Poll;
- use core::task::RawWaker;
- use core::task::RawWakerVTable;
- use core::task::Waker;
-
- extern "Rust" {
- #[link_name = "libtock::syscalls::raw::yieldk"]
- fn yieldk();
- }
-
- /// # Safety
- ///
- /// [[block_on]] yields whenever a future cannot make any progress at present. Yielding is considered unsafe.
- pub unsafe fn block_on<T>(mut future: impl Future<Output = T>) -> T {
- // Contract described in the Rustdoc: "A value, once pinned, must remain pinned forever (...).".
- // IOW calling Pin::new_unchecked is safe as long as no &mut future is leaked after pinning.
- let mut pinned_future = Pin::new_unchecked(&mut future);
-
- loop {
- match poll(pinned_future.as_mut()) {
- Poll::Pending => yieldk(),
- Poll::Ready(value) => {
- return value;
- }
- }
- }
- }
-
- pub(crate) fn poll<F: Future>(pinned_future: Pin<&mut F>) -> Poll<F::Output> {
- let waker = unsafe { Waker::from_raw(get_dummy_waker()) };
- let mut context = Context::from_waker(&waker);
- pinned_future.poll(&mut context)
- }
-
- // Since Tock OS comes with waking-up functionality built-in, we use dummy wakers that do nothing at all.
- fn get_dummy_waker() -> RawWaker {
- fn clone(_x: *const ()) -> RawWaker {
- get_dummy_waker()
- }
-
- fn do_nothing(_x: *const ()) {}
-
- // This vtable implements the methods required for managing the lifecycle of the wakers.
- // Our wakers are dummies, so those functions don't do anything.
- static DUMMY_WAKER_VTABLE: RawWakerVTable =
- RawWakerVTable::new(clone, do_nothing, do_nothing, do_nothing);
-
- // The wakers don't have any implementation, so the instance can simply be null.
- RawWaker::new(ptr::null(), &DUMMY_WAKER_VTABLE)
- }
-
- pub(crate) fn from_generator<G: Generator<Yield = ()>>(
- generator: G,
- ) -> impl Future<Output = G::Return> {
- GeneratorFuture { generator }
- }
-
- struct GeneratorFuture<G> {
- generator: G,
- }
-
- impl<G: Generator<Yield = ()>> Future for GeneratorFuture<G> {
- type Output = G::Return;
-
- fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
- // Pin::map_unchecked_mut is safe as long as the move and drop guarantees are propagated through the mapping.
- // This is trivially satisfied since our future is only a newtype decorator of the generator.
- let pinned_generator =
- unsafe { self.map_unchecked_mut(|future| &mut future.generator) };
-
- match pinned_generator.resume(()) {
- GeneratorState::Yielded(()) => Poll::Pending,
- GeneratorState::Complete(out) => Poll::Ready(out),
- }
- }
- }
-}
diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs
index ccb0bfb..e13fc97 100644
--- a/codegen/src/lib.rs
+++ b/codegen/src/lib.rs
@@ -98,7 +98,7 @@
MAIN_INVOKED = true;
}
let _block = async #block;
- unsafe {::core::executor::block_on(_block) }
+ unsafe { ::libtock::executor::block_on(_block) }
}
))
}
@@ -126,7 +126,7 @@
let _block = async {
method_call().await;
};
- unsafe { ::core::executor::block_on(_block) }
+ unsafe { ::libtock::executor::block_on(_block) }
}
))
.unwrap();
diff --git a/core/src/syscalls/mod.rs b/core/src/syscalls/mod.rs
index 833c356..bae938b 100644
--- a/core/src/syscalls/mod.rs
+++ b/core/src/syscalls/mod.rs
@@ -10,23 +10,7 @@
use crate::shared_memory::SharedMemory;
pub mod raw {
- use super::platform;
-
- pub use platform::*;
-
- /// # Safety
- ///
- /// Yielding in the main function should be safe. Nevertheless, yielding manually is not required as this is already achieved by the `async` runtime.
- ///
- /// When yielding in callbacks, two problems can arise:
- /// - The guarantees of `FnMut` are violated. In this case, make sure your callback has `Fn` behavior.
- /// - Callbacks can get executed in a nested manner and overflow the stack quickly.
- ///
- /// This function is exported as `libtock::syscalls::raw::yieldk`. Do not reference this name directly. Its only purpose is to establish a back-channel from `async-support`, a patched version of `core` to `libtock-rs` via linking. This workaround has been chosen to keep the `core` crate free of dependencies on platform-specific syscall implementations and is expected to get removed as soon as possible.
- #[export_name = "libtock::syscalls::raw::yieldk"]
- pub unsafe fn yieldk() {
- platform::yieldk()
- }
+ pub use super::platform::*;
}
pub fn subscribe<C: Consumer<T>, T>(
diff --git a/core/src/syscalls/platform.rs b/core/src/syscalls/platform.rs
index 66e79f0..3d039d5 100644
--- a/core/src/syscalls/platform.rs
+++ b/core/src/syscalls/platform.rs
@@ -3,9 +3,15 @@
use std::vec::Vec;
/// yield for a callback fired by the kernel
+///
/// # Safety
-/// Yielding inside a callback conflicts with Rust's safety guarantees. For example,
-/// a FnMut closure could be triggered multiple times making a &mut a shared reference.
+///
+/// Yielding in the main function should be safe. Nevertheless, yielding manually
+/// is not required as this is already achieved by the `async` runtime.
+///
+/// When yielding in callbacks, two problems can arise:
+/// - The guarantees of `FnMut` are violated. In this case, make sure your callback has `Fn` behavior.
+/// - Callbacks can get executed in a nested manner and overflow the stack quickly.
pub unsafe fn yieldk() {
EVENTS.with(|e| e.borrow_mut().push(Event::YieldK));
}
diff --git a/src/console.rs b/src/console.rs
index ee6f50a..a94fc13 100644
--- a/src/console.rs
+++ b/src/console.rs
@@ -1,9 +1,9 @@
use crate::callback::Identity0Consumer;
+use crate::executor;
use crate::futures;
use crate::result::TockResult;
use crate::syscalls;
use core::cell::Cell;
-use core::executor;
use core::fmt;
use core::mem;
diff --git a/src/executor.rs b/src/executor.rs
new file mode 100644
index 0000000..9204616
--- /dev/null
+++ b/src/executor.rs
@@ -0,0 +1,50 @@
+use crate::syscalls;
+use core::pin::Pin;
+use core::ptr;
+use core::task::Context;
+use core::task::Poll;
+use core::task::RawWaker;
+use core::task::RawWakerVTable;
+use core::task::Waker;
+use futures::Future;
+
+/// # Safety
+///
+/// [[block_on]] yields whenever a future cannot make any progress at present. Yielding is considered unsafe.
+pub unsafe fn block_on<T>(mut future: impl Future<Output = T>) -> T {
+ // Contract described in the Rustdoc: "A value, once pinned, must remain pinned forever (...).".
+ // IOW calling Pin::new_unchecked is safe as long as no &mut future is leaked after pinning.
+ let mut pinned_future = Pin::new_unchecked(&mut future);
+
+ loop {
+ match poll(pinned_future.as_mut()) {
+ Poll::Pending => syscalls::raw::yieldk(),
+ Poll::Ready(value) => {
+ return value;
+ }
+ }
+ }
+}
+
+fn poll<F: Future>(pinned_future: Pin<&mut F>) -> Poll<F::Output> {
+ let waker = unsafe { Waker::from_raw(get_dummy_waker()) };
+ let mut context = Context::from_waker(&waker);
+ pinned_future.poll(&mut context)
+}
+
+// Since Tock OS comes with waking-up functionality built-in, we use dummy wakers that do nothing at all.
+fn get_dummy_waker() -> RawWaker {
+ fn clone(_x: *const ()) -> RawWaker {
+ get_dummy_waker()
+ }
+
+ fn do_nothing(_x: *const ()) {}
+
+ // This vtable implements the methods required for managing the lifecycle of the wakers.
+ // Our wakers are dummies, so those functions don't do anything.
+ static DUMMY_WAKER_VTABLE: RawWakerVTable =
+ RawWakerVTable::new(clone, do_nothing, do_nothing, do_nothing);
+
+ // The wakers don't have any implementation, so the instance can simply be null.
+ RawWaker::new(ptr::null(), &DUMMY_WAKER_VTABLE)
+}
diff --git a/src/lib.rs b/src/lib.rs
index 0aabb1a..f45768d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -8,6 +8,7 @@
pub mod debug;
pub mod drivers;
pub mod electronics;
+pub mod executor;
pub mod futures;
pub mod gpio;
pub mod leds;
diff --git a/src/sensors/mod.rs b/src/sensors/mod.rs
index c4b962f..f3a0e7a 100644
--- a/src/sensors/mod.rs
+++ b/src/sensors/mod.rs
@@ -1,9 +1,9 @@
+use crate::executor;
use crate::futures;
use crate::result::TockResult;
use crate::syscalls;
use core::cell::Cell;
use core::convert::From;
-use core::executor;
use core::fmt;
use core::mem;
diff --git a/src/sensors/ninedof.rs b/src/sensors/ninedof.rs
index e468690..b5e7191 100644
--- a/src/sensors/ninedof.rs
+++ b/src/sensors/ninedof.rs
@@ -1,8 +1,8 @@
+use crate::executor;
use crate::futures;
use crate::result::TockResult;
use crate::syscalls;
use core::cell::Cell;
-use core::executor;
use core::fmt;
use core::mem;