uefi-async
A lightweight, zero-cost asynchronous executor designed specifically for UEFI environments or bare-metal Rust. It provides a simple task scheduler based on a intrusive linked-list and a procedural macro to simplify task registration.
Work in Progress
currently only nano_alloc feature is supported.
Features
- No-Std Compatible: Designed for environments without a standard library (requires
alloc). - Intrusive Linked-List: No additional collection overhead for managing tasks.
- Frequency-Based Scheduling: Define tasks to run at specific frequencies (Hz), automatically converted to hardware ticks.
- Macro-Driven Syntax: A clean, declarative DSL to assign tasks to executors.
- Tiny Control Primitives: Comprehensive support for timeouts, joins, and hardware-precise timing.
- Safe Signaling: Cross-core event notification with atomic state transitions.
- Multicore-Ready: Thread-safe primitives for cross-core signaling and data synchronization.
Tiny Async Control Flow
1. High-Precision Timing
Support for human-readable time units and hardware-aligned synchronization.
async
2. Task Completion & Concurrency
Powerful macros and traits to combine multiple futures.
join!: Runs multiple tasks concurrently; returns().try_join!: Short-circuits and returnsErrif any task fails.join_all!: Collects results from all tasks into a flattened tuple.- Trait-based Joins: Call
.join().awaitor.try_join().awaitdirectly on Tuples, Arrays, or Vectors.
async
3. Timeouts and Guarding
async
4. Advanced Execution Pacing
The Pacer allows you to strictly control the "rhythm" of your loops, essential for smooth 3D rendering or UI animations.
async
5. Oneshot, Channel and Signal...
static ASSET_LOADED: = new;
async
async
// 1. Create a channel for keyboard events with a capacity of 32
extern "efiapi"
Multicore & Multi-Scheduler Concurrency
uefi-async enabling seamless and safe parallel execution across multiple cores and schedulers. It provides a robust suite of synchronization and control primitives designed to handle the complexities of asynchronous multicore tasking.
Thread-Safe Asynchronous Primitives
To ensure data integrity and prevent race conditions during parallel execution, the framework provides three specialized pillars:
- Event-based Futures (Event Listening): Designed for non-blocking coordination, these futures allow tasks to react to external signals or hardware interrupts across different cores without polling.
- Synchronization Primitives (Data Integrity): Reliable data sharing is critical when multiple schedulers access the same memory space. We provide thread-safe containers and locks like Async Mutexes and Atomic Shared States specifically tuned for UEFI.
- Task Control Futures (Execution Management): Granular control over the lifecycle of parallel tasks. This includes Structured Concurrency to spawn, join, or cancel tasks across different schedulers, and Priority Steering to direct critical tasks to specific cores.
Installation
Add this to your Cargo.toml:
[]
= "*"
Usage
1. Define your tasks
Tasks are standard Rust async functions or closures.
2. Initialize and Run
Use the add! macro to set up your executor.
extern crate alloc;
use Box;
use ;
async
async
extern "efiapi"
or more advanced usage:
extern crate alloc;
use ;
use tick;
async
async
async
extern "efiapi"
3. Using various control flows, signals, and tunnels...
// Example: Producer task on Core 1, Consumer task on Core 0
extern "efiapi"
// Task running on Core 1's executor
async
// Task running on Core 0's executor
async
Why use uefi-async?
In UEFI development, managing multiple periodic tasks (like polling keyboard input while updating a UI or handling network packets) manually can lead to "spaghetti code." uefi-async allows you to write clean, linear async/await code while the executor ensures that timing constraints are met without a heavy OS-like scheduler.
License
MIT or Apache-2.0.