I am trying to implement futures on the Tock OS embedded operating system. I'm trying to using Tokio in a #[no_std]
environment.
My Cargo.toml
file looks like this:
[package]
name = "nrf52dk"
version = "0.1.0"
authors = ["Tock Project Developers <[email protected]>"]
build = "build.rs"
[profile.dev]
panic = "abort"
lto = true
opt-level = "z"
debug = true
[profile.release]
panic = "abort"
lto = true
opt-level = "z"
debug = true
[dependencies]
cortexm4 = { path = "../../arch/cortex-m4" }
capsules = { path = "../../capsules" }
kernel = { path = "../../kernel" }
nrf52 = { path = "../../chips/nrf52" }
nrf5x = { path = "../../chips/nrf5x" }
futures = {version = "0.2.0", default-features = false }
This compiles with no errors but when I add tokio-reactor = "0.1.1"
, I get the error: error[E0463]: can't find crate for std
. I understand this is because Tokio imports some stuff from the std library.
Is it possible to get around this problem?
As far as I can tell, you don't. Tokio Reactor 0.1.1 imports many things from the standard library, none of them conditionally.
Most of the imports could probably be switched to libcore
alternatives, but Arc
requires memory allocation, which lives in the alloc
crate.
As an example of a crate that supports no_std
, check out Futures 0.1.20. This has a feature flag to opt-in to functionality that requires the standard library.
If you wish to do this, you'll need to contribute substantial effort to Tokio and all of its dependencies to add feature flags to opt-in to all the functionality that requires the standard library. It would be worth opening an issue with the maintainers to coordinate such an effort.
Expanding on what Shepmaster already said: you don't want tokio
; it's based on mio
, which is unlikely to ever work in a kernel, especially without heap allocation / std.
So how to drive tasks (spawned Future
s) in such environment (this is written for the futures
0.1.x series):
Future
s wrapped in Spawn<...>
. It should be possible to use "static" allocated storage for that.UnsafeNotify
(and the base trait Notify
), probably for some raw pointer/&'static
reference to the task (including the state); notify
needs to be able to queue tasks to get polled in a thread safe way. The {clone,drop}_{raw,id}
functions can be empty as you'll be using static allocations anyway. notify
also needs to schedule the main loop if it is sleeping. The queue itself will need some global state too ("list head+tail"); if you need different queues you can store a reference to it too in a NotifyHandle
(e.g. in the id: usize
parameter).ThreadPool
might give some ideas how to do that (or the tokio-threadpool
crate).NotifyHandle
to the task it is supposed to wake on a timeout, some state to track whether the timeout was hit, and the event loop needs a list of active (pointers to) timers to determine how long to wait. (the tokio-timer
crate might give you some ideas how to implement this)select
with a timeout (or platform specific optimized version of it), in a kernel you'll probably have to find other ways :) (In the tokio
world this is provided by the Reactor
, which is based on mio
)poll_future_notify
In futures-0.2 NotifyHandle
became Waker
, and UnsafeNotify
became UnsafeWake
; the id: usize
context is gone (just use a struct with all the data you need to implement UnsafeWake
for). Instead of storing Spawn<...>
for a future you need to manually store a LocalMap
for each task, which is then be used to create a Context
with Context::without_spawn
, which is then passed to Future::poll
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With