* [PATCH v2 0/2] Add support for print exactly once
@ 2025-11-12 13:16 FUJITA Tomonori
2025-11-12 13:16 ` [PATCH v2 1/2] rust: Add support for calling a function " FUJITA Tomonori
2025-11-12 13:16 ` [PATCH v2 2/2] rust: Add pr_*_once macros FUJITA Tomonori
0 siblings, 2 replies; 3+ messages in thread
From: FUJITA Tomonori @ 2025-11-12 13:16 UTC (permalink / raw)
To: alex.gaynor, ojeda
Cc: a.hindborg, aliceryhl, bjorn3_gh, boqun.feng, dakr, gary, lossin,
rust-for-linux, tmgross
This adds the Rust equivalent of the kernel's DO_ONCE_LITE and
pr_*_once macros.
A proposal for this feature was made in the past [1], but it didn't
reach consensus on the implementation and wasn't merged. After reading
the previous discussions, I implemented it using a different approach.
In the previous proposal, a structure equivalent to std::sync::Once
was implemented to realize the DO_ONCE_LITE macro. The approach tried
to provide Once-like semantics by using two atomic values. As pointed
out in the previous review comments, I think this approach tries to
provide more functionality than needed, making it unnecessarily
complex. Also, because data structures in the .data..once section can
be cleared at any time (via debugfs clear_warn_once), an
implementation using two atomics wouldn't work correctly.
Therefore, I decided to drop the idea of emulating Once and took a
minimal approach to implement DO_ONCE_LITE with only one atomic
variable. While it would be possible to implement the feature entirely
as a Rust macro, the functionality that can be implemented as regular
functions has been extracted and implemented as the OnceLite struct
for better code readability.
[1] https://lore.kernel.org/rust-for-linux/20241126-pr_once_macros-v4-0-410b8ca9643e@tuta.io/
v2:
- improve do_once_lite micro syntax
- move once_lite.rs to kernel/sync/
- add comments (including ORDERING)
- fix rustdoc errors
- use vertical layout for imports
v1: https://lore.kernel.org/rust-for-linux/20251105054731.3194118-1-fujita.tomonori@gmail.com/
FUJITA Tomonori (2):
rust: Add support for calling a function exactly once
rust: Add pr_*_once macros
rust/kernel/print.rs | 70 +++++++++++++++++++++++++++++
rust/kernel/sync.rs | 1 +
rust/kernel/sync/once_lite.rs | 83 +++++++++++++++++++++++++++++++++++
3 files changed, 154 insertions(+)
create mode 100644 rust/kernel/sync/once_lite.rs
base-commit: 3b83f5d5e78ac5cddd811a5e431af73959864390
--
2.43.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH v2 1/2] rust: Add support for calling a function exactly once
2025-11-12 13:16 [PATCH v2 0/2] Add support for print exactly once FUJITA Tomonori
@ 2025-11-12 13:16 ` FUJITA Tomonori
2025-11-12 13:16 ` [PATCH v2 2/2] rust: Add pr_*_once macros FUJITA Tomonori
1 sibling, 0 replies; 3+ messages in thread
From: FUJITA Tomonori @ 2025-11-12 13:16 UTC (permalink / raw)
To: alex.gaynor, ojeda
Cc: a.hindborg, aliceryhl, bjorn3_gh, boqun.feng, dakr, gary, lossin,
rust-for-linux, tmgross
Add the Rust equivalent of the kernel's `DO_ONCE_LITE` macro. While it
would be possible to implement the feature entirely as a Rust macro,
the functionality that can be implemented as regular functions has
been extracted and implemented as the `OnceLite` struct for better
code maintainability.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
rust/kernel/sync.rs | 1 +
rust/kernel/sync/once_lite.rs | 83 +++++++++++++++++++++++++++++++++++
2 files changed, 84 insertions(+)
create mode 100644 rust/kernel/sync/once_lite.rs
diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs
index cf5b638a097d..03789283e2ec 100644
--- a/rust/kernel/sync.rs
+++ b/rust/kernel/sync.rs
@@ -17,6 +17,7 @@
mod condvar;
pub mod lock;
mod locked_by;
+pub mod once_lite;
pub mod poll;
pub mod rcu;
mod refcount;
diff --git a/rust/kernel/sync/once_lite.rs b/rust/kernel/sync/once_lite.rs
new file mode 100644
index 000000000000..04c48d18ca39
--- /dev/null
+++ b/rust/kernel/sync/once_lite.rs
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Support for calling a function exactly once.
+//!
+//! C header: [`include/linux/once_lite.h`](srctree/include/linux/once_lite.h)
+
+use super::atomic::{
+ Atomic,
+ AtomicType,
+ Relaxed, //
+};
+
+/// A lightweight `call_once` primitive.
+///
+/// This structure provides the Rust equivalent of the kernel's `DO_ONCE_LITE` macro.
+/// While it would be possible to implement the feature entirely as a Rust macro,
+/// the functionality that can be implemented as regular functions has been
+/// extracted and implemented as the `OnceLite` struct for better code maintainability.
+pub struct OnceLite(Atomic<State>);
+
+#[derive(Clone, Copy, PartialEq, Eq)]
+#[repr(i32)]
+enum State {
+ Incomplete = 0,
+ Complete = 1,
+}
+
+// SAFETY: `State` and `i32` has the same size and alignment, and it's round-trip
+// transmutable to `i32`.
+unsafe impl AtomicType for State {
+ type Repr = i32;
+}
+
+impl OnceLite {
+ /// Creates a new [`OnceLite`] in the incomplete state.
+ #[inline(always)]
+ #[allow(clippy::new_without_default)]
+ pub const fn new() -> Self {
+ OnceLite(Atomic::new(State::Incomplete))
+ }
+
+ /// Calls the provided function exactly once.
+ ///
+ /// There is no other synchronization between two `call_once()`s
+ /// except that only one will execute `f`, in other words, callers
+ /// should not use a failed `call_once()` as a proof that another
+ /// `call_once()` has already finished and the effect is observable
+ /// to this thread.
+ pub fn call_once<F>(&self, f: F) -> bool
+ where
+ F: FnOnce(),
+ {
+ // ORDERING: `Relaxed` is used here since no synchronization is required
+ // for `call_once()`.
+ let old = self.0.xchg(State::Complete, Relaxed);
+ if old == State::Complete {
+ return false;
+ }
+
+ f();
+ true
+ }
+}
+
+/// Run the given function exactly once.
+///
+/// This is equivalent to the kernel's `DO_ONCE_LITE` macro.
+///
+/// # Examples
+///
+/// ```
+/// kernel::do_once_lite! {
+/// kernel::pr_info!("This will be printed only once\n");
+/// };
+/// ```
+#[macro_export]
+macro_rules! do_once_lite {
+ { $($e:tt)* } => {{
+ #[link_section = ".data..once"]
+ static ONCE: $crate::sync::once_lite::OnceLite = $crate::sync::once_lite::OnceLite::new();
+ ONCE.call_once(|| { $($e)* });
+ }};
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH v2 2/2] rust: Add pr_*_once macros
2025-11-12 13:16 [PATCH v2 0/2] Add support for print exactly once FUJITA Tomonori
2025-11-12 13:16 ` [PATCH v2 1/2] rust: Add support for calling a function " FUJITA Tomonori
@ 2025-11-12 13:16 ` FUJITA Tomonori
1 sibling, 0 replies; 3+ messages in thread
From: FUJITA Tomonori @ 2025-11-12 13:16 UTC (permalink / raw)
To: alex.gaynor, ojeda
Cc: a.hindborg, aliceryhl, bjorn3_gh, boqun.feng, dakr, gary, lossin,
rust-for-linux, tmgross
Add Rust version of pr_[emerg|alert|crit|err|warn|notic|info]_once
macros, which print a message only once.
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
rust/kernel/print.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs
index 2d743d78d220..d66fd8e90be2 100644
--- a/rust/kernel/print.rs
+++ b/rust/kernel/print.rs
@@ -423,3 +423,73 @@ macro_rules! pr_cont (
$crate::print_macro!($crate::print::format_strings::CONT, true, $($arg)*)
)
);
+
+/// Prints an emergency-level message (level 0) only once.
+///
+/// Equivalent to the kernel's `pr_emerg_once` macro.
+#[macro_export]
+macro_rules! pr_emerg_once (
+ ($($arg:tt)*) => (
+ $crate::do_once_lite! { $crate::pr_emerg!($($arg)*) }
+ )
+);
+
+/// Prints an alert-level message (level 1) only once.
+///
+/// Equivalent to the kernel's `pr_alert_once` macro.
+#[macro_export]
+macro_rules! pr_alert_once (
+ ($($arg:tt)*) => (
+ $crate::do_once_lite! { $crate::pr_alert!($($arg)*) }
+ )
+);
+
+/// Prints a critical-level message (level 2) only once.
+///
+/// Equivalent to the kernel's `pr_crit_once` macro.
+#[macro_export]
+macro_rules! pr_crit_once (
+ ($($arg:tt)*) => (
+ $crate::do_once_lite! { $crate::pr_crit!($($arg)*) }
+ )
+);
+
+/// Prints an error-level message (level 3) only once.
+///
+/// Equivalent to the kernel's `pr_err_once` macro.
+#[macro_export]
+macro_rules! pr_err_once (
+ ($($arg:tt)*) => (
+ $crate::do_once_lite! { $crate::pr_err!($($arg)*) }
+ )
+);
+
+/// Prints a warning-level message (level 4) only once.
+///
+/// Equivalent to the kernel's `pr_warn_once` macro.
+#[macro_export]
+macro_rules! pr_warn_once (
+ ($($arg:tt)*) => (
+ $crate::do_once_lite! { $crate::pr_warn!($($arg)*) }
+ )
+);
+
+/// Prints a notice-level message (level 5) only once.
+///
+/// Equivalent to the kernel's `pr_notice_once` macro.
+#[macro_export]
+macro_rules! pr_notice_once (
+ ($($arg:tt)*) => (
+ $crate::do_once_lite! { $crate::pr_notice!($($arg)*) }
+ )
+);
+
+/// Prints an info-level message (level 6) only once.
+///
+/// Equivalent to the kernel's `pr_info_once` macro.
+#[macro_export]
+macro_rules! pr_info_once (
+ ($($arg:tt)*) => (
+ $crate::do_once_lite! { $crate::pr_info!($($arg)*) }
+ )
+);
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-11-12 13:16 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-12 13:16 [PATCH v2 0/2] Add support for print exactly once FUJITA Tomonori
2025-11-12 13:16 ` [PATCH v2 1/2] rust: Add support for calling a function " FUJITA Tomonori
2025-11-12 13:16 ` [PATCH v2 2/2] rust: Add pr_*_once macros FUJITA Tomonori
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).