Event Primitives – AxlEvent, AxlCancellable, AxlWait
The foundational synchronization primitives. All three compose: an
AxlCancellable is an AxlEvent with stop-token semantics; the
wait helpers drive a throwaway AxlLoop until an event fires, a
condition holds, a timeout elapses, or Ctrl-C is received.
AxlEvent– one-shot latch wrapping a UEFI event. Replaces the olderAxlCompletion(same mechanical behavior, UEFI-native name).AxlCancellable– typed stop token shared across async ops; cancel it once and every op observing it aborts withAXL_CANCELLED.AxlWait– interruptible wait helpers (axl_wait_for,axl_wait_for_flag,axl_wait_ms, …) built onAxlLoop.
A note on naming: “event” appears three times in AXL docs – the
event loop (the dispatcher), an event source (a thing
registered with the loop), and AxlEvent (one kind of source).
UEFI carries the same overload; an AxlEvent is a one-shot latch
backed by a UEFI event, and the event loop dispatches them.
Headers:
<axl/axl-event.h>,
<axl/axl-cancellable.h>,
<axl/axl-wait.h>.
API Reference
AxlEvent
Defines
-
axl_event_new()
Captures the caller’s file/line for leak reporting via the tier-1 resource registry. See docs/AXL-Runtime.md §4.2.1.
Typedefs
-
typedef struct AxlCancellable AxlCancellable
-
typedef void *AxlEventHandle
AxlEventHandle:
Raw UEFI event handle (
EFI_EVENT). Used where firmware owns the event — protocol completion tokens, protocol-notify events. For AXL-managed events useAxlEventand passaxl_event_handle(e)where a handle is required (e.g.,axl_loop_add_event).
Functions
-
AxlEvent *axl_event_new_impl(const char *file, int line)
Create a new, unsignalled event.
- Returns:
new AxlEvent, or NULL on failure. Free with axl_event_free().
-
void axl_event_signal(AxlEvent *e)
Signal the event. Idempotent, NULL-safe.
Safe from any context — protocol notifications, nested callbacks, interrupt-like handlers.
- Parameters:
e – event (NULL-safe)
-
void axl_event_reset(AxlEvent *e)
Reset the event to an unsignalled state. NULL-safe.
Drops any pending signal so the same event can be reused across multiple wait cycles.
- Parameters:
e – event (NULL-safe)
-
bool axl_event_is_set(const AxlEvent *e)
Fast check: is this event currently signalled?
Reads an internal flag without driving the loop. Transitions:
axl_event_signal(e)→ is_set becomes trueaxl_event_reset(e)→ is_set becomes falsesuccessful
axl_event_wait[_timeout]→ is_set becomes false (the wait consumed the signal via CheckEvent in the loop dispatch; the flag mirrors the backend state)
For the full wait-for-signal behavior with timeout and cancel support, use axl_event_wait_timeout().
- Parameters:
e – event (NULL-safe)
- Returns:
true between signal and the next reset / successful wait, else false. Returns false for NULL.
-
AxlEventHandle axl_event_handle(const AxlEvent *e)
Get the raw UEFI event handle wrapped by this AxlEvent.
Used when registering the event with the loop via axl_loop_add_event, which takes a handle so the same entry point serves AXL-managed events and firmware-owned ones alike.
- Parameters:
e – event (NULL-safe, returns NULL)
- Returns:
the wrapped handle, or NULL for NULL / uninitialized.
-
int axl_event_wait(AxlEvent *e, AxlCancellable *cancel)
Wait indefinitely for the event to be signalled.
The CPU idles between events. Returns early on Ctrl-C or a signalled cancellable. Equivalent to axl_event_wait_timeout(e, cancel, 0).
- Parameters:
e – event
cancel – optional cancel token (NULL = only Ctrl-C)
- Returns:
0 on signal, -1 on invalid arg, AXL_CANCELLED on Ctrl-C or cancel.
-
int axl_event_wait_timeout(AxlEvent *e, AxlCancellable *cancel, uint64_t timeout_us)
Wait for the event with a timeout.
The CPU idles between events. A timeout_us of 0 means wait forever. Returns early on Ctrl-C or a signalled cancellable.
- Parameters:
e – event
cancel – optional cancel token
timeout_us – timeout in microseconds (0 = forever)
- Returns:
0 on signal, -1 on timeout or invalid arg, AXL_CANCELLED on Ctrl-C or cancel.
AxlCancellable
Defines
-
axl_cancellable_new()
Captures the caller’s file/line for leak reporting via the tier-1 resource registry. See docs/AXL-Runtime.md §4.2.1.
Typedefs
-
typedef struct AxlCancellable AxlCancellable
Functions
-
AxlCancellable *axl_cancellable_new_impl(const char *file, int line)
Create a new, unsignalled cancellable.
- Returns:
new AxlCancellable, or NULL on failure. Free with axl_cancellable_free().
-
void axl_cancellable_free(AxlCancellable *c)
Free a cancellable. NULL-safe.
Must only be called after every async op that observes this cancellable has completed (via its callback) or is otherwise no longer holding a reference. Freeing while an op still references it results in a dangling event handle.
- Parameters:
c – cancellable (NULL-safe)
-
void axl_cancellable_cancel(AxlCancellable *c)
Cancel every async op currently observing this cancellable.
Idempotent — calling more than once is safe and has no additional effect. Safe to call from any context (protocol notifications, nested callbacks). NULL-safe.
- Parameters:
c – cancellable (NULL-safe)
-
bool axl_cancellable_is_cancelled(const AxlCancellable *c)
Check whether the cancellable has been signalled.
- Parameters:
c – cancellable (NULL-safe)
- Returns:
true if axl_cancellable_cancel() was called, else false. Returns false for NULL.
-
void axl_cancellable_reset(AxlCancellable *c)
Reset the cancellable to an unsignalled state. NULL-safe.
Drops any pending cancel signal so the same cancellable can be reused for a fresh batch of async ops. Only call once all ops that might have observed the prior signal have completed.
- Parameters:
c – cancellable (NULL-safe)
AxlWait
Typedefs
-
typedef struct AxlCancellable AxlCancellable
-
typedef bool (*AxlCondFn)(void *ctx)
AxlCondFn:
Condition predicate. Returns true when the wait should end.
-
typedef void (*AxlTickFn)(void *ctx)
AxlTickFn:
Periodic side-effect called between waits. Typical use is to drive a UEFI protocol state machine forward (e.g. call protocol->Poll) so the condition can become true.
Functions
-
void axl_sleep(uint64_t seconds)
Sleep for the specified number of seconds. CPU idles; Ctrl-C returns early.
-
void axl_msleep(uint64_t milliseconds)
Sleep for the specified number of milliseconds. CPU idles; Ctrl-C returns early.
-
void axl_usleep(uint64_t microseconds)
Sleep for the specified number of microseconds (rounded up to ms granularity). CPU idles; Ctrl-C returns early.
-
int axl_wait_for_flag(volatile const bool *flag, AxlCancellable *cancel, uint64_t timeout_us)
Wait until *flag becomes true, with optional cancel + timeout.
CPU idles between 1ms checks. Returns 0 immediately if *flag is already true, or AXL_CANCELLED if
cancelwas already signalled.- Parameters:
flag – flag to observe
cancel – optional cancel token (NULL = only Ctrl-C)
timeout_us – timeout in microseconds (0 = forever)
- Returns:
0 on true, -1 on timeout or invalid arg, AXL_CANCELLED on Ctrl-C or an observed cancellable.
-
int axl_wait_for_word(volatile const uint64_t *word, uint64_t not_ready_value, AxlCancellable *cancel, uint64_t timeout_us)
Wait until *word stops matching not_ready_value.
Covers UEFI completion-token Status polls, DMA flags, and any “keep checking this memory word until it changes” pattern. CPU idles between 1ms checks.
- Parameters:
word – memory word to observe
not_ready_value – value that means “keep waiting”
cancel – optional cancel token
timeout_us – timeout in microseconds (0 = forever)
- Returns:
0 on change, -1 on timeout or invalid arg, AXL_CANCELLED on Ctrl-C or an observed cancellable.
-
int axl_wait_ms(AxlCancellable *cancel, uint64_t ms)
Interruptible sleep with cancellable support.
The long form of axl_msleep — use this when you need to inspect the return code (Ctrl-C vs elapsed) or pass a shared AxlCancellable. The CPU idles for the duration.
Parameter order note: the rest of the wait family places cancel between the subject and the timeout. Sleep has no subject, so cancel comes first. The relative position (cancel immediately before the duration/timeout) is consistent with the other helpers.
- Parameters:
cancel – optional cancel token (NULL = only Ctrl-C)
ms – milliseconds to sleep (0 returns immediately)
- Returns:
0 on elapsed, AXL_CANCELLED on Ctrl-C or cancel.
-
int axl_wait_for(AxlCondFn cond_fn, void *cond_ctx, AxlCancellable *cancel, uint64_t timeout_us)
Wait until cond_fn returns true, with timeout + optional cancel.
cond_fn is evaluated immediately and then every 1ms. CPU idles between evaluations.
- Parameters:
cond_fn – predicate
cond_ctx – opaque context passed to cond_fn
cancel – optional cancel token
timeout_us – timeout in microseconds (0 = forever)
- Returns:
0 on cond_fn true, -1 on timeout or invalid arg, AXL_CANCELLED on Ctrl-C or cancel.
-
int axl_wait_for_with_tick(AxlCondFn cond_fn, void *cond_ctx, AxlTickFn tick_fn, void *tick_ctx, uint64_t tick_us, AxlCancellable *cancel, uint64_t timeout_us)
Wait until cond_fn returns true, running tick_fn each period.
cond_fn is evaluated immediately and then each time tick_fn runs. Use this form when the condition only becomes true after an external state machine is advanced (e.g. calling protocol->Poll on a UEFI driver).
- Parameters:
cond_fn – predicate (required)
cond_ctx – opaque context for cond_fn
tick_fn – periodic side-effect (may be NULL)
tick_ctx – opaque context for tick_fn
tick_us – tick period in microseconds (minimum 1ms)
cancel – optional cancel token
timeout_us – timeout in microseconds (0 = forever)
- Returns:
0 on cond_fn true, -1 on timeout or invalid arg, AXL_CANCELLED on Ctrl-C or cancel.