Change:
that our docs say That's not really correct though... at least according to the Nomicon, we , which is different from LLVM's. The kinds of ordering that exist are the same (at least insofar as Rust exposes them), but the details of the rules around data races are different. Code that mixes atomic and non-atomic accesses on the same location can behave differently under both models (concretely, some programs that are UB under C11 are no longer UB under LLVM). So if people interpret "same as LLVM's" too strongly, they might be mislead. Cc
I think this question is actually trickier than it sounds, because I see periodical interest in bringing in some of LLVM's extensions with respect to C11 (, element-wise atomic memcpy...) to Rust. A clear "we use the C11 memory model, not LLVM's" stance could be interpreted as closing that door.
Well as far as I am concerned that is the current stance. But it doesn't close any doors. Switching from C11 to LLVM's model makes strictly more programs defined, that's the only difference. IOW, that's a non-breaking change. Moving from LLVM's to C's model, on the other hand, turns some well-defined programs into UB. So, C11 is also the conservative future-compatible choice here.
This is not true of all of LLVM's features though. For example, LLVM's unordered atomics can be emulated with relaxed C11 atomics without loss of correctness (but potentially at a performance cost). In this respect, there is room for a "we mostly follow the C11 model, but allow ourselves to adopt LLVM extensions which can be pessimistically implemented on top of the C11 building blocks" stance.
is not a thing in Rust right now though. :) So for the APIs we currently expose, saying we use C11 is the conservative future-compatible choice -- and I actually think this is the current normative choice, based on what the Nomicon says (it's also what I told everyone over the last years). Extending Rust's API beyond C11's would change that game -- I'll comment on when I find the time. But I don't see any reason why that would be in conflict with saying that right now, Rust follows C11.
Point taken ;)
Oh and I don't think element-wise atomic memcpy is even an extension of the model; that's just an intrinsic for a loop that can already be expressed in the existing model.
Well, today LLVM is clearly unable to optimize a loop of the corresponding relaxed atomic load/store operation into a performant implementation of its element-wise memcpy intrinsic, because it is unable to coalesce neighboring atomic loads and stores. But that's arguably an LLVM optimizer issue, not a semantic limitation of C11 atomics.
Indeed that would have been my argument. :)
Seems like the standard library should be fixed. Want to file a PR?
PR filed:

Discussion:
//! //! Each method takes an [`Ordering`] which represents the strength of //! the memory barrier for that operation. These orderings are the <del> //! same as [LLVM atomic orderings][1]. For more information see the [nomicon][2]. </del> <ins> //! same as the [C++20 atomic orderings][1]. For more information see the [nomicon][2]. </ins> //! //! [`Ordering`]: enum.Ordering.html //! <del> //! [1]: https://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations </del> <ins> //! [1]: https://en.cppreference.com/w/cpp/atomic/memory_order </ins> //! [2]: ../../../nomicon/atomics.html //! //! Atomic variables are safe to share between threads (they implement [`Sync`])

/// operations synchronize other memory while additionally preserving a total order of such /// operations across all threads. /// <del> /// Rust's memory orderings are [the same as /// LLVM's](https://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations). </del> <ins> /// Rust's memory orderings are [the same as those of /// C++20](https://en.cppreference.com/w/cpp/atomic/memory_order). </ins> /// /// For more information see the [nomicon]. ///

pub enum Ordering { /// No ordering constraints, only atomic operations. /// <del> /// Corresponds to LLVM's [`Monotonic`] ordering. </del> <ins> /// Corresponds to [`memory_order_relaxed`] in C++20. </ins> /// <del> /// [`Monotonic`]: https://llvm.org/docs/Atomics.html#monotonic </del> <ins> /// [`memory_order_relaxed`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Relaxed_ordering </ins> #[stable(feature = "rust1", since = "1.0.0")] Relaxed, /// When coupled with a store, all previous operations become ordered

/// /// This ordering is only applicable for operations that can perform a store. /// <del> /// Corresponds to LLVM's [`Release`] ordering. </del> <ins> /// Corresponds to [`memory_order_release`] in C++20. </ins> /// <del> /// [`Release`]: https://llvm.org/docs/Atomics.html#release /// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire /// [`Relaxed`]: https://llvm.org/docs/Atomics.html#monotonic </del> <ins> /// [`Release`]: #variant.Release /// [`Acquire`]: #variant.Acquire /// [`Relaxed`]: #variant.Relaxed /// [`memory_order_release`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering </ins> #[stable(feature = "rust1", since = "1.0.0")] Release, /// When coupled with a load, if the loaded value was written by a store operation with

/// /// This ordering is only applicable for operations that can perform a load. /// <del> /// Corresponds to LLVM's [`Acquire`] ordering. </del> <ins> /// Corresponds to [`memory_order_acquire`] in C++20. </ins> /// <del> /// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire /// [`Release`]: https://llvm.org/docs/Atomics.html#release /// [`Relaxed`]: https://llvm.org/docs/Atomics.html#monotonic </del> <ins> /// [`Acquire`]: #variant.Acquire /// [`Release`]: #variant.Release /// [`Relaxed`]: #variant.Relaxed /// [`memory_order_acquire`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering </ins> #[stable(feature = "rust1", since = "1.0.0")] Acquire, /// Has the effects of both [`Acquire`] and [`Release`] together:

/// /// Notice that in the case of `compare_and_swap`, it is possible that the operation ends up /// not performing any store and hence it has just [`Acquire`] ordering. However, <del> /// [`AcqRel`][`AcquireRelease`] will never perform [`Relaxed`] accesses. </del> <ins> /// `AcqRel` will never perform [`Relaxed`] accesses. </ins> /// /// This ordering is only applicable for operations that combine both loads and stores. /// <del> /// Corresponds to LLVM's [`AcquireRelease`] ordering. </del> <ins> /// Corresponds to [`memory_order_acq_rel`] in C++20. </ins> /// <del> /// [`AcquireRelease`]: https://llvm.org/docs/Atomics.html#acquirerelease /// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire /// [`Release`]: https://llvm.org/docs/Atomics.html#release /// [`Relaxed`]: https://llvm.org/docs/Atomics.html#monotonic </del> <ins> /// [`memory_order_acq_rel`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering /// [`Acquire`]: #variant.Acquire /// [`Release`]: #variant.Release /// [`Relaxed`]: #variant.Relaxed </ins> #[stable(feature = "rust1", since = "1.0.0")] AcqRel, /// Like [`Acquire`]/[`Release`]/[`AcqRel`] (for load, store, and load-with-store /// operations, respectively) with the additional guarantee that all threads see all /// sequentially consistent operations in the same order. /// <del> /// Corresponds to LLVM's [`SequentiallyConsistent`] ordering. </del> <ins> /// Corresponds to [`memory_order_seq_cst`] in C++20. </ins> /// <del> /// [`SequentiallyConsistent`]: https://llvm.org/docs/Atomics.html#sequentiallyconsistent /// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire /// [`Release`]: https://llvm.org/docs/Atomics.html#release /// [`AcqRel`]: https://llvm.org/docs/Atomics.html#acquirerelease </del> <ins> /// [`memory_order_seq_cst`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Sequentially-consistent_ordering /// [`Acquire`]: #variant.Acquire /// [`Release`]: #variant.Release /// [`AcqRel`]: #variant.AcqRel </ins> #[stable(feature = "rust1", since = "1.0.0")] SeqCst, }