Skip to content

Commit 5a52202

Browse files
RalfJungLuigiPiucco
authored andcommitted
docs: further revision on read_volatile
1 parent 4b3ce76 commit 5a52202

File tree

1 file changed

+44
-48
lines changed

1 file changed

+44
-48
lines changed

library/core/src/ptr/mod.rs

Lines changed: 44 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@
113113
//! fully contiguous (i.e., has no "holes"), there is no guarantee that this
114114
//! will not change in the future.
115115
//!
116+
//! Allocated objects must behave like "normal" memory: in particular, reads must not have
117+
//! side-effects, and writes must become visible to other threads using the usual synchronization
118+
//! primitives.
119+
//!
116120
//! For any allocated object with `base` address, `size`, and a set of
117121
//! `addresses`, the following are guaranteed:
118122
//! - For all addresses `a` in `addresses`, `a` is in the range `base .. (base +
@@ -1747,69 +1751,61 @@ pub const unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
17471751

17481752
/// Performs a volatile read of the value from `src` without moving it.
17491753
///
1750-
/// Rust does not currently have a rigorously and formally defined memory model,
1751-
/// so the precise semantics of what "volatile" means here is subject to change
1752-
/// over time. That being said, the semantics will almost always end up pretty
1753-
/// similar to [C11's definition of volatile][c11].
1754-
///
1755-
/// Volatile operations are intended to act on I/O memory, and are guaranteed
1756-
/// to not be elided or reordered by the compiler across other volatile
1757-
/// operations. With this in mind, there are two cases of usage that need to
1758-
/// be distinguished:
1759-
///
1760-
/// - When a volatile operation is used for memory inside an [allocation], all
1761-
/// the typical restrictions of Rust-allocated memory apply, meaning things
1762-
/// like data races and mutable aliasing remain as undefined behavior. In
1763-
/// addition, the volatile rule that the operation won't be elided or
1764-
/// reordered applies, such that the operation will access memory and not e.g.
1765-
/// be lowered to a register access or stack pop. The memory in `src` should
1766-
/// remain unchanged. Just like in C, whether an operation is volatile has no
1767-
/// bearing whatsoever on questions involving concurrent access from multiple
1768-
/// threads. Volatile accesses behave exactly like non-atomic accesses in that
1769-
/// regard. All this is because this kind of target-memory may be used from
1770-
/// safe code at any time, and its validity assumptions must not be violated.
1771-
///
1772-
/// - Volatile operations, however, provide a conditionally valid way to access
1773-
/// memory that is _outside_ of any allocation. The main use-case is CPU and
1774-
/// peripheral registers that must be accessed via an I/O memory mapping, most
1775-
/// commonly at fixed addresses reserved by the hardware. These often have
1776-
/// special semantics associated to their manipulation, and cannot be used as
1777-
/// general purpose memory. Here, any address value is possible, from 0 to
1778-
/// [`usize::MAX`], so long as its semantics are well-defined by the target
1779-
/// hardware. The access is restricted to not trap/interrupt. It can (and
1780-
/// usually will) cause side-effects, but note they shouldn't affect
1781-
/// Rust-allocated memory in any way.
1782-
///
1783-
/// The compiler shouldn't change the relative order or number of volatile
1784-
/// memory operations. However, volatile memory operations on zero-sized types
1785-
/// (e.g., if a zero-sized type is passed to `read_volatile`) are noops
1786-
/// and may be ignored.
1754+
/// Rust does not currently have a rigorously and formally defined memory model, so the precise
1755+
/// semantics of what "volatile" means here is subject to change over time. That being said, the
1756+
/// semantics will almost always end up pretty similar to [C11's definition of volatile][c11].
1757+
///
1758+
/// Volatile operations are intended to act on I/O memory. As such, they are considered externally
1759+
/// observable events (just like syscalls), and are guaranteed to not be elided or reordered by the
1760+
/// compiler across other externally observable events. With this in mind, there are two cases of
1761+
/// usage that need to be distinguished:
1762+
///
1763+
/// - When a volatile operation is used for memory inside an [allocation], it behaves exactly like
1764+
/// [`read`], except for the additional guarantee that it won't be elided or reordered (see
1765+
/// above). This implies that the operation will actually access memory and not e.g. be lowered to
1766+
/// a register access or stack pop. Other than that, all the usual rules for memory accesses
1767+
/// apply. In particular, just like in C, whether an operation is volatile has no bearing
1768+
/// whatsoever on questions involving concurrent access from multiple threads. Volatile accesses
1769+
/// behave exactly like non-atomic accesses in that regard.
1770+
///
1771+
/// - Volatile operations, however, may also be used access memory that is _outside_ of any Rust
1772+
/// allocation. The main use-case is CPU and peripheral registers that must be accessed via an I/O
1773+
/// memory mapping, most commonly at fixed addresses reserved by the hardware. These often have
1774+
/// special semantics associated to their manipulation, and cannot be used as general purpose
1775+
/// memory. Here, any address value is possible, including 0 and [`usize::MAX`], so long as the
1776+
/// semantics of such a read are well-defined by the target hardware. The access must not trap. It
1777+
/// can (and usually will) cause side-effects, but those must not affect Rust-allocated memory in
1778+
/// any way. In this use-case, the pointer validity rules in the [module documentation][mod-docs]
1779+
/// may not apply.
1780+
///
1781+
/// Note that volatile memory operations on zero-sized types (e.g., if a zero-sized type is passed
1782+
/// to `read_volatile`) are noops and may be ignored.
17871783
///
17881784
/// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
17891785
/// [allocation]: crate::ptr#allocated-object
1786+
/// [mod-docs]: crate::ptr
17901787
///
17911788
/// # Safety
17921789
///
17931790
/// Behavior is undefined if any of the following conditions are violated:
17941791
///
1795-
/// * `src` must be readable without trapping.
1792+
/// * `src` must be either [valid] for reads, or it must point to memory outside of all Rust
1793+
/// allocations and reading from that memory must:
1794+
/// - not trap, and
1795+
/// - not cause any memory inside a Rust allocation to be modified.
17961796
///
17971797
/// * `src` must be properly aligned.
17981798
///
1799-
/// * No Rust memory may be modified.
1799+
/// * Reading from `src` must produce a properly initialized value of type `T`.
18001800
///
1801-
/// * If operating on an allocation, `src` must point to a properly initialized
1802-
/// value of type `T`, and the safe usage assumptions of the data must be
1803-
/// satisfied.
1804-
///
1805-
/// Like [`read`], `read_volatile` creates a bitwise copy of `T`, regardless of
1806-
/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the returned
1807-
/// value and the value at `*src` can [violate memory safety][read-ownership].
1808-
/// However, modeling volatile memory with non-[`Copy`] types is almost
1809-
/// certainly incorrect.
1801+
/// Like [`read`], `read_volatile` creates a bitwise copy of `T`, regardless of whether `T` is
1802+
/// [`Copy`]. If `T` is not [`Copy`], using both the returned value and the value at `*src` can
1803+
/// [violate memory safety][read-ownership]. However, modeling volatile memory with non-[`Copy`]
1804+
/// types is almost certainly incorrect.
18101805
///
18111806
/// Note that even if `T` has size `0`, the pointer must be properly aligned.
18121807
///
1808+
/// [valid]: self#safety
18131809
/// [read-ownership]: read#ownership-of-the-returned-value
18141810
///
18151811
/// # Examples

0 commit comments

Comments
 (0)