Continuing the day's libm streak with the long-tail (erf, gamma, fma, remainder, Bessel) and adding two more Linux ABI extensions (timerfd and memfd_create) to both kernels. Eight sprints total in this single session — five POSIX, three Linux ABI — with both kernels now at 77.36% / 76.80% strict POSIX. The session split worked exactly as planned: libc-only POSIX sprints flip both kernels in lockstep because they share userspace/libc/, while Linux extensions get mirrored implementations in each kernel's linux_syscall.{cpp,rs}.
The math long-tail
Eight unique functions × {double, float, long double} plus six scalar Bessels = 27 entries. erf and erfc use the Abramowitz & Stegun 7.1.26 rational approximation (~1.5e-7 max error). gamma and lgamma use the Pugh-Lanczos g=7, n=9 coefficients (~15 digits on Re(z) > 0) with reflection through gamma(x)·gamma(1-x) = π/sin(πx) for negative arguments. fma compiles to __builtin_fma which becomes VFMADD on Haswell-and-newer x86. remainder is IEEE round-to-nearest reduction; remquo packs the low 3 bits of the integer quotient with sign per POSIX. Bessel J_n and Y_n use the textbook split: power series for |x| ≤ 2, asymptotic sqrt(2/(πx)) · trig for |x| > 2, with forward recurrence for higher orders. The transition region near |x| ≈ 2-3 is ~1e-3 not the ~1e-12 we hit elsewhere — POSIX scoring is "implemented" so it's fine, and a future phase could swap in vendored fdlibm if any workload demands tighter accuracy.
timerfd and memfd_create — Linux extensions, no per-process page tables required
Both fit the same pattern as eventfd from earlier in the session: pure file-descriptor based, no signal/timer subsystem coupling, no dependency on the per-process page tables work that's blocking Tier 3 dynamic linker. timerfd is implemented as lazy-evaluation: no IRQ fires, the read syscall computes the number of expirations using the kernel's monotonic millisecond counter at call time. That's exactly what libuv-style and chronyd-style polling main loops want — they read in their reactor loop anyway. memfd_create is an anonymous heap-backed file fd that grows on write past end (exponential 4 KB → 2x). Read, write, lseek, and ftruncate work via the existing per-fd position field; mmap support waits for VMA tracking when per-process page tables land. Both syscalls got mirrored implementations in C++ (FdType::TimerFd / FdType::MemFd with state structs) and JefeRust (slot-table based, Vec<u8> for memfd backing).
The score after one big day
| Sprint | Track | Δ POSIX cpp | Δ POSIX rust |
|---|---|---|---|
| LIBM-PHASE-1 (bit-manip) | POSIX | +96 | +96 |
| LIBM-PHASE-2 (transcendentals) | POSIX | +72 | +72 |
| COMPLEX-MATH | POSIX | +69 | +69 |
| FENV | POSIX | +11 | +11 |
| LIBM-LONGTAIL | POSIX | +27 | +27 |
| LINUX-EVENTFD | Linux ABI | 0* | 0* |
| LINUX-TIMERFD | Linux ABI | 0* | 0* |
| LINUX-MEMFD | Linux ABI | 0* | 0* |
| Total | +275 | +275 |
* Linux extensions don't move the POSIX scoreboard — they move a different one (real Linux workloads that now run). Aggregate Linux ABI compat moved from ~20-25% to ~25-30% with three new extension syscalls landed.
Final POSIX strict numbers: C++ JefeOS at 77.36%, JefeRust at 76.80%. Up from 55.63%/55.07% at session start — that's +21.73 percentage points each kernel in one sitting. The mathtest harness now covers ~100 subtests across all five POSIX sprints. Validated through commit 6482cc9 end-to-end on JefeRust VM; the long-tail validation is pending because JefeRust SSH wedged on the latest rebuild cycle (the parallel-N regression listed as a PR #5 follow-up). Both kernels build clean — the wedge is SSH server, not kernel correctness.
What's between us and 85%
From 77% → 85% is +97 entries. The cheap libc cleanup wins (partial→yes promotion sweeps in pthreads/wchar/stdio/fs categories) probably get us another ~30 entries to ~80%. Past that, the remaining gaps are real kernel surface — pthreads timed-wait kernel paths (52 cpp:no), fileio (21), fs (18), aio (8 entirely kernel), dlfcn (6 needs dynamic linker which needs per-process page tables). The one big swing that unlocks both Linux Tier 3+ AND the dlfcn POSIX entries is per-process page tables for the C++ kernel — a multi-week effort that's been on the backlog as #8.
What's Next
- POSIX partial→yes audit — review existing partial-status entries across pthreads/wchar/stdio/fs and promote what's actually fully implemented. Could land ~20-30 more entries.
- Linux signalfd / signalfd4 — last shared-AS-friendly Linux extension before the VFS-coupled ones (inotify/fanotify). Unlocks busybox init + Go runtimes.
- JefeRust SSH parallel regression — listed as PR #5 follow-up, blocks reliable VM validation when running multiple sequential commands. Worth one focused session.
- Per-process page tables for C++ JefeOS (#8) — multi-week swing that unlocks the 85% POSIX ceiling AND Linux Tier 3 dynamic linker AND epoll/pidfd/io_uring AND the semtest case 3 fix. Needs explicit decision before committing.