Add Volatile ReadBarrier and WriteBarrier - #597
Merged
Conversation
These are net10 rather than net9, so the guard covers everything below net10. Both are implemented as Interlocked.MemoryBarrier, a full fence. That is strictly stronger than the acquire-only and release-only barriers the BCL emits, so it is correct, but it is not free: on x86 and x64 the BCL versions constrain the JIT without emitting a processor instruction, where a full fence does. Noted on both. Memory ordering cannot be asserted deterministically from a unit test, since the message passing pattern used to exercise them succeeds on x86 and x64 even with no barrier at all. The tests cover that the calls compile and complete on every target and behave under real concurrency, and the comment says what they do not prove. API count 1109 -> 1111.
This was referenced Sep 10, 2026
This was referenced Sep 11, 2026
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.
Two members. The audit item said net9; they are actually net10 — absent from the 9.0.20 ref pack, present in 10.0.12 — so the guard is
!NET10_0_OR_GREATERand net9.0 gets them too.A full fence is the only option, and it is not free
Volatile.ReadBarrieris an acquire barrier (LoadLoad + LoadStore) andVolatile.WriteBarrieris a release barrier (StoreStore + LoadStore). Below net10 there is no one-way barrier in the BCL at all —Interlocked.MemoryBarrierandThread.MemoryBarrierare both full fences, and both are available everywhere Polyfill targets, including netstandard2.0 and net461.A full fence provides a superset of the orderings each one-way barrier guarantees, so the polyfill is correct, never weaker. The divergence is cost, and it is worth being precise about because it is not the usual "slightly slower" case: on x86 and x64 the BCL's
ReadBarrier/WriteBarrierconstrain JIT reordering without emitting any processor instruction, since the hardware memory model already provides acquire/release for ordinary loads and stores. A full fence emits a real serialising instruction there. So the polyfilled versions cost something the BCL versions cost nothing for, rather than merely costing more. That is//Note:d on both.What the tests do and do not prove
Memory ordering is not deterministically testable from a unit test. The canonical message-passing pattern —
payload = i; WriteBarrier(); publish(i)againstwait(i); ReadBarrier(); read payload— passes on x86 and x64 even with no barrier at all, so a green test says nothing about the ordering guarantee.Rather than dress that up, the tests cover what they actually can: that both calls compile and complete on every target framework, and that the barriers behave under real two-thread concurrency across 200 publish/consume iterations with a bounded spin. A comment at the top of the file states plainly what is not being proven. This would catch a barrier that throws, that fails to resolve on some target, or that deadlocks — not a barrier that is too weak.
Result
API count 1109 → 1111.
Solution clean in Release, Consume clean across all 22 TFMs, tests green on net11.0 (1699), net10.0 (1699), net9.0 (1699), net8.0 (1696), net462 (1661), plus PublicTests, EmbeddedTests, UnsafeTests, NoRefsTests and NoExtrasTests.