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 :( > Thanks for the input, Benno! My pleasure! --- Cheers, Benno