Change:
} } <del> /// A compiler memory fence. </del> <ins> /// A "compiler-only" atomic fence. </ins> /// <del> /// `compiler_fence` does not emit any machine code, but restricts the kinds /// of memory re-ordering the compiler is allowed to do. Specifically, depending on /// the given [`Ordering`] semantics, the compiler may be disallowed from moving reads /// or writes from before or after the call to the other side of the call to /// `compiler_fence`. Note that it does **not** prevent the *hardware* /// from doing such re-ordering. This is not a problem in a single-threaded, /// execution context, but when other threads may modify memory at the same /// time, stronger synchronization primitives such as [`fence`] are required. </del> <ins> /// Like [`fence`], this function establishes synchronization with other atomic operations and /// fences. However, unlike [`fence`], `compiler_fence` only establishes synchronization with /// operations *in the same thread*. This may at first sound rather useless, since code within a /// thread is typically already totally ordered and does not need any further synchronization. /// However, there are cases where code can run on the same thread without being ordered: /// - The most common case is that of a *signal handler*: a signal handler runs in the same thread ///   as the code it interrupted, but it is not ordered with respect to that code. `compiler_fence` ///   can be used to establish synchronization between a thread and its signal handler, the same way ///   that `fence` can be used to establish synchronization across threads. /// - Similar situations can arise in embedded programming with interrupt handlers, or in custom ///   implementations of preemptive green threads. In general, `compiler_fence` can establish ///   synchronization with code that is guaranteed to run on the same hardware CPU. </ins> /// <del> /// The re-ordering prevented by the different ordering semantics are: </del> <ins> /// See [`fence`] for how a fence can be used to achieve synchronization. Note that just like /// [`fence`], synchronization still requires atomic operations to be used in both threads -- it is /// not possible to perform synchronization entirely with fences and non-atomic operations. </ins> /// <del> ///  - with [`SeqCst`], no re-ordering of reads and writes across this point is allowed. ///  - with [`Release`], preceding reads and writes cannot be moved past subsequent writes. ///  - with [`Acquire`], subsequent reads and writes cannot be moved ahead of preceding reads. ///  - with [`AcqRel`], both of the above rules are enforced. </del> <ins> /// `compiler_fence` does not emit any machine code, but restricts the kinds of memory re-ordering /// the compiler is allowed to do. `compiler_fence` corresponds to [`atomic_signal_fence`] in C and /// C++. </ins> /// <del> /// `compiler_fence` is generally only useful for preventing a thread from /// racing *with itself*. That is, if a given thread is executing one piece /// of code, and is then interrupted, and starts executing code elsewhere /// (while still in the same thread, and conceptually still on the same /// core). In traditional programs, this can only occur when a signal /// handler is registered. In more low-level code, such situations can also /// arise when handling interrupts, when implementing green threads with /// pre-emption, etc. Curious readers are encouraged to read the Linux kernel's /// discussion of [memory barriers]. </del> <ins> /// [`atomic_signal_fence`]: https://en.cppreference.com/w/cpp/atomic/atomic_signal_fence </ins> /// /// # Panics ///

Discussion:
The current docs for  explain that function in terms of reorderings: That's somewhat misleading. For good reasons, our  docs quickly transition from "reordering" to "synchronization" terminology: should also be explained in terms of synchronizes-with, to avoid raising any false expectations. Specifically, compilerfence is equivalent to C++ , and so its synchronization rules are very similar to those of except that synchronization only occurs between a thread and its signal handler, not across different threads. Cc Cc
(Sorry, race condition...)

The documentation for with say "no re-ordering of reads and writes across this point is allowed". As I understand it, for a single thread doesn't give anything more than . E.g., a store before the fence could be moved past a load after then fence. Is that correct? cc
Hmm, that's a good point, though the details are a little subtle. From the : I think what this translates into is that guarantees that: no subsequent operations can be moved before this operation if it is a load, and no operations can be moved after this operation if it is a store. The italic parts there aren't present in the current documentation, so that should probably be rectified. I think some annotated source code would really help here!
It actually depends on the other operation, does it not? stores after the fence can be moved up, but stores cannot. TBH I have a hard time thinking in terms of reorderings; I usually think in terms of what actually happens in the underlying memory model. Some of these models can be fully characterized by the allowed reorderings, but not all of them can (as far as we know). And anyway, SC fences are broken in the C11 memory model and probably going to change in the next version, so...^^ On top of that, all are in a total order, and that is the entire point of . (The website says it but you left it away in your quote. Just making sure nobody thinks that a load is the same as an load. It is not.)
I'm actually not entirely sure about that. Another store to the same memory location shouldn't be ordered before, but I don't see from the reference text why an unrelated store with couldn't be. I'd be happy for this to be rephrased this in terms of the memory model, but I'm not entirely sure how we'd even do that. Proposals welcome. I think talking about what can and cannot happen, with examples, is probably the most understandable way to present what the different orderings do. I left off the total order part because it didn't seem directly related to the original question. But you're right that it's a vital part of that shouldn't get lost in the docs!

It says The sequentially-consistent ordering consists of all operation, across all locations, and the order in which they are observed must be consistent across all threads. In particular, if one thread performs two operations (i.e., they are ordered by program-order), then the order in which it does them must match the order in which every other thread observes them. That rules out reordering them. This is the sole justification for the existence of .
Yes, good point. So how about we move the bullet point to bottom and change it to say