"Benno Lossin" <lossin@xxxxxxxxxx> writes: > On Fri Jun 27, 2025 at 9:57 AM CEST, Andreas Hindborg wrote: >> Andreas Hindborg <a.hindborg@xxxxxxxxxx> writes: >>> "Benno Lossin" <lossin@xxxxxxxxxx> writes: >>>> That's good to know, then let's try to go for something simple. >>>> >>>> I don't think that we can just use a `Mutex<T>`, because we don't have a >>>> way to create it at const time... I guess we could have >>>> >>>> impl<T> Mutex<T> >>>> /// # Safety >>>> /// >>>> /// The returned value needs to be pinned and then `init` needs >>>> /// to be called before any other methods are called on this. >>>> pub unsafe const fn const_new() -> Self; >>>> >>>> pub unsafe fn init(&self); >>>> } >>>> >>>> But that seems like a bad idea, because where would we call the `init` >>>> function? That also needs to be synchronized... >>> >>> Ah, that is unfortunate. The init function will not run before this, so >>> we would need a `Once` or an atomic anyway to initialize the lock. >>> >>> I am not sure if we are allowed to sleep during this, I would have to >>> check. But then we could use a spin lock. >>> >>> We will need the locking anyway, when we want to enable sysfs write >>> access to the parameters. >>> >>>> >>>> Maybe we can just like you said use an atomic bool? >>> >>> Sigh, I will have to check how far that series has come. >>> >> >> I think I am going to build some kind of `Once` feature on top of >> Boqun's atomic series [1], so that we can initialize a lock in these >> statics. We can't use `global_lock!`, because that depends on module >> init to initialize the lock before first use. > > Sounds good, though we probably don't want to name it `Once`. Since it > is something that will be populated in the future, but not by some > random accessor, but rather a specific populator. > > So maybe: > > pub struct Delayed<T> { > dummy: T, > real: Opaque<T>, > populated: Atomic<bool>, // or Atomic<Flag> > writing: Atomic<bool>, // or Atomic<Flag> > } > > impl<T> Delayed<T> { > pub fn new(dummy: T) -> Self { > Self { > dummy, > real: Opaque::uninit(), > populated: Atomic::new(false), > writing: Atomic::new(false), > } > } > > pub fn get(&self) -> &T { > if self.populated.load(Acquire) { > unsafe { &*self.real.get() } > } else { > // maybe print a warning here? > // or maybe let the user configure this in `new()`? > &self.dummy > } > } > > pub fn populate(&self, value: T) { > if self.writing.cmpxchg(false, true, Release) { > unsafe { *self.real.get() = value }; > self.populated.store(true, Release); > } else { > pr_warn!("`Delayed<{}>` written to twice!\n", core::any::type_name::<T>()); > } > } > } > > (no idea if the orderings are correct, I always have to think way to > much about that... especially since our atomics seem to only take one > ordering in compare_exchange?) > >> As far as I can tell, atomics may not land in v6.17, so this series >> will probably not be ready for merge until v6.18 at the earliest. > > Yeah, sorry about that :( Actually, perhaps we could aim at merging this code without this synchronization? The lack of synchronization is only a problem if we support custom parsing. This patch set does not allow custom parsing code, so it does not suffer this issue. Best regards, Andreas Hindborg