Further clarificarion for atomic and UnsafeCell docs: · qinheping/verify-rust-std@81fcbcd (original) (raw)

`@@ -33,12 +33,6 @@

`

33

33

`//! atomic load (via the operations provided in this module). A "modification of an atomic object"

`

34

34

`//! refers to an atomic store.

`

35

35

`//!

`

36

``

`-

//! The most important aspect of this model is that conflicting non-synchronized accesses are

`

37

``

`-

//! Undefined Behavior unless both accesses are atomic. Here, accesses are conflicting if they

`

38

``

`-

//! affect overlapping regions of memory and at least one of them is a write. They are

`

39

``

`-

//! non-synchronized if neither of them happens-before the other, according to the

`

40

``

`-

//! happens-before order of the memory model.

`

41

``

`-

//!

`

42

36

`//! The end result is almost equivalent to saying that creating a shared reference to one of the

`

43

37

`` //! Rust atomic types corresponds to creating an atomic_ref in C++, with the atomic_ref being

``

44

38

`//! destroyed when the lifetime of the shared reference ends. The main difference is that Rust

`

`@@ -47,20 +41,25 @@

`

47

41

`` //! objects" and "non-atomic objects" (with atomic_ref temporarily converting a non-atomic object

``

48

42

`//! into an atomic object).

`

49

43

`//!

`

50

``

`-

//! That said, Rust does inherit the C++ limitation that non-synchronized conflicting atomic

`

51

``

`-

//! accesses may not partially overlap: they must be either disjoint or access the exact same

`

52

``

`-

//! memory. This in particular rules out non-synchronized differently-sized atomic accesses to the

`

53

``

`-

//! same data unless all accesses are reads.

`

``

44

`+

//! The most important aspect of this model is that data races are undefined behavior. A data race

`

``

45

`+

//! is defined as conflicting non-synchronized accesses where at least one of the accesses is

`

``

46

`+

//! non-atomic. Here, accesses are conflicting if they affect overlapping regions of memory and at

`

``

47

`+

//! least one of them is a write. They are non-synchronized if neither of them happens-before

`

``

48

`+

//! the other, according to the happens-before order of the memory model.

`

54

49

`//!

`

55

``

`-

//! [cpp]: https://en.cppreference.com/w/cpp/atomic

`

56

``

`-

//! [cpp-intro.races]: https://timsong-cpp.github.io/cppwp/n4868/intro.multithread#intro.races

`

``

50

`+

//! The other possible cause of undefined behavior in the memory model are mixed-size accesses: Rust

`

``

51

`+

//! inherits the C++ limitation that non-synchronized conflicting atomic accesses may not partially

`

``

52

`+

//! overlap. In other words, every pair of non-synchronized atomic accesses must be either disjoint,

`

``

53

`+

//! access the exact same memory (including using the same access size), or both be reads.

`

57

54

`//!

`

58

``

`` -

//! Each method takes an [Ordering] which represents the strength of

``

59

``

`-

//! the memory barrier for that operation. These orderings behave the

`

60

``

`-

//! same as the corresponding [C++20 atomic orderings][1]. For more information see the [nomicon][2].

`

``

55

`` +

//! Each atomic access takes an [Ordering] which defines how the operation interacts with the

``

``

56

`+

//! happens-before order. These orderings behave the same as the corresponding [C++20 atomic

`

``

57

`+

//! orderings][cpp_memory_order]. For more information, see the [nomicon].

`

61

58

`//!

`

62

``

`-

//! [1]: https://en.cppreference.com/w/cpp/atomic/memory_order

`

63

``

`-

//! [2]: ../../../nomicon/atomics.html

`

``

59

`+

//! [cpp]: https://en.cppreference.com/w/cpp/atomic

`

``

60

`+

//! [cpp-intro.races]: https://timsong-cpp.github.io/cppwp/n4868/intro.multithread#intro.races

`

``

61

`+

//! [cpp_memory_order]: https://en.cppreference.com/w/cpp/atomic/memory_order

`

``

62

`+

//! [nomicon]: ../../../nomicon/atomics.html

`

64

63

`//!

`

65

64

```` //! ```rust,no_run undefined_behavior

````

66

65

`//! use std::sync::atomic::{AtomicU16, AtomicU8, Ordering};

`

157

156

`//!

`

158

157

`//! # Atomic accesses to read-only memory

`

159

158

`//!

`

160

``

`-

//! In general, all atomic accesses on read-only memory are Undefined Behavior. For instance, attempting

`

``

159

`+

//! In general, all atomic accesses on read-only memory are undefined behavior. For instance, attempting

`

161

160

`` //! to do a compare_exchange that will definitely fail (making it conceptually a read-only

``

162

161

`//! operation) can still cause a segmentation fault if the underlying memory page is mapped read-only. Since

`

163

162

`` //! atomic loads might be implemented using compare-exchange operations, even a load can fault

``

`@@ -173,7 +172,7 @@

`

173

172

`//!

`

174

173

`//! As an exception from the general rule stated above, "sufficiently small" atomic loads with

`

175

174

`` //! Ordering::Relaxed are implemented in a way that works on read-only memory, and are hence not

``

176

``

`-

//! Undefined Behavior. The exact size limit for what makes a load "sufficiently small" varies

`

``

175

`+

//! undefined behavior. The exact size limit for what makes a load "sufficiently small" varies

`

177

176

`//! depending on the target:

`

178

177

`//!

`

179

178

`` //! | target_arch | Size limit |

``