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 :
futex—syscall(SYS_futex, …): aucune fonction libcfutex()n’a jamais existé (glibc/musl y accèdent tous par le syscall brut) ; c’est la base desMutex/Condvar/Once/parkde std sur Linux.gettid—syscall(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
- Couche 0 : ajouter
air_sys_syscall::raw_syscall::raw_syscall(number, a1..a6) -> c_long— l’instructionsyscall/svc 0brute (2 arches), rendant la valeur brute du noyau. C’est l’équivalent du__syscallde musl. - Libc : shim
air_libc_capi::syscallcible-only (#[cfg(target_vendor = "air")], non-variadique 7-params commeopen/fcntl) qui binderaw_syscalldirectement 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-stdmono-thread n’appelle jamaisfutex(contention uniquement) ; le symbole doit seulement exister pour lier. - Alternatives rejetées : router
SYS_futex/SYS_gettiddans le shim (fragile — décodage des flags futex de std ; casse sur tout autre numéro) ; renvoyerENOSYSpartout (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).