AxlTask – Task Pool and Arena
AP worker pool, region-based arena allocator, preallocated buffer pool, and async work helpers.
Headers:
<axl/axl-task.h>– Arena allocator and AP task pool<axl/axl-buf-pool.h>– Preallocated buffer pool (LIFO free-stack)<axl/axl-async.h>– AP-offloaded async work
Overview
UEFI systems have multiple CPU cores, but only one – the Bootstrap Processor (BSP) – can call Boot Services (I/O, networking, protocol calls). The other cores are Application Processors (APs) that can run compute-heavy tasks in parallel.
BSP (main core) APs (worker cores)
├─ Boot Services (gBS) ├─ CRC/checksum
├─ Protocol calls ├─ Decompression
├─ Network I/O ├─ Hash computation
├─ File I/O ├─ Data parsing
├─ axl_printf └─ Memory-only work
└─ Event loop (no Boot Services!)
AP constraints: APs cannot call Boot Services, axl_printf,
axl_fopen, or any UEFI protocol function. They can only access
memory (including the arena allocator, which uses lock-free CAS).
Arena Allocator
Lock-free bump allocator for AP-safe memory. Pre-allocates a contiguous block; allocations are O(1) pointer bumps with CAS (no locks needed for concurrent AP access).
AXL_AUTOPTR(AxlArena) arena = axl_arena_new(4096);
// AP-safe: can be called from any core
void *buf = axl_arena_alloc(arena, 256);
// BSP-only: reset frees all allocations at once
axl_arena_reset(arena);
Task Pool
Submit work to an AP and get a callback on the BSP when it completes:
// Create pool (discovers available APs)
AxlTaskPool *pool = axl_task_pool_new();
// AP work function (runs on a worker core)
void compute(void *arg, AxlArena *arena) {
Result *r = axl_arena_alloc(arena, sizeof(Result));
r->crc = calculate_crc(arg);
}
// BSP completion callback (runs on main core)
void on_done(void *arg, AxlArena *arena) {
axl_printf("CRC computed on AP\n");
}
AxlArena *arena = axl_arena_new(1024);
axl_task_pool_submit(pool, compute, data, arena, on_done);
// Poll for completions (call from event loop or main loop)
axl_task_pool_poll(pool);
// Single-core fallback: if no APs available, submit runs
// the work synchronously on the BSP.
axl_task_pool_free(pool);
AxlBufPool
Preallocated fixed-size buffer pool with LIFO free-stack. Zero-copy:
get returns a buffer pointer, put returns it to the pool.
No allocation or freeing in the hot path.
AXL_AUTOPTR(AxlBufPool) pool = axl_buf_pool_new(4, 64 * 1024);
// ^ ^
// 4 buffers, 64KB each
void *buf = axl_buf_pool_get(pool); // grab a buffer (NULL if exhausted)
// ... use buf ...
axl_buf_pool_put(pool, buf); // return to pool
AxlAsync
Convenience wrapper: submit AP work and get a BSP callback via the event loop (combines AxlTask + AxlLoop idle source).
AxlAsync *async = axl_async_new(loop, 4); // max 4 pending jobs
axl_async_submit(async, work_fn, data, arena, done_fn);
// work_fn runs on AP, done_fn fires on BSP via loop idle
axl_async_free(async);
API Reference
AxlTask
Defines
-
AXL_TASK_ID_INVALID
Typedefs
-
typedef struct AxlTaskPool AxlTaskPool
-
typedef uint32_t AxlTaskId
Functions
-
AxlArena *axl_arena_new(size_t capacity)
Create a new arena with fixed capacity. BSP-only.
All memory is zeroed.
- Parameters:
capacity – total bytes available
- Returns:
arena handle, or NULL on failure.
-
void axl_arena_free(AxlArena *arena)
Free backing memory. BSP-only.
- Parameters:
arena – arena to free (NULL-safe)
-
void *axl_arena_alloc(AxlArena *arena, size_t size)
Allocate from arena. AP-safe (lock-free CAS).
Returns zeroed, 8-byte-aligned memory. Returns NULL on exhaustion.
- Parameters:
arena – arena
size – bytes to allocate
-
void axl_arena_reset(AxlArena *arena)
Reset arena, freeing all allocations.
Backing memory retained and zeroed. BSP-only.
- Parameters:
arena – arena to reset
-
size_t axl_arena_remaining(AxlArena *arena)
Get bytes remaining in the arena.
- Parameters:
arena – arena to query
- Returns:
bytes remaining.
-
size_t axl_arena_capacity(AxlArena *arena)
Get total capacity of the arena.
- Parameters:
arena – arena to query
- Returns:
total capacity in bytes.
-
AxlTaskPool *axl_task_pool_new(void)
Create a new task pool.
Locates MP Services and dispatches APs.
- Returns:
pool handle, or NULL on error.
-
void axl_task_pool_free(AxlTaskPool *pool)
Free the task pool. Signals all workers to exit.
- Parameters:
pool – pool to free (NULL-safe)
-
AxlTaskId axl_task_pool_submit(AxlTaskPool *pool, AxlTaskProc proc, void *arg, AxlArena *arena, AxlTaskComplete on_complete)
Submit a task. Non-blocking.
On single-core, runs synchronously.
- Parameters:
pool – task pool
proc – task procedure (AP-safe)
arg – argument passed to proc and on_complete
arena – arena for task allocations (NULL = no arena)
on_complete – BSP callback when done (NULL = fire-and-forget)
- Returns:
task ID, or AXL_TASK_ID_INVALID if all workers busy.
-
size_t axl_task_pool_poll(AxlTaskPool *pool)
Poll for completed tasks. Call once per event loop iteration.
- Parameters:
pool – task pool
- Returns:
number of tasks completed this poll cycle.
-
bool axl_task_pool_done(AxlTaskPool *pool, AxlTaskId id)
Check if a task is done.
- Parameters:
pool – task pool
id – task ID
- Returns:
true if task is done (or ID is invalid).
-
size_t axl_task_pool_available(AxlTaskPool *pool)
Get idle worker count.
- Parameters:
pool – task pool
- Returns:
number of idle workers.
-
size_t axl_task_pool_worker_count(AxlTaskPool *pool)
Get total worker count.
- Parameters:
pool – task pool
- Returns:
total worker count (0 on single-core).
-
bool axl_task_pool_is_single_core(AxlTaskPool *pool)
Check if the pool is in single-core fallback mode.
- Parameters:
pool – task pool
- Returns:
true if single-core (no APs available).
AxlBufPool
Typedefs
-
typedef struct AxlBufPool AxlBufPool
Functions
-
AxlBufPool *axl_buf_pool_new(size_t count, size_t buf_size)
Create a new buffer pool.
Allocates count buffers of buf_size bytes each in a single contiguous block. All buffers are initially available.
- Parameters:
count – number of buffers
buf_size – size of each buffer in bytes
- Returns:
pool handle, or NULL on failure.
-
void *axl_buf_pool_get(AxlBufPool *pool)
Get a buffer from the pool.
- Parameters:
pool – buffer pool
- Returns:
pointer to a buffer, or NULL if the pool is exhausted.
-
void axl_buf_pool_put(AxlBufPool *pool, void *buf)
Return a buffer to the pool.
The buffer must have been obtained from this pool via axl_buf_pool_get. NULL-safe (no-op if pool or buf is NULL).
- Parameters:
pool – buffer pool
buf – buffer to return
-
size_t axl_buf_pool_available(AxlBufPool *pool)
Get the number of available (free) buffers.
- Parameters:
pool – buffer pool (NULL returns 0)
- Returns:
number of buffers available for axl_buf_pool_get.
-
size_t axl_buf_pool_buf_size(AxlBufPool *pool)
Get the size of each buffer in the pool.
- Parameters:
pool – buffer pool
- Returns:
buffer size in bytes (0 if pool is NULL).
-
void axl_buf_pool_free(AxlBufPool *pool)
Free the pool and all backing memory. NULL-safe.
- Parameters:
pool – buffer pool to free
AxlAsync
Defines
-
AXL_ASYNC_INVALID
Functions
-
AxlAsync *axl_async_new(AxlLoop *loop, size_t max_pending)
Create a new async work queue.
Creates an internal task pool and slot array.
- Parameters:
loop – event loop (idle source installed here)
max_pending – maximum concurrent async jobs
- Returns:
async handle, or NULL on failure.
-
void axl_async_free(AxlAsync *async)
Free the async work queue. Drains pending work.
- Parameters:
async – async handle (NULL-safe)
-
AxlAsyncHandle axl_async_submit(AxlAsync *async, AxlTaskProc work_fn, void *data, AxlArena *arena, AxlTaskComplete done_cb)
Submit work to an AP core.
On multi-core, dispatches work_fn to an AP and returns immediately. On single-core, runs work_fn and done_cb synchronously before returning.
- Parameters:
async – async handle
work_fn – AP work function (same as AxlTaskProc)
data – argument passed to work_fn and done_cb
arena – arena for AP allocations (NULL OK)
done_cb – BSP callback when done (NULL = fire-and-forget)
- Returns:
handle for axl_async_cancel, or AXL_ASYNC_INVALID on failure.
-
bool axl_async_cancel(AxlAsync *async, AxlAsyncHandle handle)
Cancel pending async work (best-effort).
AP work continues to completion, but done_cb is suppressed.
- Parameters:
async – async handle
handle – handle from axl_async_submit
- Returns:
true if cancelled, false if handle invalid or already completed.