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

Boqun Feng
2025-11-11T05:17:12Z

On Tue, Nov 11, 2025 at 12:09:49PM +0900, FUJITA Tomonori wrote:
> 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.
>

What an unintended way you mean? Do you have an example?

>
> >> 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.
>

Rust std has its own Once[1] module, so I think the concept of "doing
something once" is going to be more general in Rust code.

Moreover, I don't see any downside, right now you are putting it in a
random place, and as we discussed, there is no synchronization problem
on the implementation, so putting it in kernel::sync is not worse than a
random place?

> 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()?
>

To follow the exact behavior in your patchset, but either way it's fine.

> 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

Yes, I think `SetOnce<T>` should be `Sync` if T is `Sync`. So good
finding! I would say it's actually the effort of trying to reuse the
existing solution makes that we find places that needs to be improved.

@Andreas, thoughts?

> 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.
>

We should always try to find a unified solution, if there is not much
trouble. Otherwise, we will end up having MyOnce, YourOnce, HisOnce,
HerOnce, TheirOnce etc in our code base.

[1]: https://doc.rust-lang.org/std/sync/struct.Once.html

Regards,
Boqun