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

ADR-087 — syscall générique (raw_syscall) : escape hatch temporaire pour le pal std (M5, Lot D) — À RETIRER

Statut : Accepté (ratification BDFL 2026-07-09) — explicitement TEMPORAIRE. Additif couche 0 servant le jalon M5 (lier std sur libair, ADR-076). Re-scellé couche-0-v1.12 le 2026-07-10 (additif, tag signé sous délégation ADR-065). Exception consignée à docs/EXCEPTIONS.md.

Catégorie : Additif couche 0 + entorse assumée à ADR-021 conv. 3 (« pas de wrapper générique pour syscalls multiplexés ») et à la règle « la libc binde la couche 1, jamais la couche 0 » (ADR-077). Aucun symbole existant modifié.

Contexte

Le lien de hello-std contre libair (M5) laisse un symbole indéfini après les Lots A–C : syscall. La libc C-ABI d’Air doit fournir long syscall(long number, ...) parce que le pal unix de Rust std l’appelle en direct :

  • futexsyscall(SYS_futex, …) : aucune fonction libc futex() n’a jamais existé (glibc/musl y accèdent tous par le syscall brut) ; c’est la base des Mutex/Condvar/Once/park de std sur Linux.
  • gettidsyscall(SYS_gettid) : pas de wrapper libc garanti avant glibc 2.30 (2019) ; std le fait en brut par portabilité.

syscall(2) est par nature une trappe non typée (un numéro + 6 mots bruts transmis au noyau). On ne peut ni la rendre typée sans la dénaturer, ni router proprement les numéros (les flags d’opération futex de std rendent tout routage fragile).

Décision

  1. Couche 0 : ajouter air_sys_syscall::raw_syscall::raw_syscall(number, a1..a6) -> c_long — l’instruction syscall/svc 0 brute (2 arches), rendant la valeur brute du noyau. C’est l’équivalent du __syscall de musl.
  2. Libc : shim air_libc_capi::syscall cible-only (#[cfg(target_vendor = "air")], non-variadique 7-params comme open/fcntl) qui binde raw_syscall directement et applique la convention __syscall_ret (-errno[-4095, -1]errno + -1).

Ceci est une entorse assumée : (a) ADR-021 conv. 3 interdit les génériques — mais syscall(2) est l’escape hatch générique, pas un multiplexeur d’ops typées ; (b) la libc ne doit pas taper la couche 0 — mais ce shim le fait, faute d’API typée pour futex.

Statut TEMPORAIRE + plan de retrait

Le BDFL refuse cet appel générique traversant la couche 0 de façon permanente. Accepté uniquement comme débloquant M5. Action item amont (équipe Rust) : faire que le pal unix de std n’ait pas besoin d’un syscall générique sur *-linux-air — router futex/gettid vers des fonctions typées Air, ou fournir un pal Air dédié. Dès l’amont résolu, raw_syscall et le shim syscall disparaissent (et cette exception avec).

Conséquences

  • Positives : débloque le dernier symbole de M5 ; escape hatch correct (tout numéro, future OpenSSH) et confiné (un seul consommateur cible-only).
  • Coût : une entorse doctrinale consignée (EXCEPTIONS.md) + un re-sceau additif (couche-0-v1.12) + une dette explicite à résorber en amont.
  • Périmètre runtime M5 quasi nul : hello-std mono-thread n’appelle jamais futex (contention uniquement) ; le symbole doit seulement exister pour lier.
  • Alternatives rejetées : router SYS_futex/SYS_gettid dans le shim (fragile — décodage des flags futex de std ; casse sur tout autre numéro) ; renvoyer ENOSYS partout (stopgap qui ne prépare pas OpenSSH).

Portée du re-sceau couche-0-v1.12

air_sys_syscall::raw_syscall. Tag signé posé sous délégation additive (ADR-065).