Re: [PATCH v1 0/2] Add support for print exactly once

Alice Ryhl
2025-11-13T10:07:39Z

On Wed, Nov 05, 2025 at 02:47:29PM +0900, FUJITA Tomonori wrote:
> 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.
>
> Of course, unlike the previous proposal, this uses LKMM atomics.
>
> [1] https://lore.kernel.org/rust-for-linux/20241126-pr_once_macros-v4-0-410b8ca9643e@tuta.io/

There has been a fair bit of discussion below. Here is my take on the
way forward:

1. OnceLite should be it's own special type, and it should be in a
printing-related module, not kernel::sync. The reason for this is
that do_once_lite! is hooked up to a special section that allows you
to reset the once status, and if someone used it for anything not
related to printing, they would end up with being incorrectly reset
when someone resets pr_warn_once calls.

2. I would suggest just using a relaxed load followed by store instead
of xchg. This is what the C-side does, and I think there is no strong
reason to deviate. It allows for a single byte of data instead of i32.

3. If we *do* decide to use xchg, then the xchg needs to be guarded by a
load so that we avoid a write operation when it's already cleared.
Many read ops are much cheaper than many read/write ops.

Alice