Skip to content

Commit b3268cf

Browse files
fbqjannau
authored andcommitted
rust: sync: atomic: Add ordering annotation types
Preparation for atomic primitives. Instead of a suffix like _acquire, a method parameter along with the corresponding generic parameter will be used to specify the ordering of an atomic operations. For example, atomic load() can be defined as: impl<T: ...> Atomic<T> { pub fn load<O: AcquireOrRelaxed>(&self, _o: O) -> T { ... } } and acquire users would do: let r = x.load(Acquire); relaxed users: let r = x.load(Relaxed); doing the following: let r = x.load(Release); will cause a compiler error. Compared to suffixes, it's easier to tell what ordering variants an operation has, and it also make it easier to unify the implementation of all ordering variants in one method via generic. The `TYPE` associate const is for generic function to pick up the particular implementation specified by an ordering annotation. Signed-off-by: Boqun Feng <boqun.feng@gmail.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Benno Lossin <lossin@kernel.org> Reviewed-by: Elle Rhumsaa <elle@weathered-steel.dev> Link: https://lore.kernel.org/all/20250719030827.61357-4-boqun.feng@gmail.com/
1 parent de4275b commit b3268cf

2 files changed

Lines changed: 106 additions & 0 deletions

File tree

rust/kernel/sync/atomic.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,7 @@
1818
1919
#[allow(dead_code, unreachable_pub)]
2020
mod internal;
21+
pub mod ordering;
2122

2223
pub use internal::AtomicImpl;
24+
pub use ordering::{Acquire, Full, Relaxed, Release};
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! Memory orderings.
4+
//!
5+
//! The semantics of these orderings follows the [`LKMM`] definitions and rules.
6+
//!
7+
//! - [`Acquire`] provides ordering between the load part of the annotated operation and all the
8+
//! following memory accesses, and if there is a store part, the store part has the [`Relaxed`]
9+
//! ordering.
10+
//! - [`Release`] provides ordering between all the preceding memory accesses and the store part of
11+
//! the annotated operation, and if there is a load part, the load part has the [`Relaxed`]
12+
//! ordering.
13+
//! - [`Full`] means "fully-ordered", that is:
14+
//! - It provides ordering between all the preceding memory accesses and the annotated operation.
15+
//! - It provides ordering between the annotated operation and all the following memory accesses.
16+
//! - It provides ordering between all the preceding memory accesses and all the following memory
17+
//! accesses.
18+
//! - All the orderings are the same strength as a full memory barrier (i.e. `smp_mb()`).
19+
//! - [`Relaxed`] provides no ordering except the dependency orderings. Dependency orderings are
20+
//! described in "DEPENDENCY RELATIONS" in [`LKMM`]'s [`explanation`].
21+
//!
22+
//! [`LKMM`]: srctree/tools/memory-model/
23+
//! [`explanation`]: srctree/tools/memory-model/Documentation/explanation.txt
24+
25+
/// The annotation type for relaxed memory ordering, for the description of relaxed memory
26+
/// ordering, see [module-level documentation].
27+
///
28+
/// [module-level documentation]: crate::sync::atomic::ordering
29+
pub struct Relaxed;
30+
31+
/// The annotation type for acquire memory ordering, for the description of acquire memory
32+
/// ordering, see [module-level documentation].
33+
///
34+
/// [module-level documentation]: crate::sync::atomic::ordering
35+
pub struct Acquire;
36+
37+
/// The annotation type for release memory ordering, for the description of release memory
38+
/// ordering, see [module-level documentation].
39+
///
40+
/// [module-level documentation]: crate::sync::atomic::ordering
41+
pub struct Release;
42+
43+
/// The annotation type for fully-ordered memory ordering, for the description fully-ordered memory
44+
/// ordering, see [module-level documentation].
45+
///
46+
/// [module-level documentation]: crate::sync::atomic::ordering
47+
pub struct Full;
48+
49+
/// Describes the exact memory ordering.
50+
#[doc(hidden)]
51+
pub enum OrderingType {
52+
/// Relaxed ordering.
53+
Relaxed,
54+
/// Acquire ordering.
55+
Acquire,
56+
/// Release ordering.
57+
Release,
58+
/// Fully-ordered.
59+
Full,
60+
}
61+
62+
mod internal {
63+
/// Sealed trait, can be only implemented inside atomic mod.
64+
pub trait Sealed {}
65+
66+
impl Sealed for super::Relaxed {}
67+
impl Sealed for super::Acquire {}
68+
impl Sealed for super::Release {}
69+
impl Sealed for super::Full {}
70+
}
71+
72+
/// The trait bound for annotating operations that support any ordering.
73+
pub trait Ordering: internal::Sealed {
74+
/// Describes the exact memory ordering.
75+
const TYPE: OrderingType;
76+
}
77+
78+
impl Ordering for Relaxed {
79+
const TYPE: OrderingType = OrderingType::Relaxed;
80+
}
81+
82+
impl Ordering for Acquire {
83+
const TYPE: OrderingType = OrderingType::Acquire;
84+
}
85+
86+
impl Ordering for Release {
87+
const TYPE: OrderingType = OrderingType::Release;
88+
}
89+
90+
impl Ordering for Full {
91+
const TYPE: OrderingType = OrderingType::Full;
92+
}
93+
94+
/// The trait bound for operations that only support acquire or relaxed ordering.
95+
pub trait AcquireOrRelaxed: Ordering {}
96+
97+
impl AcquireOrRelaxed for Acquire {}
98+
impl AcquireOrRelaxed for Relaxed {}
99+
100+
/// The trait bound for operations that only support release or relaxed ordering.
101+
pub trait ReleaseOrRelaxed: Ordering {}
102+
103+
impl ReleaseOrRelaxed for Release {}
104+
impl ReleaseOrRelaxed for Relaxed {}

0 commit comments

Comments
 (0)