Re: [PATCH v1 1/2] rust: Add support for calling a function exactly once

FUJITA Tomonori
2025-11-11T03:10:01Z

On Mon, 10 Nov 2025 08:14:56 -0800
Boqun Feng <boqun.feng@gmail.com> wrote:

> On Mon, Nov 10, 2025 at 06:21:50PM +0900, FUJITA Tomonori wrote:
>> On Fri, 7 Nov 2025 09:03:01 +0000
>> Alice Ryhl <aliceryhl@google.com> wrote:
>>
>> >> That's my point (and probably also Andreas' point), we already has the
>> >> type `SetOnce` to do this, no need for a `OnceLite` type if not
>> >> necessary, and the fact that it can be zero'd by debugfs doesn't change
>> >> it as I explained above.
>> >
>> > The SetOnce type doesn't do the same thing as OnceLite. SetOnce has
>> > three different states, but OnceLite only needs two. I don't think we
>> > should be reusing SetOnce here.
>
> I mean 3 states should cover 2 states, right? In this case we only need
> to support SetOnce<()>, so I think it's fine, see below:

Yeah, that would remove access to the value member, but I think that
init member could still be accessed in an unintended way.

>> Yes, SetOnce provides three different states and the feature to set a
>> value, which are not necessary for this case.
>>
>> So there are two design options: 1) to add a new minimal
>> implementation that provides only the features required for this case,
>
> Just to be clear 1) will still need to be in kernel::sync module, as per
> our previous discussion.

As I wrote before, I think that once_lite.rs could be put in
kernel::sync but I'm not sure it's a good idea because I'm not sure if
there are any other users who actually need this feature.

Any thoughts from others?

>> or 2) to use the exisiting, more complex implementation with richer
>> functionality.
>>
>
> or we can just add it into `SetOnce<()>`, for exammple:
>
> impl SetOnce<()> {
> pub fn call_once<F: FnOnce()>(&self, f: F) -> bool {
> // ORDERING: Relaxed is fine because we don't expect
> // synchronization here.
> let old = self.init.xchg(1, Relaxed);
>
> // We are the first one here.
> if old == 0 {
> f();
> return true;
> }
>
> return false;
> }
> }
>
> Thoughts?

Why not using populate() method instead of accesing the init member
directly by xchg()?

Anyway, I tried and got a following compile error:

error[E0277]: `core::cell::UnsafeCell<core::mem::MaybeUninit<()>>` cannot be shared between threads safely
--> /home/fujita/git/linux-rust/samples/rust/rust_configfs.rs:109:9
|
109 | kernel::pr_info_once!("print once\n");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `core::cell::UnsafeCell<core::mem::MaybeUninit<()>>` cannot be shared between threads safely

We need Sync for SetOnce? I haven't been following the SetOnce
discussion, but I wonder if there are use cases that require Sync. If
all access goes through its methods, it seems safe to add Sync.

I personally prefer the OnceLite implementation of not using SetOnce,
however since it's not directly used by users and can be easily
changed later, so I'm fine with any implementation as long as we can
reach an agreement soon.