fix(no_std): the census counters no longer cost the crate bare metal (Cortex-M4F, RV32) - #13
Merged
Merged
Conversation
`cargo check -p rusty_zstd --no-default-features --features alloc` failed with 204 errors on thumbv7em-none-eabihf (Cortex-M4F) and the same on riscv32imac-unknown-none-elf. Every one was `cannot find AtomicU64 in atomic`, and every one was an INSTRUMENT -- reload counts, decode band histograms, kernel reach, walk exits, copy bytes. Not one was a line of codec. Neither part has 64-bit atomics. Found by rusty_RTOS's house gate, which wants the codec on those parts for on-chip OTA payloads and trace capture. Its plan estimated eight statics from a capped rustc report; the real count is 427 fully-qualified uses plus six imports across sixteen files, which is why this is one seam rather than a hundred `#[cfg]`s. `census64` is that seam: - Where 64-bit atomics EXIST it is `pub use core::sync::atomic::AtomicU64` -- the same type, not a wrapper -- so the public statics keep their published type and codegen cannot change. Proved rather than asserted: the asm board over every shipping kernel, fill and finder is identical in all thirty-two columns to the pre-change build, and the identity gates still read GOLD 2F6594F7EEDBD12B / 59,680,638 and LDM 57BE83EA4E1199E8 / 57,796,847. - Where they do not, it is a zero-sized stub: the statics leave BSS and every fetch_add folds away. Not `portable-atomic`, deliberately. It would keep the census readable there and it is the other honest answer, but on a core with no 64-bit atomic instruction it needs a critical-section implementation, and a library that enables that conscripts every downstream firmware's interrupt policy so a diagnostic counter can increment. The seam is one type wide, so a firmware that wants the count can supply portable_atomic::AtomicU64 itself. A zero there means "not measurable on this target", never "measured zero" -- the exact trap this crate's own rules warn about -- so it is published, not buried: census64::CENSUS_LIVE is false on such a build. The REVERSE mistake would be far worse, because a stub selected on a hosted target would make every count-based verdict fiction while every gate still passed. Two guards: a compile-time size check, and a unit test that asserts on BEHAVIOUR rather than on the constant (it counts to 42 and reads it back). CI gains both rungs in the job that already guards the portable configurations, and the README's platform table gains both rows. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements B1 of
rusty_RTOS/docs/plans/build-me-bare.md: the censuscounters were costing rusty_zstd both Kairos bare-metal targets.
The failure
Every one was
cannot find AtomicU64 in atomic, and every one was aninstrument — reload counts, decode band histograms, kernel reach, walk exits,
copy bytes. Not one was a line of codec. Neither part has 64-bit atomics.
The plan estimated eight statics, reading a capped rustc report. The real count
is 427 fully-qualified uses plus six imports across sixteen files, which is
why this is one seam rather than a hundred
#[cfg]s.The fix
census64is the single seam:pub use core::sync::atomic::AtomicU64. Thesame type, not a wrapper, so the public statics keep their published type and
codegen cannot change.
every
fetch_addfolds away.Not
portable-atomic, deliberatelyIt would keep the census readable on those parts and it is the other honest
answer. But on a core with no 64-bit atomic instruction it needs a
critical-section implementation, and a library that enables that feature
conscripts every downstream firmware's interrupt policy so that a diagnostic
counter can increment. The seam is one type wide, so a firmware that does want
the count can supply
portable_atomic::AtomicU64itself.Zero costs nothing here, and says so
A counter that silently reads zero is the exact "stale instrument" trap this
crate's own rules warn about, so it is published rather than buried:
census64::CENSUS_LIVEisfalseon such a build. Zero there means "notmeasurable on this target", never "measured zero".
The reverse mistake would be far worse — a stub selected on a hosted target
would make every count-based verdict fiction while every gate still passed — so
it is gated twice: a compile-time size check, and a unit test that asserts on
behaviour rather than on the constant (it counts to 42 and reads it back).
Evidence the shipping target is untouched
build, across every shipping kernel, fill and finder.
2F6594F7EEDBD12B/ 59,680,638 and LDM57BE83EA4E1199E8/ 57,796,847.clippy -D warnings,fmt --check, the ASCII gate, wasm32stdandalloc, the profile feature, and the bench crate all clean. Cross-checkedagainst
x86_64-unknown-linux-gnuandaarch64-apple-darwintoo.Also here
configurations, so this cannot rot.
CENSUS_LIVEcaveatstated rather than implied.
Closing the loop upstream: once this releases,
rusty_RTOS'sgate-zstdcanmove to the new pin and B1's kill test (
cargo check -p gate-zstd --target thumbv7em-none-eabihf, exit 0 at a crates.io pin) passes.🤖 Generated with Claude Code