|
79 | 79 | //!
|
80 | 80 | //! [lock-free]: https://en.wikipedia.org/wiki/Non-blocking_algorithm
|
81 | 81 | //!
|
| 82 | +//! # Atomic accesses to read-only memory |
| 83 | +//! |
| 84 | +//! In general, *all* atomic accesses on read-only memory are Undefined Behavior. For instance, attempting |
| 85 | +//! to do a `compare_exchange` that will definitely fail (making it conceptually a read-only |
| 86 | +//! operation) can still cause a page fault if the underlying memory page is mapped read-only. Since |
| 87 | +//! atomic `load`s might be implemented using compare-exchange operations, even a `load` can fault |
| 88 | +//! on read-only memory. |
| 89 | +//! |
| 90 | +//! For the purpose of this section, "read-only memory" is defined as memory that is read-only in |
| 91 | +//! the underlying target, i.e., the pages are mapped with a read-only flag and any attempt to write |
| 92 | +//! will cause a page fault. In particular, an `&u128` reference that points to memory that is |
| 93 | +//! read-write mapped is *not* considered to point to "read-only memory". In Rust, almost all memory |
| 94 | +//! is read-write; the only exceptions are memory created by `const` items or `static` items without |
| 95 | +//! interior mutability, and memory that was specifically marked as read-only by the operating |
| 96 | +//! system via platform-specific APIs. |
| 97 | +//! |
| 98 | +//! As an exception from the general rule stated above, "sufficiently small" atomic loads with |
| 99 | +//! `Ordering::Relaxed` are implemented in a way that works on read-only memory, and are hence not |
| 100 | +//! Undefined Behavior. The exact size limit for what makes a load "sufficiently small" varies |
| 101 | +//! depending on the target: |
| 102 | +//! |
| 103 | +//! | `target_arch` | Size limit | |
| 104 | +//! |---------------|---------| |
| 105 | +//! | `x86`, `arm`, `mips`, `mips32r6, `powerpc`, `riscv32`, `sparc`, `hexagon` | 4 bytes | |
| 106 | +//! | `x86_64`, `aarch64`, `loongarch64`, `mips64`, `mips64r6`, `powerpc64`, `riscv64`, `sparc64`, `s390x` | 8 bytes | |
| 107 | +//! |
| 108 | +//! Atomics loads that are larger than this limit as well as atomic loads with ordering other |
| 109 | +//! than `Relaxed`, as well as *all* atomic loads on targets not listed in the table, might still be |
| 110 | +//! read-only under certain conditions, but that is not a stable guarantee and should not be relied |
| 111 | +//! upon. |
| 112 | +//! |
| 113 | +//! If you need to do an acquire load on read-only memory, you can do a relaxed load followed by an |
| 114 | +//! acquire fence instead. |
| 115 | +//! |
82 | 116 | //! # Examples
|
83 | 117 | //!
|
84 | 118 | //! A simple spinlock:
|
|
0 commit comments