-
-
Notifications
You must be signed in to change notification settings - Fork 14.7k
compiler_fence example is misleading #133014
Copy link
Copy link
Closed
Labels
A-atomicArea: Atomics, barriers, and sync primitivesArea: Atomics, barriers, and sync primitivesA-concurrencyArea: ConcurrencyArea: ConcurrencyA-docsArea: Documentation for any part of the project, including the compiler, standard library, and toolsArea: Documentation for any part of the project, including the compiler, standard library, and toolsT-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.Relevant to the library API team, which will review and decide on the PR/issue.T-opsemRelevant to the opsem teamRelevant to the opsem team
Metadata
Metadata
Assignees
Labels
A-atomicArea: Atomics, barriers, and sync primitivesArea: Atomics, barriers, and sync primitivesA-concurrencyArea: ConcurrencyArea: ConcurrencyA-docsArea: Documentation for any part of the project, including the compiler, standard library, and toolsArea: Documentation for any part of the project, including the compiler, standard library, and toolsT-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.Relevant to the library API team, which will review and decide on the PR/issue.T-opsemRelevant to the opsem teamRelevant to the opsem team
Type
Fields
Give feedbackNo fields configured for issues without a type.
Location
https://doc.rust-lang.org/nightly/core/sync/atomic/fn.compiler_fence.html#examples
Summary
This example makes it look like there is some kind of guarantee for a release fence that isn't paired with an acquire operation or fence, which as far as I can tell, is not the case. (See the C++ docs for regular (thread) fences that do not guarantee anything for an unpaired release fence and compiler (signal) fences that are described as strictly weaker than thread fences.)
So in this example there is no happens-before relation between the store of
IMPORTANT_VARIABLEin main and the load thereof in the signal handler and therefore the signal handler may actually observeIS_READY == trueandIMPORTANT_VARIABLE == 0.Presumably the example should have a load fence in the signal handler and explain in the prose text above that the loads can be reordered, too:
fn signal_handler() { if IS_READY.load(Ordering::Relaxed) { + // prevent later reads from being moved beyond this point + compiler_fence(Ordering::Acquire); assert_eq!(IMPORTANT_VARIABLE.load(Ordering::Relaxed), 42); } }related: #129189