Skip to content

๐Ÿ”— ABI โ€‹

The ABI module defines Xila's stable C-callable surface for foreign runtimes and C-compatible consumers.

Role in system โ€‹

  • Exposes a C ABI facade over core services (file, memory, task, time, user-related types).
  • Provides symbol and type ownership needed for static/dynamic linkage across Rust and non-Rust components.
  • Supplies per-task file-context indirection used by runtime integrations.

Responsibilities and boundaries โ€‹

In scope

  • Exported C symbols and C-representable data layouts.
  • Conversion between C-level identifiers/pointers and internal Rust APIs.
  • ABI-local context for open file/directory handles.

Out of scope

  • Runtime-specific host-call dispatch mechanics (handled by Bindings).
  • Full parity with every internal Rust API (ABI coverage is intentionally incremental).

Internal architecture โ€‹

The ABI is split into three crates with explicit roles:

This separation prevents duplicate-symbol/linkage ambiguity and keeps contract vs implementation boundaries explicit.

Contract vs implementation

  • Contract: exported C signatures/types and numeric error/result conventions.
  • Implementation: how ABI functions call into VFS/task/memory internals, including lock strategy and helper abstractions.

Lifecycle and execution model โ€‹

  1. Runtime enters ABI call path.
  2. abi_context::Context::call_abi(...) captures current TaskIdentifier.
  3. ABI symbol executes, uses context tables (FileIdentifier, UniqueFileIdentifier) and proxies to module APIs.
  4. Context task binding is cleared after call.

Data/control flow โ€‹

  • File ABI calls convert C inputs -> FileIdentifier -> synchronous VFS wrappers via ABI context maps.
  • Memory ABI calls adapt raw C pointers/sizes to memory manager functions and metadata wrappers.
  • Task/time ABI calls route to module managers with ABI-compatible result codes.

Concurrency and synchronization model โ€‹

  • ABI context uses internal RwLock to guard file/directory maps and active task marker.
  • Some ABI subsystems (notably memory allocation entry points) serialize specific operations with explicit mutexes.
  • Most exported functions are synchronous at the C boundary, with async internals bridged via task::block_on where required.

Dependency model โ€‹

Failure semantics and recovery behavior โ€‹

  • ABI functions typically return numeric result codes (0 success, non-zero mapped from module errors).
  • Errors are logged at boundary points for diagnosability.
  • Invalid pointers/identifiers are rejected early where conversion helpers exist.

Extension points โ€‹

  • Add new exported functions/types in definitions and declarations, then regenerate headers.
  • Extend ABI context identifier ranges or table behavior as new handle classes are introduced.
  • Incrementally expose additional module capabilities through stable C signatures.

Known limitations and trade-offs โ€‹

  • Coverage is partial by design; several exported subsystems include todo!() placeholders in current implementation.
  • C boundary introduces conversion and safety-check overhead versus native Rust calls.
  • ABI stability requires strict versioning discipline for signatures, constants, and generated headers.

References / See also โ€‹