Skip to content

Add NEON GF(256) kernels for FEC encode/decode on ARM targets - #2

Open
wkumik wants to merge 3 commits into
mainfrom
claude/ruby-fpv-performance-t0u557
Open

Add NEON GF(256) kernels for FEC encode/decode on ARM targets#2
wkumik wants to merge 3 commits into
mainfrom
claude/ruby-fpv-performance-t0u557

Conversation

@wkumik

@wkumik wkumik commented Jul 5, 2026

Copy link
Copy Markdown
Owner

The FEC codec's only optimized path was 32-bit x86 assembly, so all real
targets (Pi, Radxa, OpenIPC) ran the scalar byte-at-a-time table lookup
loops. Add NEON implementations of addmul1/mul1 using nibble-split vtbl
table lookups, processing 16 bytes per iteration, for both aarch64 and
armv7 NEON. The NEON path is enabled only after a one-time self test in
fec_init verifies it matches the scalar reference exactly; platforms
without NEON (e.g. Pi Zero W, ARMv6) keep the scalar path.

Add test_fec (make test_fec) that encodes, erases and decodes blocks and
verifies recovery; verified on x86 (scalar), aarch64 (NEON), armv7+NEON
and armv6 (scalar) via qemu-user.

Co-Authored-By: Claude Fable 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01TWFTzQ3aWucyVgKpyf6HcT

claude added 3 commits July 5, 2026 07:53
The FEC codec's only optimized path was 32-bit x86 assembly, so all real
targets (Pi, Radxa, OpenIPC) ran the scalar byte-at-a-time table lookup
loops. Add NEON implementations of addmul1/mul1 using nibble-split vtbl
table lookups, processing 16 bytes per iteration, for both aarch64 and
armv7 NEON. The NEON path is enabled only after a one-time self test in
fec_init verifies it matches the scalar reference exactly; platforms
without NEON (e.g. Pi Zero W, ARMv6) keep the scalar path.

Add test_fec (make test_fec) that encodes, erases and decodes blocks and
verifies recovery; verified on x86 (scalar), aarch64 (NEON), armv7+NEON
and armv6 (scalar) via qemu-user.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TWFTzQ3aWucyVgKpyf6HcT
- Consumer wait: replace the sem_trywait + fixed 200us sleep + retry poll
  with a blocking sem_clockwait on CLOCK_MONOTONIC honoring the caller's
  timeout (glibc >= 2.30; other libcs keep the previous behavior). The
  consumer now wakes immediately on sem_post instead of finishing a fixed
  sleep, and does not burn CPU polling while idle. The previously
  commented-out sem_timedwait attempt had a unit bug (timeout scaled by
  1e6 instead of 1e3) and used CLOCK_REALTIME, which jumps on NTP sync.
- Enqueue ordering: fill the queue slot (payload + metadata) before
  advancing the published write index, so a consumer woken between the
  index update and the memcpy can no longer read a partially written slot.
- Rx thread: map poll fd indexes to radio interface indexes when building
  the pollfd array instead of rescanning all interfaces for every ready fd.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TWFTzQ3aWucyVgKpyf6HcT
The video output FIFO to the streamer is opened blocking, so a stalled
video player made write() block the router main loop, delaying
retransmission requests and all radio/IPC processing (the 'main loop took
too long' overloads). Route the writes through a 512KB ring buffer
drained by a dedicated writer thread:

- The router loop now only memcpys into the ring (never blocks on the
  player). If the player stalls long enough to fill the ring, new data is
  dropped and reported as a truncated write, feeding the existing IO
  error alarm logic. Writer IO errors (EPIPE etc) are reported back on
  the next output call, feeding the same restart logic as before.
- The writer thread polls POLLOUT with a short timeout and writes at most
  PIPE_BUF bytes per wakeup, so it never blocks indefinitely and stops
  promptly when the pipe is closed or reopened.

Also fix the pipe open retry loop, which did not stop on success: it
opened the FIFO up to 200 times, leaking the first 199 descriptors, and
pass a mode to open(O_CREAT) as required.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TWFTzQ3aWucyVgKpyf6HcT
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants