1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//!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.
//!
//! WIP
//! --------------------------------
//! currently only `nano_alloc` feature is supported.
//!
//! Features
//! --------------------------------
//! * **No-Std Compatible**: Designed for environments without a standard library (only 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.
//!
//! Architecture
//! --------------------------------
//! The project consists of two main components:
//!
//! 1. **The Executor**: A round-robin scheduler that polls `TaskNode`s based on timing requirements.
//! 2. **The Task Macro**: A procedural macro that handles the boilerplate of pinning futures and registering them to executors.
//!
//! Installation
//! --------------------------------
//! Add this to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! uefi-async = "*"
//!
//! ```
//!
//! 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.
//!
//! ```rust
//! extern crate alloc;
//! use alloc::boxed::Box;
//! use uefi_async::nano_alloc::{Executor, TaskNode};
//!
//! async fn calc_1() {}
//! async fn calc_2() {}
//!
//! extern "efiapi" fn process(arg: *mut c_void) {
//! // 1. Create executor
//! Executor::new()
//! // 2. Register tasks
//! .add(&mut TaskNode::new(Box::pin(calc_1()), 0))
//! .add(&mut TaskNode::new(Box::pin(calc_2()), 60))
//! // 3. Run the event loop
//! .run_forever();
//! }
//! ```
//!
//! or more advanced usage:
//!
//! ```rust
//! extern crate alloc;
//! use uefi_async::nano_alloc::{Executor, add};
//! use uefi_async::util::tick;
//!
//! async fn af1() {}
//! async fn af2(_: usize) {}
//! async fn af3(_: usize, _:usize) {}
//!
//! extern "efiapi" fn process(arg: *mut c_void) {
//! if arg.is_null() { return }
//! let ctx = unsafe { &mut *arg.cast::<Context>() };
//! let core = ctx.mp.who_am_i().expect("Failed to get core ID");
//!
//! // 1. Create executor
//! let mut executor1 = Executor::new();
//! let mut executor2 = Executor::new();
//! let mut cx = Executor::init_step();
//!
//! let offset = 20;
//! // 2. Use the macro to register tasks
//! // Syntax: executor => { frequency -> future }
//! add! (
//! executor1 => {
//! 0 -> af1(), // Runs at every tick
//! 60 -> af2(core), // Runs at 60 HZ
//! },
//! executor2 => {
//! 10u64.saturating_sub(offset) -> af3(core, core),
//! 30 + 10 -> af1(),
//! },
//! );
//!
//! loop {
//! calc_sync(core);
//!
//! // 3. Run the event loop manually
//! executor1.run_step(tick(), &mut cx);
//! executor2.run_step(tick(), &mut cx);
//! }
//! }
//! ```
//!
//! 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
//! --------------------------------
//! This project is licensed under the MIT License or Apache-2.0. (temporary)
/// pretty unsafe, but it works.
/// WIP
/// WIP