-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable async operation #63
Conversation
This allows using the constants in match arms.
As for interesting mbox user applications: Seems that TCP is using it internally, and gnrc_netapi_mbox is available (but then again, that also has a callback style way of using it). CAN is using it, but I have no hardware to play with that. |
gcoap client-side also goes onto the list of easy targets for async support. |
With the complex feature gating of Delay, this is essential for docs usability.
Main merged in once more to get updated tests. Two things are missing yet:
|
1b903bf
to
ab262b6
Compare
This is required (at least) by newer versions of embassy.
ab262b6
to
d517415
Compare
The two stoppers are addressed: There is now an async ztimer test, and thanks to embassy updates, the tests can run on the stable image. APIs don't need to be complete for this to go in, so next plan is to merge. |
This sketch PR adds async building blocks -- wrappers around RIOT APIs that produce futures and can be
.await
ed.It does not add an executor (the branch async-experiments-1 contains one, but it's not very good). The embassy-executor-riot module in the riot-module-examples contains an implementation of an embassy based executor in less than 50 lines of code.
This suffices for simple examples, in particular any UDP echo tests. I'd love to add more APIs, but many are tricky:
TCP (through embedded-nal-async), UART (through embedded-io-async) and GPIO (through embedded-hal-async) should be straightforward enough (but are also not super exciting).
Mutex and message (including msg_bus, which is currently the only way to be notified of IP address changes) are tricky, as for neither, you can get a callback in the originating context. As callbacks are how wakers are triggered, implementing them will need cooperation from the executor. (This is in contrast to what is implemented now: There, the embassy-executor-riot knows nothing of what is implemented on top). The fundamental issues are:
A thread can only wait for one mutex at a time. An executor may have different tasks that wait for different mutexes. (Similarly, an application may find itself in a situation where it needs to wait for either of two mutexes).
As long as mutexes are only used like lightweight critical sections (preventing simultaneous access to any given data structure, eg. while inserting into a linked list), that's all not too bad: For those, even an async environment may just block on them. (Maybe the Rust lint for holding a mutex across await points is even user configurable and could apply to our Mutex locks). However, our use of mutexes in RIOT is mixed (for example, SUIT has a worker lock that's held for full a full firmware update).
Messages are queued or even delivered only on wait. Even if a task could make the executor wait for its requested message when it is idle, unlike a thread a task can't guarantee that its executor is always idle when the task is idle -- so tasks will practically need queues more often than not. But they're accessible only in the sequence they come in (except responses to sent messages -- sending a message and getting the response might be straightforward to implement async'ly). So when one task is awaiting to process messages of type A, and task B has generally ordered messages of type B (but is currently doing some stuff inbetween, like working off the last message), then when a new message of the type that B ordered arrives, followed by one for A, the executor either needs to drop the one for B (in the model of B not having a queue) or needs to delay what is there for A.
We might introduce some per-task queues where the executor dispatches messages as soon as they arrive (and that can probably be done without changes to RIOT), but this feels a lot like just reimplementing mboxes.
(Which also means mboxes are probably on the easy list; gotta look through what can be used with mboxes these days.)