Runtime Architecture
Component Diagram
Section titled “Component Diagram”┌──────────────────────────────────────────────────────────────┐│ Compiled Run Program ││ (generated C code + main) │├──────────────────────────────────────────────────────────────┤│ librunrt.a ││ ││ ┌─────────┐ ┌─────────┐ ┌──────────┐ ┌──────────────┐ ││ │ alloc │ │ string │ │ slice │ │ fmt │ ││ │ (gen ref)│ │ (ptr+ │ │ (dynamic │ │ (printing) │ ││ │ │ │ len) │ │ array) │ │ │ ││ └────┬─────┘ └────┬────┘ └────┬─────┘ └──────────────┘ ││ │ │ │ ││ ┌────┴─────────────┴────────────┴─────────────────────────┐ ││ │ Scheduler (GMP) │ ││ │ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───────────┐ │ ││ │ │ G │ │ G │ │ G │ │ P │ │ P │ │ Channels │ │ ││ │ └───┘ └───┘ └───┘ └─┬─┘ └─┬─┘ └───────────┘ │ ││ │ │ │ │ ││ │ ┌─┴─┐ ┌─┴─┐ │ ││ │ │ M │ │ M │ (OS threads) │ ││ │ └───┘ └───┘ │ ││ └─────────────────────────────────────────────────────────┘ ││ ││ ┌─────────────────────────────────────────────────────────┐ ││ │ Platform Abstraction (vmem) │ ││ │ mmap/VirtualAlloc, pthreads/CreateThread │ ││ └─────────────────────────────────────────────────────────┘ │└──────────────────────────────────────────────────────────────┘Compilation and Linking
Section titled “Compilation and Linking”The Run compiler pipeline produces a C source file that includes run_runtime.h:
Source (.run) → Lexer → Parser → AST → Resolve → TypeCheck → Lower → IR → C Codegen │ generated .c file │ cc -o binary generated.c -lrunrtThe generated C code:
#include "run_runtime.h"for access to all runtime APIs- Defines
void run_main__main(void)as the user’s entry point - Calls
run_gen_alloc/run_gen_free/run_gen_checkfor heap memory - Calls
run_string_*for string operations - Calls
run_slice_*for slice operations - Calls
run_spawnto launch green threads - Calls
run_chan_*for channel operations
Initialization Sequence
Section titled “Initialization Sequence”The program entry point is main() in run_main.c:
int main(void) { run_scheduler_init(); // 1. Initialize scheduler (create Ps, set up main M) run_main__main(); // 2. Run user's main function run_scheduler_run(); // 3. Run scheduler loop until all Gs complete return 0;}Step 1: run_scheduler_init()
Section titled “Step 1: run_scheduler_init()”Future behavior (when scheduler is implemented):
- Query CPU count via
sysconf(_SC_NPROCESSORS_ONLN)(orGetSystemInfoon Windows) - Read
RUN_MAXPROCSenvironment variable (defaults to CPU count) - Allocate P structs (one per logical processor)
- Create the main M (wrapping the main OS thread)
- Bind the main M to P[0]
- Initialize the global run queue
Step 2: run_main__main()
Section titled “Step 2: run_main__main()”The user’s main function runs directly on the main M/P. Any run statements in user code call run_spawn() which creates new Gs and adds them to run queues.
Step 3: run_scheduler_run()
Section titled “Step 3: run_scheduler_run()”Future behavior:
- Enter scheduling loop on the main M
- Pick runnable Gs from local/global queues
- Context-switch to each G, run until it yields or blocks
- When all Gs are dead and all queues empty, return
- Main returns 0
Shutdown Sequence
Section titled “Shutdown Sequence”run_scheduler_run()returns when no runnable Gs remain- All M threads are joined or detached
- P structs and remaining resources are freed
main()returns 0
Current State
Section titled “Current State”The runtime currently operates in a simplified mode:
run_scheduler_init()is a no-oprun_spawn()calls the function directly (synchronous execution, no green threads)run_scheduler_run()is a no-op- All channel operations abort with an error message