AtomVM Internals
Relevant source files
The following files were used as context for generating this wiki page:
AtomVM is an abstract machine designed to implement a functional subset of the Bogdan Erlang Abstract Machine (BEAM) instruction set. It simulates in software the execution of bytecode instructions compiled from Erlang or Elixir source code, specifically optimized for resource-constrained micro-controllers like the ESP32 and STM32. Sources: doc/src/atomvm-internals.md:10-30, doc/src/index.rst:11-15
The runtime execution engine is responsible for loading BEAM opcodes, managing process lifecycles, handling memory allocation/reclamation, and interfacing with host hardware or operating systems. By providing a pre-emptive multitasking environment with lightweight processes and message passing, AtomVM allows developers to use a modern actor-based concurrency model on devices with as little as 128KB of RAM. Sources: doc/src/atomvm-internals.md:32-42, doc/src/welcome-to-atomvm.md:65-75
Core Architecture and Data Structures
The GlobalContext
The GlobalContext is the root data structure and serves as a singleton representing an instance of the virtual machine. It manages process tables, atom storage, module loading, and reference-counted binaries shared between processes. Sources: doc/src/atomvm-internals.md:52-65
The diagram shows the major management fields within the GlobalContext structure. Sources: doc/src/atomvm-internals.md:73-85
Process Management and Contexts
Each Erlang process is encapsulated in a Context structure. Processes move between different states (waiting, running, or ready) and are managed via doubly-linked ring structures within the GlobalContext. Sources: doc/src/atomvm-internals.md:87-105
| Process List | Description |
|---|---|
processes_table | Master list of all processes currently in the system. |
waiting_processes | Processes suspended waiting for a message or timeout. |
running_processes | Processes currently being executed by a scheduler. |
ready_processes | Processes eligible to run once a scheduler becomes available. |
| Sources: doc/src/atomvm-internals.md:88-95 |
Execution Model
The Scheduler
AtomVM supports Symmetric Multi-Processing (SMP), running one scheduler thread per available CPU core. Schedulers pick processes from the ready_processes list and execute them until they yield due to waiting for a message or exhausting their "reductions" (computational quota). Sources: doc/src/atomvm-internals.md:204-215
This sequence demonstrates the scheduler loop and process yielding mechanism. Sources: doc/src/atomvm-internals.md:204-230
JIT and Native Execution
AtomVM offers multiple execution modes to balance performance and memory usage:
- Emulated (EMU): The default mode where BEAM bytecode is interpreted.
- Just-In-Time (JIT): Compiles Erlang bytecode to native machine code at runtime (available on x86_64, aarch64, armv6m, and riscv32).
- Native: Executing code precompiled on a desktop (Ahead-of-Time).
- Hybrid: A combination of native and emulated code.
Sources: doc/src/atomvm-internals.md:144-165
Communication and Synchronization
Mailboxes and Signals
Processes communicate via mailboxes using lock-free data structures. When a message is sent, it is enqueued in an "outer" mailbox using atomic CAS (Compare-And-Swap) operations. The recipient process later moves these to an "inner" mailbox for processing. Sources: doc/src/atomvm-internals.md:275-285
Signals are special messages used for out-of-band management, such as:
- Querying process information via
process_info/1,2. - Triggering garbage collection on another process.
- Handling traps when a process must block until a specific condition is met.
Sources: doc/src/atomvm-internals.md:288-305
Synchronization Mechanisms
On SMP builds, AtomVM utilizes various primitives depending on platform capabilities:
- Mutexes and Condition Variables: Provided by the host SDK (e.g., FreeRTOS on ESP32).
- RW Locks: Used for protecting the ETS table list.
- Atomics: Used for mailboxes; replaced by critical sections on platforms like the Raspberry Pi RP2040 which lack hardware atomics.
Sources: doc/src/atomvm-internals.md:237-255
Memory Management and ETS
ETS Tables
AtomVM provides a subset of the Erlang Term Storage (ETS) interface. Tables are conceptually "owned" by the process that created them and are destroyed when that process terminates. Sources: doc/src/atomvm-internals.md:387-395, doc/src/atomvm-internals.md:464-472
| Component | Description |
|---|---|
EtsTable | Stores metadata (name, access type, key position). |
EtsHashTable | The underlying hash table implementing the set type. |
HNode | Individual entries containing a pointer to a dedicated Heap fragment. |
Heap | Stores a copy of the Erlang term data added to the table. |
| Sources: doc/src/atomvm-internals.md:400-420 |
Stacktraces and Line Numbers
Stacktraces are reconstructed using information from the runtime stack and the Line chunk of BEAM files. Including line information adds memory overhead:
- line-refs table: Maps 16-bit refs to line numbers (
num_line_refs * 2bytes). - filenames table: Maps indices to source filenames.
- line-ref-offsets list: Maps code offsets to line references.
Sources: doc/src/atomvm-internals.md:320-365
Platform Specifics
WebAssembly (Wasm) Port
The Wasm port uses the Emscripten SDK and can run in browsers or NodeJS. It leverages proxy-to-pthread to run the main AtomVM loop in a Web Worker, preventing the browser's UI thread from freezing. Sources: doc/src/atomvm-internals.md:534-545
Browser Integration Features:
- run_script: Erlang processes can execute Javascript on the main thread.
- Promises: JS can
awaitresults from Erlang processes via a promise-resolution mechanism involving Erlang resources. - Events: HTML5 events (click, keypress, etc.) can be registered and handled as messages in Erlang.
Sources: doc/src/atomvm-internals.md:548-585, src/platforms/emscripten/tests/src/test_html5.html:30-45
Hardware Flashing
On embedded targets like the ESP32, the AtomVM binary (bootloader, partition map, and VM) is flashed starting at 0x1000. The Erlang application (compiled .avm file) is flashed to the data partition, typically at 0x210000. Sources: doc/src/getting-started-guide.md:68-85
The AtomVM internals provide a robust foundation for executing concurrent, functional applications on highly constrained hardware by abstracting complex low-level scheduling and memory management into a predictable, BEAM-compatible environment. Sources: doc/src/atomvm-internals.md:43-50, doc/src/welcome-to-atomvm.md:105-115