简体   繁体   中英

How do I use Tokio Reactor in a #[no_std] environment?

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 <tock-dev@googlegroups.com>"]
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):

  • your "Executor" ("main loop") will want to track some state per task, eg whether you need to poll it, perhaps some linked list to find those that need to be polled.
  • you need a place for that state; you also need to store the Future s wrapped in Spawn<...> . It should be possible to use "static" allocated storage for that.
  • you'll need to implement 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 (eg in the id: usize parameter).
  • you could even try running multiple loops on the same "poll queue", good luck getting it thread-safe :) The future-0.2 ThreadPool might give some ideas how to do that (or the tokio-threadpool crate).
  • you'll probably need to add some "timer" handling to the event loop; a timer should store a 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)
  • some similar handling for async IO; in userspace you'd use 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 )
  • to drive a task you'll want to use 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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM