Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Roadmap — clôture du PAL (std::sys::pal::air) : les 3 chantiers

Statut : note de roadmap (opérationnelle). Fige le plan de clôture du PAL décidé par ADR-075. S’appuie sur l’audit face-PAL (audit-face-pal-cloture-fr.md), le journal rt/DECISIONS.md, et ADR-049/050/052/056. Non normative : les évolutions structurantes restent des ADR.

✅ CLÔTURE 2026-07-10 — CHANTIER B/C FAIT, hello-std TOURNE 2 ARCHES (M5 atteint). Le lien de hello-std contre libair passe de 12 → 0 symboles indéfinis ; il s’exécute on-targethello from std on air + exit 0 sur x86_64-air (carbon) ET aarch64-air (raspi). Un programme Rust std static-PIE lié intégralement sans glibc. Pari ADR-076 tenu de bout en bout. Re-sceaux couche-0-v1.12 (ADR-087 raw_syscall) + couche-1-v1.9 (ADR-086 introspection thread). Statut vivant : etat-avancement.md. Prochaine phase = OpenSSH / air-sshd (ADR-074). Dette ouverte : retirer l’escape hatch syscall/raw_syscall (ADR-087) avec l’équipe Rust. (Le détail ci-dessous — chantiers A/B/C — est conservé comme historique du plan ; il est désormais réalisé.)

⚠️ MISE À JOUR 2026-07-08 — chantier A FAIT, chantier B pivoté (option A). (Superseded par le bandeau de clôture ci-dessus : le chantier B/C est terminéhello-std tourne on-target 2 arches, jalon M5 atteint le 2026-07-10. Le texte ci-dessous est conservé comme trace du pivot.)

  • Chantier A COMPLET : les 6 briques additives couche 1 sont mergées (AirCondvar, AirOnce, os_str, mutation d’env air_env::set/unset, yield_now/set_thread_name, destructeurs thread_local). Un bug de fondation aarch64 (TCB recouvrant la zone TLS) a été traqué au gdb et corrigé, validé 2 arches.
  • Chantier B pivoté vers l’OPTION A (ADR-076) : le portage a montré que std (cible unix/linux) EXIGE une libc — on abandonne le pal air custom ; std réutilise le pal unix + la libc d’Air (libair) fournit les symboles (zéro glibc). La cible porte env=musl + vendor=air. build-std=std compile entièrement pour Air, sans patch libc/std. Cible de production = compléter libair pour lier stdhello-std on-target 2 arches (§5 chantier C).

1. Point de départ (dé-risqué)

Fait et prouvé on-target 2 arches (selftest rt/, exit 42) : _start + self-reloc static-PIE, TLS Variant I/II + errno #[thread_local] + TCB, spawn clone3/CLONE_SETTLS

  • join futex, allocateur réel air-alloc branché, layering ADR-052 (air-rt = shim mince, runtime en couche 1). Migration #![no_std] : 10/10 crates que le PAL compose.

Verdict audit face-PAL : zéro gap fondateur. Chaque primitive std::sys a sa brique couche 1. Reste : quelques briques additives + écrire le backend + bootstrapper std.

2. Table de correspondance std::sys → brique couche 1

Primitive std::sysBrique couche 1État
alloc (GlobalAlloc)air_alloc::GlobalAllocator✅ branché on-target
thread spawn/joinair_runtime::thread (spawn/JoinHandle)✅ (ergonomie boxée à câbler)
thread yield/sleep/idcouche-0 sched_yield · air_base_core::time::sleep · current_tid◐ yield/name à surfacer
thread_local (TLS/TCB)air_runtime::{thread_control_block, thread_local_storage}dtors à ajouter
sync Mutex/RwLockair_thread::{AirMutex, AirRwLock} (futex, loom)
sync Condvar / Onceprimitives futex air_thread (publiques)additif
time Instant/SystemTimeair_base_core::time::{AirInstant, AirSystemTime}
fs File/metadata/dirair_filesystem::AirFile + AirFileMetadata + read_dir✅ (sceau v1.0, #214)
net TCP/UDP/lookupair_socket::* + AirNameResolver
process Command/Childair_process::{AirCommand, AirProcess} + air_pipe
env varsair_env::{get, vars}set/unset additif
args (argv)air_runtime::args
stdioair_stdio::{stdin, stdout, stderr}
pathair_base_core::path::AirPath
os_strsubstrat [u8]/Vec<u8> (AirPath owned)newtype additif
random (getrandom)couche-0 getrandom (lien direct — pas air-crypto)
backtrace/unwindpanic=abort → surface minimale

3. Chantier A — briques additives couche 1 (host-testables, sous barrière 100 %)

Chacune = descellement additif (ADR-051), aucune refonte d’API scellée :

  • A1 air_thread::AirCondvar (sur futex_wait_word/futex_wake_one).
  • A2 air_thread::AirOnce (AtomicU32 + futex) — pour std::sync::Once/lazy.
  • A3 destructeurs thread_local! : register_dtor + exécution en fin de thread (champ DTV présent dans le TCB). Mineur (panic=abort, threads courts) mais requis par std::sys::thread_local.
  • A4 mutation d’env : air_env::{set, unset} (pour std::env::set_var/remove_var) — gouverner l’__environ mutable (audit musl ADR-047).
  • A5 newtype os_str : AirOsStr/AirOsString (paire empruntée/possédée sur [u8]).
  • A6 thread::yield_now (passthrough couche-0 sched_yield) + nommage (prctl(PR_SET_NAME)) sur cible.

4. Chantier B — le backend std::sys::pal::air (phase 3)

Un rust-src patché (ADR-075) : ajouter sys/pal/air qui compose les briques ci-dessus (jamais de re-syscall). Portage module par module, chacun validé par un bout de std qui l’exerce. Ordre naturel (dépendances croissantes) :

  1. alloc + process::exit/abort (déjà amorcés) → un std qui démarre/quitte.
  2. time, env, argsstd::env, SystemTime, Instant.
  3. thread + thread_local + sync (mutex/rwlock/condvar/once) → std::thread, std::sync.
  4. fs (File/metadata/read_dir) → std::fs.
  5. stdio (Stdin/out/err, is_terminal) → println!/std::io.
  6. process (Command/Child) → std::process.
  7. net (TCP/UDP + lookup) → std::net.
  8. path / os_strstd::path, OsStr.
  9. random (seed HashMap via couche-0 getrandom), pipe, backtrace minimal.

5. Chantier C — bootstrap std + lane CI nightly (phase 4)

  • C1 faire compiler -Z build-std=std pour *-linux-air (2 arches).
  • C2 lier et exécuter un « hello std » : ouvre un fichier (AirFile), un socket, un thread, écrit via println! — prouvé exit propre sur x86_64 (carbon) + aarch64 (raspi).
  • C3 lane CI nightly dédiée qui rejoue C1+C2 → referme le carve-out de rt/ (aujourd’hui hors barrière).
  • C4 (après démo) : enregistrer les cibles Tier-3 en amont (upstream rustc).

6. Résidus sécurité à refermer au passage

  • canari de pile depuis auxv AT_RANDOM (matérialiser %fs:0x28 / tpidr_el0).
  • mprotect RELRO après self-relocation (.data.rel.ro/.got inscriptibles sinon).
  • placement d’errno à offset C-ABI fixe dans le TCB (utile à la future libc, pas au PAL Rust).

7. Ordre de bataille

  1. ADR-075 (fait) + cette note.
  2. Chantier A (A1→A6) — briques additives, host-testées, sous 100 %. Faible risque, parallélisable, valeur immédiate (elles servent aussi le userland no_std).
  3. Chantier B — pal module par module (§4), chaque étape adossée à un fragment std.
  4. Chantier C — bootstrap std + « hello std » 2 arches + lane nightly.
  5. Résidus sécurité (§6) au fil de l’eau.

8. Rappel : host-first

Les briques du chantier A et la logique testable se valident sur l’hôte (les crates couche 1 tournent déjà en gnu). Seuls le backend pal (chantier B, construit via build-std) et le bootstrap std (chantier C) exigent la cible + le nightly — validés par selftest/hello-std on-target (carbon x86, raspi aarch64), comme le programme rt/ actuel.