* [PATCH v2] rust: add global lock support
@ 2024-08-27 8:41 Alice Ryhl
2024-08-29 18:16 ` Benno Lossin
0 siblings, 1 reply; 14+ messages in thread
From: Alice Ryhl @ 2024-08-27 8:41 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Alex Gaynor, Wedson Almeida Filho, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
rust-for-linux, linux-kernel, Alice Ryhl
We don't currently have any support for global locks in Rust, however
they are very useful and I have needed to work around this limitation
several times. My workarounds generally involve initializing the mutex
in the module's init function, and this workaround is reflected here.
Due to the initialization requirement, constructing a global mutex is
unsafe with the current approach. In the future, it would be really nice
to support global mutexes that don't need to be initialized, which would
make them safe. Unfortunately, this is not possible today because
bindgen refuses to expose __ARCH_SPIN_LOCK_UNLOCKED to Rust as a
compile-time constant. It just generates an `extern "C"` global
reference instead.
On most architectures, we could initialize the lock to just contain all
zeros. A possible improvement would be to create a Kconfig constant
that is set whenever the current architecture uses all zeros for the
initializer and have `unsafe_const_init` be a no-op on those
architectures. We could also provide a safe const initializer that is
only available when that Kconfig option is set.
For architectures that don't use all-zeros for the unlocked case, we
will most likely have to hard-code the correct representation on the
Rust side.
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
Changes in v2:
- Require `self: Pin<&Self>` and recommend `Pin::static_ref`.
- Other doc improvements including new example.
- Link to v1: https://lore.kernel.org/r/20240826-static-mutex-v1-1-a14ee71561f3@google.com
---
rust/kernel/sync/lock.rs | 64 +++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 63 insertions(+), 1 deletion(-)
diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs
index f6c34ca4d819..cfc5e160d78c 100644
--- a/rust/kernel/sync/lock.rs
+++ b/rust/kernel/sync/lock.rs
@@ -7,7 +7,7 @@
use super::LockClassKey;
use crate::{init::PinInit, pin_init, str::CStr, types::Opaque, types::ScopeGuard};
-use core::{cell::UnsafeCell, marker::PhantomData, marker::PhantomPinned};
+use core::{cell::UnsafeCell, marker::PhantomData, marker::PhantomPinned, pin::Pin};
use macros::pin_data;
pub mod mutex;
@@ -117,6 +117,68 @@ pub fn new(t: T, name: &'static CStr, key: &'static LockClassKey) -> impl PinIni
}),
})
}
+
+ /// Create a global lock that has not yet been initialized.
+ ///
+ /// Since global locks is not yet fully supported, this method implements global locks by
+ /// requiring you to initialize them before you start using it. Usually this is best done in
+ /// the module's init function.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use kernel::sync::Mutex;
+ ///
+ /// // SAFETY: We initialize the mutex before first use.
+ /// static MY_MUTEX: Mutex<()> = unsafe { Mutex::unsafe_const_new(()) };
+ ///
+ /// // For the sake of this example, assume that this is the module initializer.
+ /// fn module_init() {
+ /// // SAFETY:
+ /// // * `MY_MUTEX` was created using `unsafe_const_new`.
+ /// // * This call is in the module initializer, which doesn't runs more than once.
+ /// unsafe {
+ /// core::pin::Pin::static_ref(&MY_MUTEX)
+ /// .unsafe_const_init(kernel::c_str!("MY_MUTEX"), kernel::static_lock_class!())
+ /// };
+ /// }
+ /// ```
+ ///
+ /// # Safety
+ ///
+ /// You must call [`unsafe_const_init`] before calling any other method on this lock.
+ ///
+ /// [`unsafe_const_init`]: Self::unsafe_const_init
+ pub const unsafe fn unsafe_const_new(t: T) -> Self {
+ Self {
+ data: UnsafeCell::new(t),
+ state: Opaque::uninit(),
+ _pin: PhantomPinned,
+ }
+ }
+
+ /// Initialize a global lock.
+ ///
+ /// When using this to initialize a `static` lock, you can use [`Pin::static_ref`] to construct
+ /// the pinned reference.
+ ///
+ /// See the docs for [`unsafe_const_new`] for examples.
+ ///
+ /// # Safety
+ ///
+ /// * This lock must have been created with [`unsafe_const_new`].
+ /// * This method must not be called more than once on a given lock.
+ ///
+ /// [`unsafe_const_new`]: Self::unsafe_const_new
+ pub unsafe fn unsafe_const_init(
+ self: Pin<&Self>,
+ name: &'static CStr,
+ key: &'static LockClassKey,
+ ) {
+ // SAFETY: The pointer to `state` is valid for the duration of this call, and both `name`
+ // and `key` are valid indefinitely.
+ unsafe { B::init(self.state.get(), name.as_char_ptr(), key.as_ptr()) }
+ }
}
impl<T: ?Sized, B: Backend> Lock<T, B> {
---
base-commit: b204bbc53f958fc3119d63bf2cda5a526e7267a4
change-id: 20240826-static-mutex-a4b228e0e6aa
Best regards,
--
Alice Ryhl <aliceryhl@google.com>
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v2] rust: add global lock support
2024-08-27 8:41 [PATCH v2] rust: add global lock support Alice Ryhl
@ 2024-08-29 18:16 ` Benno Lossin
2024-08-30 5:34 ` Alice Ryhl
0 siblings, 1 reply; 14+ messages in thread
From: Benno Lossin @ 2024-08-29 18:16 UTC (permalink / raw)
To: Alice Ryhl, Miguel Ojeda
Cc: Alex Gaynor, Wedson Almeida Filho, Boqun Feng, Gary Guo,
Björn Roy Baron, Andreas Hindborg, rust-for-linux,
linux-kernel
On 27.08.24 10:41, Alice Ryhl wrote:
> We don't currently have any support for global locks in Rust, however
> they are very useful and I have needed to work around this limitation
> several times. My workarounds generally involve initializing the mutex
> in the module's init function, and this workaround is reflected here.
I would not exactly call this a "workaround". If your use-case is
covered by putting a `Mutex`, then I would prefer it. Or did you need
additional ugly code to access it?
> Due to the initialization requirement, constructing a global mutex is
> unsafe with the current approach. In the future, it would be really nice
> to support global mutexes that don't need to be initialized, which would
> make them safe. Unfortunately, this is not possible today because
> bindgen refuses to expose __ARCH_SPIN_LOCK_UNLOCKED to Rust as a
> compile-time constant. It just generates an `extern "C"` global
> reference instead.
Ideally, we would have support for static initialization in pinned-init.
> On most architectures, we could initialize the lock to just contain all
> zeros. A possible improvement would be to create a Kconfig constant
> that is set whenever the current architecture uses all zeros for the
> initializer and have `unsafe_const_init` be a no-op on those
> architectures. We could also provide a safe const initializer that is
> only available when that Kconfig option is set.
I am not sure if the two branches (depending on the config) will be a
good idea. We don't save on `unsafe` and only increase code complexity.
The no-op sounds like a better idea to me.
> For architectures that don't use all-zeros for the unlocked case, we
> will most likely have to hard-code the correct representation on the
> Rust side.
You mean in `unsafe_const_init`?
> Signed-off-by: Alice Ryhl <aliceryhl@google.com>
> ---
> Changes in v2:
> - Require `self: Pin<&Self>` and recommend `Pin::static_ref`.
> - Other doc improvements including new example.
> - Link to v1: https://lore.kernel.org/r/20240826-static-mutex-v1-1-a14ee71561f3@google.com
> ---
> rust/kernel/sync/lock.rs | 64 +++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 63 insertions(+), 1 deletion(-)
>
> diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs
> index f6c34ca4d819..cfc5e160d78c 100644
> --- a/rust/kernel/sync/lock.rs
> +++ b/rust/kernel/sync/lock.rs
> @@ -7,7 +7,7 @@
>
> use super::LockClassKey;
> use crate::{init::PinInit, pin_init, str::CStr, types::Opaque, types::ScopeGuard};
> -use core::{cell::UnsafeCell, marker::PhantomData, marker::PhantomPinned};
> +use core::{cell::UnsafeCell, marker::PhantomData, marker::PhantomPinned, pin::Pin};
> use macros::pin_data;
>
> pub mod mutex;
> @@ -117,6 +117,68 @@ pub fn new(t: T, name: &'static CStr, key: &'static LockClassKey) -> impl PinIni
> }),
> })
> }
> +
> + /// Create a global lock that has not yet been initialized.
> + ///
Could you add a paragraph that explains that
> + /// Since global locks is not yet fully supported, this method implements global locks by
> + /// requiring you to initialize them before you start using it. Usually this is best done in
> + /// the module's init function.
> + ///
> + /// # Examples
> + ///
I would preface this example with "Instead of [`Mutex<T>`], you can use
any other lock.".
> + /// ```
> + /// use kernel::sync::Mutex;
> + ///
> + /// // SAFETY: We initialize the mutex before first use.
> + /// static MY_MUTEX: Mutex<()> = unsafe { Mutex::unsafe_const_new(()) };
> + ///
> + /// // For the sake of this example, assume that this is the module initializer.
Why not actually provide a module initializer?
> + /// fn module_init() {
> + /// // SAFETY:
> + /// // * `MY_MUTEX` was created using `unsafe_const_new`.
> + /// // * This call is in the module initializer, which doesn't runs more than once.
> + /// unsafe {
> + /// core::pin::Pin::static_ref(&MY_MUTEX)
I would put this into a let binding, that way the formatting will also
be nicer.
> + /// .unsafe_const_init(kernel::c_str!("MY_MUTEX"), kernel::static_lock_class!())
> + /// };
> + /// }
> + /// ```
> + ///
> + /// # Safety
> + ///
> + /// You must call [`unsafe_const_init`] before calling any other method on this lock.
> + ///
> + /// [`unsafe_const_init`]: Self::unsafe_const_init
> + pub const unsafe fn unsafe_const_new(t: T) -> Self {
I am not sure on this name, I don't think we have any functions with
`unsafe` in it (and `std` also doesn't). How about `new_uninitialized`?
Although that might be confusing, since it does actually take a value...
> + Self {
> + data: UnsafeCell::new(t),
> + state: Opaque::uninit(),
> + _pin: PhantomPinned,
> + }
> + }
> +
> + /// Initialize a global lock.
> + ///
> + /// When using this to initialize a `static` lock, you can use [`Pin::static_ref`] to construct
> + /// the pinned reference.
> + ///
> + /// See the docs for [`unsafe_const_new`] for examples.
> + ///
> + /// # Safety
> + ///
> + /// * This lock must have been created with [`unsafe_const_new`].
> + /// * This method must not be called more than once on a given lock.
> + ///
> + /// [`unsafe_const_new`]: Self::unsafe_const_new
> + pub unsafe fn unsafe_const_init(
I know you are using `const` here to have symmetry with the function
above, but I think it's a bit misleading, you can't call this from const
context. Going with the theme of the suggestion from above, what about
`manual_init`?
---
Cheers,
Benno
> + self: Pin<&Self>,
> + name: &'static CStr,
> + key: &'static LockClassKey,
> + ) {
> + // SAFETY: The pointer to `state` is valid for the duration of this call, and both `name`
> + // and `key` are valid indefinitely.
> + unsafe { B::init(self.state.get(), name.as_char_ptr(), key.as_ptr()) }
> + }
> }
>
> impl<T: ?Sized, B: Backend> Lock<T, B> {
>
> ---
> base-commit: b204bbc53f958fc3119d63bf2cda5a526e7267a4
> change-id: 20240826-static-mutex-a4b228e0e6aa
>
> Best regards,
> --
> Alice Ryhl <aliceryhl@google.com>
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2] rust: add global lock support
2024-08-29 18:16 ` Benno Lossin
@ 2024-08-30 5:34 ` Alice Ryhl
2024-08-30 13:21 ` Benno Lossin
2024-08-30 15:09 ` Gary Guo
0 siblings, 2 replies; 14+ messages in thread
From: Alice Ryhl @ 2024-08-30 5:34 UTC (permalink / raw)
To: Benno Lossin
Cc: Miguel Ojeda, Alex Gaynor, Wedson Almeida Filho, Boqun Feng,
Gary Guo, Björn Roy Baron, Andreas Hindborg, rust-for-linux,
linux-kernel
On Thu, Aug 29, 2024 at 8:17 PM Benno Lossin <benno.lossin@proton.me> wrote:
>
> On 27.08.24 10:41, Alice Ryhl wrote:
> > We don't currently have any support for global locks in Rust, however
> > they are very useful and I have needed to work around this limitation
> > several times. My workarounds generally involve initializing the mutex
> > in the module's init function, and this workaround is reflected here.
>
> I would not exactly call this a "workaround". If your use-case is
> covered by putting a `Mutex`, then I would prefer it. Or did you need
> additional ugly code to access it?
Not sure what you mean by "putting a Mutex" but the workaround is
really gross and involves defining a whole struct to make types Sync
and so on. Unlike binder, this patch has access to private fields of
Lock, so it can do it in a more nice way. You can find it in the
Binder RFC if you search for "context_global".
https://lore.kernel.org/rust-for-linux/20231101-rust-binder-v1-2-08ba9197f637@google.com/#Z31drivers:android:context.rs
> > Due to the initialization requirement, constructing a global mutex is
> > unsafe with the current approach. In the future, it would be really nice
> > to support global mutexes that don't need to be initialized, which would
> > make them safe. Unfortunately, this is not possible today because
> > bindgen refuses to expose __ARCH_SPIN_LOCK_UNLOCKED to Rust as a
> > compile-time constant. It just generates an `extern "C"` global
> > reference instead.
>
> Ideally, we would have support for static initialization in pinned-init.
I don't think traits work with const today, so pin-init would need an
entirely different mechanism? If you're talking about using
CONSTRUCTORS, then I think it's an undesirable solution. C code can
define static mutexes without load-time initialization hooks. We
should be able to do the same.
> > On most architectures, we could initialize the lock to just contain all
> > zeros. A possible improvement would be to create a Kconfig constant
> > that is set whenever the current architecture uses all zeros for the
> > initializer and have `unsafe_const_init` be a no-op on those
> > architectures. We could also provide a safe const initializer that is
> > only available when that Kconfig option is set.
>
> I am not sure if the two branches (depending on the config) will be a
> good idea. We don't save on `unsafe` and only increase code complexity.
> The no-op sounds like a better idea to me.
You mean put the logic here instead in the downstream user? I agree.
> > For architectures that don't use all-zeros for the unlocked case, we
> > will most likely have to hard-code the correct representation on the
> > Rust side.
>
> You mean in `unsafe_const_init`?
No, I mean we would have `unsafe_const_new` directly set `state` to
the right value and let `unsafe_const_init` be a no-op.
> > Signed-off-by: Alice Ryhl <aliceryhl@google.com>
> > ---
> > Changes in v2:
> > - Require `self: Pin<&Self>` and recommend `Pin::static_ref`.
> > - Other doc improvements including new example.
> > - Link to v1: https://lore.kernel.org/r/20240826-static-mutex-v1-1-a14ee71561f3@google.com
> > ---
> > rust/kernel/sync/lock.rs | 64 +++++++++++++++++++++++++++++++++++++++++++++++-
> > 1 file changed, 63 insertions(+), 1 deletion(-)
> >
> > diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs
> > index f6c34ca4d819..cfc5e160d78c 100644
> > --- a/rust/kernel/sync/lock.rs
> > +++ b/rust/kernel/sync/lock.rs
> > @@ -7,7 +7,7 @@
> >
> > use super::LockClassKey;
> > use crate::{init::PinInit, pin_init, str::CStr, types::Opaque, types::ScopeGuard};
> > -use core::{cell::UnsafeCell, marker::PhantomData, marker::PhantomPinned};
> > +use core::{cell::UnsafeCell, marker::PhantomData, marker::PhantomPinned, pin::Pin};
> > use macros::pin_data;
> >
> > pub mod mutex;
> > @@ -117,6 +117,68 @@ pub fn new(t: T, name: &'static CStr, key: &'static LockClassKey) -> impl PinIni
> > }),
> > })
> > }
> > +
> > + /// Create a global lock that has not yet been initialized.
> > + ///
>
> Could you add a paragraph that explains that
Explains that what?
> > + /// Since global locks is not yet fully supported, this method implements global locks by
> > + /// requiring you to initialize them before you start using it. Usually this is best done in
> > + /// the module's init function.
> > + ///
> > + /// # Examples
> > + ///
>
> I would preface this example with "Instead of [`Mutex<T>`], you can use
> any other lock.".
I don't love that wording. How about something along these lines?
"This example uses a Mutex, but this works with any other lock
including spin locks."
> > + /// ```
> > + /// use kernel::sync::Mutex;
> > + ///
> > + /// // SAFETY: We initialize the mutex before first use.
> > + /// static MY_MUTEX: Mutex<()> = unsafe { Mutex::unsafe_const_new(()) };
> > + ///
> > + /// // For the sake of this example, assume that this is the module initializer.
>
> Why not actually provide a module initializer?
Can I put a `module!` macro inside a kunit test? I assumed that I couldn't.
> > + /// fn module_init() {
> > + /// // SAFETY:
> > + /// // * `MY_MUTEX` was created using `unsafe_const_new`.
> > + /// // * This call is in the module initializer, which doesn't runs more than once.
> > + /// unsafe {
> > + /// core::pin::Pin::static_ref(&MY_MUTEX)
>
> I would put this into a let binding, that way the formatting will also
> be nicer.
Ok.
> > + /// .unsafe_const_init(kernel::c_str!("MY_MUTEX"), kernel::static_lock_class!())
> > + /// };
> > + /// }
> > + /// ```
> > + ///
> > + /// # Safety
> > + ///
> > + /// You must call [`unsafe_const_init`] before calling any other method on this lock.
> > + ///
> > + /// [`unsafe_const_init`]: Self::unsafe_const_init
> > + pub const unsafe fn unsafe_const_new(t: T) -> Self {
>
> I am not sure on this name, I don't think we have any functions with
> `unsafe` in it (and `std` also doesn't). How about `new_uninitialized`?
>
> Although that might be confusing, since it does actually take a value...
Hmm. Any other ideas? const_new_need_manual_init?
> > + Self {
> > + data: UnsafeCell::new(t),
> > + state: Opaque::uninit(),
> > + _pin: PhantomPinned,
> > + }
> > + }
> > +
> > + /// Initialize a global lock.
> > + ///
> > + /// When using this to initialize a `static` lock, you can use [`Pin::static_ref`] to construct
> > + /// the pinned reference.
> > + ///
> > + /// See the docs for [`unsafe_const_new`] for examples.
> > + ///
> > + /// # Safety
> > + ///
> > + /// * This lock must have been created with [`unsafe_const_new`].
> > + /// * This method must not be called more than once on a given lock.
> > + ///
> > + /// [`unsafe_const_new`]: Self::unsafe_const_new
> > + pub unsafe fn unsafe_const_init(
>
> I know you are using `const` here to have symmetry with the function
> above, but I think it's a bit misleading, you can't call this from const
> context. Going with the theme of the suggestion from above, what about
> `manual_init`?
That could work.
Alice
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2] rust: add global lock support
2024-08-30 5:34 ` Alice Ryhl
@ 2024-08-30 13:21 ` Benno Lossin
2024-09-02 11:37 ` Alice Ryhl
2024-08-30 15:09 ` Gary Guo
1 sibling, 1 reply; 14+ messages in thread
From: Benno Lossin @ 2024-08-30 13:21 UTC (permalink / raw)
To: Alice Ryhl
Cc: Miguel Ojeda, Alex Gaynor, Wedson Almeida Filho, Boqun Feng,
Gary Guo, Björn Roy Baron, Andreas Hindborg, rust-for-linux,
linux-kernel
On 30.08.24 07:34, Alice Ryhl wrote:
> On Thu, Aug 29, 2024 at 8:17 PM Benno Lossin <benno.lossin@proton.me> wrote:
>>
>> On 27.08.24 10:41, Alice Ryhl wrote:
>>> We don't currently have any support for global locks in Rust, however
>>> they are very useful and I have needed to work around this limitation
>>> several times. My workarounds generally involve initializing the mutex
>>> in the module's init function, and this workaround is reflected here.
>>
>> I would not exactly call this a "workaround". If your use-case is
>> covered by putting a `Mutex`, then I would prefer it. Or did you need
>> additional ugly code to access it?
>
> Not sure what you mean by "putting a Mutex" but the workaround is
Oh sorry, seems like I forgot to write the rest of that... Let me try
again: If your use-case is covered by putting a `Mutex` inside of the
type that implements `Module`, then I think you should do that instead
of using a global. (you need the inplace module patch for that)
> really gross and involves defining a whole struct to make types Sync
> and so on. Unlike binder, this patch has access to private fields of
> Lock, so it can do it in a more nice way. You can find it in the
> Binder RFC if you search for "context_global".
> https://lore.kernel.org/rust-for-linux/20231101-rust-binder-v1-2-08ba9197f637@google.com/#Z31drivers:android:context.rs
Oh I remember this... Yeah I agree that is ugly, but it is not the
workaround that I imagined when you wrote "initializing the mutex in the
module's init function". There I was thinking of what I wrote above.
This might just be me misunderstanding that, but if you want to improve
it, then you could mention that the mutex is still a static.
>>> Due to the initialization requirement, constructing a global mutex is
>>> unsafe with the current approach. In the future, it would be really nice
>>> to support global mutexes that don't need to be initialized, which would
>>> make them safe. Unfortunately, this is not possible today because
>>> bindgen refuses to expose __ARCH_SPIN_LOCK_UNLOCKED to Rust as a
>>> compile-time constant. It just generates an `extern "C"` global
>>> reference instead.
>>
>> Ideally, we would have support for static initialization in pinned-init.
>
> I don't think traits work with const today, so pin-init would need an
> entirely different mechanism? If you're talking about using
Oh yeah I forgot that that got scratched some time ago.
> CONSTRUCTORS, then I think it's an undesirable solution. C code can
No, I was thinking that the initializer is run at const eval and then
the result is put into the binary.
> define static mutexes without load-time initialization hooks. We
> should be able to do the same.
Agreed.
>>> On most architectures, we could initialize the lock to just contain all
>>> zeros. A possible improvement would be to create a Kconfig constant
>>> that is set whenever the current architecture uses all zeros for the
>>> initializer and have `unsafe_const_init` be a no-op on those
>>> architectures. We could also provide a safe const initializer that is
>>> only available when that Kconfig option is set.
>>
>> I am not sure if the two branches (depending on the config) will be a
>> good idea. We don't save on `unsafe` and only increase code complexity.
>> The no-op sounds like a better idea to me.
>
> You mean put the logic here instead in the downstream user? I agree.
I meant that
#[cfg(ZERO_LOCK_INIT)]
static MY_MUTEX: Mutex<()> = Mutex::new_zeroed();
#[cfg(not(ZERO_LOCK_INIT))]
// SAFETY: ...
static MY_MUTEX: Mutex<()> = unsafe { Mutex::unsafe_const_new() };
module_init() {
#[cfg(not(ZERO_LOCK_INIT))]
{
// SAFETY: ...
unsafe { MY_MUTEX.unsafe_const_init() };
}
}
is significantly worse compared to just
// SAFETY: ...
static MY_MUTEX: Mutex<()> = unsafe { Mutex::unsafe_const_new() };
module_init() {
// SAFETY: ...
unsafe { MY_MUTEX.unsafe_const_init() };
// ^^^^^^^^^^^^^^^^^
// if ZERO_LOCK_INIT, then this is a no-op.
}
>>> For architectures that don't use all-zeros for the unlocked case, we
>>> will most likely have to hard-code the correct representation on the
>>> Rust side.
>>
>> You mean in `unsafe_const_init`?
>
> No, I mean we would have `unsafe_const_new` directly set `state` to
> the right value and let `unsafe_const_init` be a no-op.
But how do you set the right value of a list_head? The value will be
moved.
>>> Signed-off-by: Alice Ryhl <aliceryhl@google.com>
>>> ---
>>> Changes in v2:
>>> - Require `self: Pin<&Self>` and recommend `Pin::static_ref`.
>>> - Other doc improvements including new example.
>>> - Link to v1: https://lore.kernel.org/r/20240826-static-mutex-v1-1-a14ee71561f3@google.com
>>> ---
>>> rust/kernel/sync/lock.rs | 64 +++++++++++++++++++++++++++++++++++++++++++++++-
>>> 1 file changed, 63 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs
>>> index f6c34ca4d819..cfc5e160d78c 100644
>>> --- a/rust/kernel/sync/lock.rs
>>> +++ b/rust/kernel/sync/lock.rs
>>> @@ -7,7 +7,7 @@
>>>
>>> use super::LockClassKey;
>>> use crate::{init::PinInit, pin_init, str::CStr, types::Opaque, types::ScopeGuard};
>>> -use core::{cell::UnsafeCell, marker::PhantomData, marker::PhantomPinned};
>>> +use core::{cell::UnsafeCell, marker::PhantomData, marker::PhantomPinned, pin::Pin};
>>> use macros::pin_data;
>>>
>>> pub mod mutex;
>>> @@ -117,6 +117,68 @@ pub fn new(t: T, name: &'static CStr, key: &'static LockClassKey) -> impl PinIni
>>> }),
>>> })
>>> }
>>> +
>>> + /// Create a global lock that has not yet been initialized.
>>> + ///
>>
>> Could you add a paragraph that explains that
>
> Explains that what?
... this is not the usual way to create a `Lock`, use this only when
creating a global, `static` lock. For all other purposes, use
`new_<lock-type>`.
>>> + /// Since global locks is not yet fully supported, this method implements global locks by
>>> + /// requiring you to initialize them before you start using it. Usually this is best done in
>>> + /// the module's init function.
>>> + ///
>>> + /// # Examples
>>> + ///
>>
>> I would preface this example with "Instead of [`Mutex<T>`], you can use
>> any other lock.".
>
> I don't love that wording. How about something along these lines?
> "This example uses a Mutex, but this works with any other lock
> including spin locks."
Sure.
>>> + /// ```
>>> + /// use kernel::sync::Mutex;
>>> + ///
>>> + /// // SAFETY: We initialize the mutex before first use.
>>> + /// static MY_MUTEX: Mutex<()> = unsafe { Mutex::unsafe_const_new(()) };
>>> + ///
>>> + /// // For the sake of this example, assume that this is the module initializer.
>>
>> Why not actually provide a module initializer?
>
> Can I put a `module!` macro inside a kunit test? I assumed that I couldn't.
I think if you wrap it in another `mod`, then it should work, but I
might be wrong.
>>> + /// fn module_init() {
>>> + /// // SAFETY:
>>> + /// // * `MY_MUTEX` was created using `unsafe_const_new`.
>>> + /// // * This call is in the module initializer, which doesn't runs more than once.
>>> + /// unsafe {
>>> + /// core::pin::Pin::static_ref(&MY_MUTEX)
>>
>> I would put this into a let binding, that way the formatting will also
>> be nicer.
>
> Ok.
>
>>> + /// .unsafe_const_init(kernel::c_str!("MY_MUTEX"), kernel::static_lock_class!())
>>> + /// };
>>> + /// }
>>> + /// ```
>>> + ///
>>> + /// # Safety
>>> + ///
>>> + /// You must call [`unsafe_const_init`] before calling any other method on this lock.
>>> + ///
>>> + /// [`unsafe_const_init`]: Self::unsafe_const_init
>>> + pub const unsafe fn unsafe_const_new(t: T) -> Self {
>>
>> I am not sure on this name, I don't think we have any functions with
>> `unsafe` in it (and `std` also doesn't). How about `new_uninitialized`?
>>
>> Although that might be confusing, since it does actually take a value...
>
> Hmm. Any other ideas? const_new_need_manual_init?
Hmm that seems too long... `new_static_uninit`? I don't think that
`const` belongs in the name either, since you wouldn't use it in a
`const` (but sure it is used in const contexts, but I find putting it in
the name confusing).
---
Cheers,
Benno
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2] rust: add global lock support
2024-08-30 5:34 ` Alice Ryhl
2024-08-30 13:21 ` Benno Lossin
@ 2024-08-30 15:09 ` Gary Guo
2024-09-02 10:46 ` Alice Ryhl
1 sibling, 1 reply; 14+ messages in thread
From: Gary Guo @ 2024-08-30 15:09 UTC (permalink / raw)
To: Alice Ryhl
Cc: Benno Lossin, Miguel Ojeda, Alex Gaynor, Wedson Almeida Filho,
Boqun Feng, Björn Roy Baron, Andreas Hindborg,
rust-for-linux, linux-kernel
On Fri, 30 Aug 2024 07:34:00 +0200
Alice Ryhl <aliceryhl@google.com> wrote:
> > > Due to the initialization requirement, constructing a global mutex is
> > > unsafe with the current approach. In the future, it would be really nice
> > > to support global mutexes that don't need to be initialized, which would
> > > make them safe. Unfortunately, this is not possible today because
> > > bindgen refuses to expose __ARCH_SPIN_LOCK_UNLOCKED to Rust as a
> > > compile-time constant. It just generates an `extern "C"` global
> > > reference instead.
> >
> > Ideally, we would have support for static initialization in pinned-init.
>
> I don't think traits work with const today, so pin-init would need an
> entirely different mechanism? If you're talking about using
> CONSTRUCTORS, then I think it's an undesirable solution. C code can
> define static mutexes without load-time initialization hooks. We
> should be able to do the same.
I think I actually prefer using constructors to unsafe.
Best,
Gary
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2] rust: add global lock support
2024-08-30 15:09 ` Gary Guo
@ 2024-09-02 10:46 ` Alice Ryhl
0 siblings, 0 replies; 14+ messages in thread
From: Alice Ryhl @ 2024-09-02 10:46 UTC (permalink / raw)
To: Gary Guo
Cc: Benno Lossin, Miguel Ojeda, Alex Gaynor, Wedson Almeida Filho,
Boqun Feng, Björn Roy Baron, Andreas Hindborg,
rust-for-linux, linux-kernel
On Fri, Aug 30, 2024 at 5:10 PM Gary Guo <gary@garyguo.net> wrote:
>
> On Fri, 30 Aug 2024 07:34:00 +0200
> Alice Ryhl <aliceryhl@google.com> wrote:
>
> > > > Due to the initialization requirement, constructing a global mutex is
> > > > unsafe with the current approach. In the future, it would be really nice
> > > > to support global mutexes that don't need to be initialized, which would
> > > > make them safe. Unfortunately, this is not possible today because
> > > > bindgen refuses to expose __ARCH_SPIN_LOCK_UNLOCKED to Rust as a
> > > > compile-time constant. It just generates an `extern "C"` global
> > > > reference instead.
> > >
> > > Ideally, we would have support for static initialization in pinned-init.
> >
> > I don't think traits work with const today, so pin-init would need an
> > entirely different mechanism? If you're talking about using
> > CONSTRUCTORS, then I think it's an undesirable solution. C code can
> > define static mutexes without load-time initialization hooks. We
> > should be able to do the same.
>
> I think I actually prefer using constructors to unsafe.
Constructors are used pretty rarely. They're not enabled in the
Android build right now at all. I could ask to enable the option, but
I think "global mutexes" are a rather weak reason.
I also think they're a can of worms safety-wise. You can't run
arbitrary code in them since otherwise one constructor could use
another global before it gets initialized, so we will still need
global-mutex/spinlock-specific functionality even with constructors.
At that point, I think it would be better to just strive for real
const mutexes.
Alice
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2] rust: add global lock support
2024-08-30 13:21 ` Benno Lossin
@ 2024-09-02 11:37 ` Alice Ryhl
2024-09-02 11:42 ` Alice Ryhl
2024-09-02 21:37 ` Benno Lossin
0 siblings, 2 replies; 14+ messages in thread
From: Alice Ryhl @ 2024-09-02 11:37 UTC (permalink / raw)
To: Benno Lossin
Cc: Miguel Ojeda, Alex Gaynor, Wedson Almeida Filho, Boqun Feng,
Gary Guo, Björn Roy Baron, Andreas Hindborg, rust-for-linux,
linux-kernel
On Fri, Aug 30, 2024 at 3:22 PM Benno Lossin <benno.lossin@proton.me> wrote:
>
> On 30.08.24 07:34, Alice Ryhl wrote:
> > On Thu, Aug 29, 2024 at 8:17 PM Benno Lossin <benno.lossin@proton.me> wrote:
> >>
> >> On 27.08.24 10:41, Alice Ryhl wrote:
> >>> We don't currently have any support for global locks in Rust, however
> >>> they are very useful and I have needed to work around this limitation
> >>> several times. My workarounds generally involve initializing the mutex
> >>> in the module's init function, and this workaround is reflected here.
> >>
> >> I would not exactly call this a "workaround". If your use-case is
> >> covered by putting a `Mutex`, then I would prefer it. Or did you need
> >> additional ugly code to access it?
> >
> > Not sure what you mean by "putting a Mutex" but the workaround is
>
> Oh sorry, seems like I forgot to write the rest of that... Let me try
> again: If your use-case is covered by putting a `Mutex` inside of the
> type that implements `Module`, then I think you should do that instead
> of using a global. (you need the inplace module patch for that)
I don't think it's possible to access the `Module` struct after `init`
returns? Even with in-place init.
> > really gross and involves defining a whole struct to make types Sync
> > and so on. Unlike binder, this patch has access to private fields of
> > Lock, so it can do it in a more nice way. You can find it in the
> > Binder RFC if you search for "context_global".
> > https://lore.kernel.org/rust-for-linux/20231101-rust-binder-v1-2-08ba9197f637@google.com/#Z31drivers:android:context.rs
>
> Oh I remember this... Yeah I agree that is ugly, but it is not the
> workaround that I imagined when you wrote "initializing the mutex in the
> module's init function". There I was thinking of what I wrote above.
>
> This might just be me misunderstanding that, but if you want to improve
> it, then you could mention that the mutex is still a static.
>
> >>> Due to the initialization requirement, constructing a global mutex is
> >>> unsafe with the current approach. In the future, it would be really nice
> >>> to support global mutexes that don't need to be initialized, which would
> >>> make them safe. Unfortunately, this is not possible today because
> >>> bindgen refuses to expose __ARCH_SPIN_LOCK_UNLOCKED to Rust as a
> >>> compile-time constant. It just generates an `extern "C"` global
> >>> reference instead.
> >>
> >> Ideally, we would have support for static initialization in pinned-init.
> >
> > I don't think traits work with const today, so pin-init would need an
> > entirely different mechanism? If you're talking about using
>
> Oh yeah I forgot that that got scratched some time ago.
>
> > CONSTRUCTORS, then I think it's an undesirable solution. C code can
>
> No, I was thinking that the initializer is run at const eval and then
> the result is put into the binary.
>
> > define static mutexes without load-time initialization hooks. We
> > should be able to do the same.
>
> Agreed.
>
> >>> On most architectures, we could initialize the lock to just contain all
> >>> zeros. A possible improvement would be to create a Kconfig constant
> >>> that is set whenever the current architecture uses all zeros for the
> >>> initializer and have `unsafe_const_init` be a no-op on those
> >>> architectures. We could also provide a safe const initializer that is
> >>> only available when that Kconfig option is set.
> >>
> >> I am not sure if the two branches (depending on the config) will be a
> >> good idea. We don't save on `unsafe` and only increase code complexity.
> >> The no-op sounds like a better idea to me.
> >
> > You mean put the logic here instead in the downstream user? I agree.
>
> I meant that
>
> #[cfg(ZERO_LOCK_INIT)]
> static MY_MUTEX: Mutex<()> = Mutex::new_zeroed();
>
> #[cfg(not(ZERO_LOCK_INIT))]
> // SAFETY: ...
> static MY_MUTEX: Mutex<()> = unsafe { Mutex::unsafe_const_new() };
>
>
> module_init() {
> #[cfg(not(ZERO_LOCK_INIT))]
> {
> // SAFETY: ...
> unsafe { MY_MUTEX.unsafe_const_init() };
> }
> }
>
> is significantly worse compared to just
>
> // SAFETY: ...
> static MY_MUTEX: Mutex<()> = unsafe { Mutex::unsafe_const_new() };
>
>
> module_init() {
> // SAFETY: ...
> unsafe { MY_MUTEX.unsafe_const_init() };
> // ^^^^^^^^^^^^^^^^^
> // if ZERO_LOCK_INIT, then this is a no-op.
> }
Agree.
> >>> For architectures that don't use all-zeros for the unlocked case, we
> >>> will most likely have to hard-code the correct representation on the
> >>> Rust side.
> >>
> >> You mean in `unsafe_const_init`?
> >
> > No, I mean we would have `unsafe_const_new` directly set `state` to
> > the right value and let `unsafe_const_init` be a no-op.
>
> But how do you set the right value of a list_head? The value will be
> moved.
Right ... we probably can't get around needing a macro. Can statics
even reference themselves?
> >>> Signed-off-by: Alice Ryhl <aliceryhl@google.com>
> >>> ---
> >>> Changes in v2:
> >>> - Require `self: Pin<&Self>` and recommend `Pin::static_ref`.
> >>> - Other doc improvements including new example.
> >>> - Link to v1: https://lore.kernel.org/r/20240826-static-mutex-v1-1-a14ee71561f3@google.com
> >>> ---
> >>> rust/kernel/sync/lock.rs | 64 +++++++++++++++++++++++++++++++++++++++++++++++-
> >>> 1 file changed, 63 insertions(+), 1 deletion(-)
> >>>
> >>> diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs
> >>> index f6c34ca4d819..cfc5e160d78c 100644
> >>> --- a/rust/kernel/sync/lock.rs
> >>> +++ b/rust/kernel/sync/lock.rs
> >>> @@ -7,7 +7,7 @@
> >>>
> >>> use super::LockClassKey;
> >>> use crate::{init::PinInit, pin_init, str::CStr, types::Opaque, types::ScopeGuard};
> >>> -use core::{cell::UnsafeCell, marker::PhantomData, marker::PhantomPinned};
> >>> +use core::{cell::UnsafeCell, marker::PhantomData, marker::PhantomPinned, pin::Pin};
> >>> use macros::pin_data;
> >>>
> >>> pub mod mutex;
> >>> @@ -117,6 +117,68 @@ pub fn new(t: T, name: &'static CStr, key: &'static LockClassKey) -> impl PinIni
> >>> }),
> >>> })
> >>> }
> >>> +
> >>> + /// Create a global lock that has not yet been initialized.
> >>> + ///
> >>
> >> Could you add a paragraph that explains that
> >
> > Explains that what?
>
> ... this is not the usual way to create a `Lock`, use this only when
> creating a global, `static` lock. For all other purposes, use
> `new_<lock-type>`.
Ok.
> >>> + /// Since global locks is not yet fully supported, this method implements global locks by
> >>> + /// requiring you to initialize them before you start using it. Usually this is best done in
> >>> + /// the module's init function.
> >>> + ///
> >>> + /// # Examples
> >>> + ///
> >>
> >> I would preface this example with "Instead of [`Mutex<T>`], you can use
> >> any other lock.".
> >
> > I don't love that wording. How about something along these lines?
> > "This example uses a Mutex, but this works with any other lock
> > including spin locks."
>
> Sure.
>
> >>> + /// ```
> >>> + /// use kernel::sync::Mutex;
> >>> + ///
> >>> + /// // SAFETY: We initialize the mutex before first use.
> >>> + /// static MY_MUTEX: Mutex<()> = unsafe { Mutex::unsafe_const_new(()) };
> >>> + ///
> >>> + /// // For the sake of this example, assume that this is the module initializer.
> >>
> >> Why not actually provide a module initializer?
> >
> > Can I put a `module!` macro inside a kunit test? I assumed that I couldn't.
>
> I think if you wrap it in another `mod`, then it should work, but I
> might be wrong.
I guess I can implement the Module trait without using the module! macro.
> >>> + /// .unsafe_const_init(kernel::c_str!("MY_MUTEX"), kernel::static_lock_class!())
> >>> + /// };
> >>> + /// }
> >>> + /// ```
> >>> + ///
> >>> + /// # Safety
> >>> + ///
> >>> + /// You must call [`unsafe_const_init`] before calling any other method on this lock.
> >>> + ///
> >>> + /// [`unsafe_const_init`]: Self::unsafe_const_init
> >>> + pub const unsafe fn unsafe_const_new(t: T) -> Self {
> >>
> >> I am not sure on this name, I don't think we have any functions with
> >> `unsafe` in it (and `std` also doesn't). How about `new_uninitialized`?
> >>
> >> Although that might be confusing, since it does actually take a value...
> >
> > Hmm. Any other ideas? const_new_need_manual_init?
>
> Hmm that seems too long... `new_static_uninit`? I don't think that
> `const` belongs in the name either, since you wouldn't use it in a
> `const` (but sure it is used in const contexts, but I find putting it in
> the name confusing).
Works for me.
Alice
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2] rust: add global lock support
2024-09-02 11:37 ` Alice Ryhl
@ 2024-09-02 11:42 ` Alice Ryhl
2024-09-02 14:18 ` Boqun Feng
2024-09-02 22:16 ` Benno Lossin
2024-09-02 21:37 ` Benno Lossin
1 sibling, 2 replies; 14+ messages in thread
From: Alice Ryhl @ 2024-09-02 11:42 UTC (permalink / raw)
To: Benno Lossin
Cc: Miguel Ojeda, Alex Gaynor, Wedson Almeida Filho, Boqun Feng,
Gary Guo, Björn Roy Baron, Andreas Hindborg, rust-for-linux,
linux-kernel
On Mon, Sep 2, 2024 at 1:37 PM Alice Ryhl <aliceryhl@google.com> wrote:
>
> On Fri, Aug 30, 2024 at 3:22 PM Benno Lossin <benno.lossin@proton.me> wrote:
> >
> > On 30.08.24 07:34, Alice Ryhl wrote:
> > > On Thu, Aug 29, 2024 at 8:17 PM Benno Lossin <benno.lossin@proton.me> wrote:
> > >>
> > >> On 27.08.24 10:41, Alice Ryhl wrote:
> > >>> For architectures that don't use all-zeros for the unlocked case, we
> > >>> will most likely have to hard-code the correct representation on the
> > >>> Rust side.
> > >>
> > >> You mean in `unsafe_const_init`?
> > >
> > > No, I mean we would have `unsafe_const_new` directly set `state` to
> > > the right value and let `unsafe_const_init` be a no-op.
> >
> > But how do you set the right value of a list_head? The value will be
> > moved.
>
> Right ... we probably can't get around needing a macro. Can statics
> even reference themselves?
Looks like they can:
use std::ptr::addr_of;
struct MyStruct {
ptr: *const MyStruct,
}
static mut MY_STRUCT: MyStruct = MyStruct {
ptr: addr_of!(MY_STRUCT),
};
Alice
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2] rust: add global lock support
2024-09-02 11:42 ` Alice Ryhl
@ 2024-09-02 14:18 ` Boqun Feng
2024-09-02 14:19 ` Alice Ryhl
2024-09-02 22:16 ` Benno Lossin
1 sibling, 1 reply; 14+ messages in thread
From: Boqun Feng @ 2024-09-02 14:18 UTC (permalink / raw)
To: Alice Ryhl
Cc: Benno Lossin, Miguel Ojeda, Alex Gaynor, Wedson Almeida Filho,
Gary Guo, Björn Roy Baron, Andreas Hindborg, rust-for-linux,
linux-kernel
On Mon, Sep 02, 2024 at 01:42:53PM +0200, Alice Ryhl wrote:
> On Mon, Sep 2, 2024 at 1:37 PM Alice Ryhl <aliceryhl@google.com> wrote:
> >
> > On Fri, Aug 30, 2024 at 3:22 PM Benno Lossin <benno.lossin@proton.me> wrote:
> > >
> > > On 30.08.24 07:34, Alice Ryhl wrote:
> > > > On Thu, Aug 29, 2024 at 8:17 PM Benno Lossin <benno.lossin@proton.me> wrote:
> > > >>
> > > >> On 27.08.24 10:41, Alice Ryhl wrote:
> > > >>> For architectures that don't use all-zeros for the unlocked case, we
> > > >>> will most likely have to hard-code the correct representation on the
> > > >>> Rust side.
> > > >>
> > > >> You mean in `unsafe_const_init`?
> > > >
> > > > No, I mean we would have `unsafe_const_new` directly set `state` to
> > > > the right value and let `unsafe_const_init` be a no-op.
> > >
> > > But how do you set the right value of a list_head? The value will be
> > > moved.
> >
> > Right ... we probably can't get around needing a macro. Can statics
> > even reference themselves?
>
> Looks like they can:
>
> use std::ptr::addr_of;
>
> struct MyStruct {
> ptr: *const MyStruct,
> }
>
> static mut MY_STRUCT: MyStruct = MyStruct {
> ptr: addr_of!(MY_STRUCT),
I'm guessing you're using nightly or new enough rustc, in the current
stable (1.80), this would complain using static mut without unsafe:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=2954daab193caf14d1fb91492dcf325a
, which gets changed recently:
https://github.com/rust-lang/rust/pull/125834
Regards,
Boqun
> };
>
> Alice
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2] rust: add global lock support
2024-09-02 14:18 ` Boqun Feng
@ 2024-09-02 14:19 ` Alice Ryhl
0 siblings, 0 replies; 14+ messages in thread
From: Alice Ryhl @ 2024-09-02 14:19 UTC (permalink / raw)
To: Boqun Feng
Cc: Benno Lossin, Miguel Ojeda, Alex Gaynor, Wedson Almeida Filho,
Gary Guo, Björn Roy Baron, Andreas Hindborg, rust-for-linux,
linux-kernel
On Mon, Sep 2, 2024 at 4:18 PM Boqun Feng <boqun.feng@gmail.com> wrote:
>
> On Mon, Sep 02, 2024 at 01:42:53PM +0200, Alice Ryhl wrote:
> > On Mon, Sep 2, 2024 at 1:37 PM Alice Ryhl <aliceryhl@google.com> wrote:
> > >
> > > On Fri, Aug 30, 2024 at 3:22 PM Benno Lossin <benno.lossin@proton.me> wrote:
> > > >
> > > > On 30.08.24 07:34, Alice Ryhl wrote:
> > > > > On Thu, Aug 29, 2024 at 8:17 PM Benno Lossin <benno.lossin@proton.me> wrote:
> > > > >>
> > > > >> On 27.08.24 10:41, Alice Ryhl wrote:
> > > > >>> For architectures that don't use all-zeros for the unlocked case, we
> > > > >>> will most likely have to hard-code the correct representation on the
> > > > >>> Rust side.
> > > > >>
> > > > >> You mean in `unsafe_const_init`?
> > > > >
> > > > > No, I mean we would have `unsafe_const_new` directly set `state` to
> > > > > the right value and let `unsafe_const_init` be a no-op.
> > > >
> > > > But how do you set the right value of a list_head? The value will be
> > > > moved.
> > >
> > > Right ... we probably can't get around needing a macro. Can statics
> > > even reference themselves?
> >
> > Looks like they can:
> >
> > use std::ptr::addr_of;
> >
> > struct MyStruct {
> > ptr: *const MyStruct,
> > }
> >
> > static mut MY_STRUCT: MyStruct = MyStruct {
> > ptr: addr_of!(MY_STRUCT),
>
> I'm guessing you're using nightly or new enough rustc, in the current
> stable (1.80), this would complain using static mut without unsafe:
>
> https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=2954daab193caf14d1fb91492dcf325a
>
> , which gets changed recently:
>
> https://github.com/rust-lang/rust/pull/125834
That's a trivial matter. Adding the unsafe block makes it work on stable.
Alice
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2] rust: add global lock support
2024-09-02 11:37 ` Alice Ryhl
2024-09-02 11:42 ` Alice Ryhl
@ 2024-09-02 21:37 ` Benno Lossin
1 sibling, 0 replies; 14+ messages in thread
From: Benno Lossin @ 2024-09-02 21:37 UTC (permalink / raw)
To: Alice Ryhl
Cc: Miguel Ojeda, Alex Gaynor, Wedson Almeida Filho, Boqun Feng,
Gary Guo, Björn Roy Baron, Andreas Hindborg, rust-for-linux,
linux-kernel
On 02.09.24 13:37, Alice Ryhl wrote:
> On Fri, Aug 30, 2024 at 3:22 PM Benno Lossin <benno.lossin@proton.me> wrote:
>>
>> On 30.08.24 07:34, Alice Ryhl wrote:
>>> On Thu, Aug 29, 2024 at 8:17 PM Benno Lossin <benno.lossin@proton.me> wrote:
>>>>
>>>> On 27.08.24 10:41, Alice Ryhl wrote:
>>>>> We don't currently have any support for global locks in Rust, however
>>>>> they are very useful and I have needed to work around this limitation
>>>>> several times. My workarounds generally involve initializing the mutex
>>>>> in the module's init function, and this workaround is reflected here.
>>>>
>>>> I would not exactly call this a "workaround". If your use-case is
>>>> covered by putting a `Mutex`, then I would prefer it. Or did you need
>>>> additional ugly code to access it?
>>>
>>> Not sure what you mean by "putting a Mutex" but the workaround is
>>
>> Oh sorry, seems like I forgot to write the rest of that... Let me try
>> again: If your use-case is covered by putting a `Mutex` inside of the
>> type that implements `Module`, then I think you should do that instead
>> of using a global. (you need the inplace module patch for that)
>
> I don't think it's possible to access the `Module` struct after `init`
> returns? Even with in-place init.
Oh I see... Maybe if you create it inside of an `Arc` or `Box` and then
pass it to something inside of your module that will then be called by
some other mechanism?
---
Cheers,
Benno
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2] rust: add global lock support
2024-09-02 11:42 ` Alice Ryhl
2024-09-02 14:18 ` Boqun Feng
@ 2024-09-02 22:16 ` Benno Lossin
2024-09-04 10:32 ` Alice Ryhl
1 sibling, 1 reply; 14+ messages in thread
From: Benno Lossin @ 2024-09-02 22:16 UTC (permalink / raw)
To: Alice Ryhl
Cc: Miguel Ojeda, Alex Gaynor, Wedson Almeida Filho, Boqun Feng,
Gary Guo, Björn Roy Baron, Andreas Hindborg, rust-for-linux,
linux-kernel
On 02.09.24 13:42, Alice Ryhl wrote:
> On Mon, Sep 2, 2024 at 1:37 PM Alice Ryhl <aliceryhl@google.com> wrote:
>>
>> On Fri, Aug 30, 2024 at 3:22 PM Benno Lossin <benno.lossin@proton.me> wrote:
>>>
>>> On 30.08.24 07:34, Alice Ryhl wrote:
>>>> On Thu, Aug 29, 2024 at 8:17 PM Benno Lossin <benno.lossin@proton.me> wrote:
>>>>>
>>>>> On 27.08.24 10:41, Alice Ryhl wrote:
>>>>>> For architectures that don't use all-zeros for the unlocked case, we
>>>>>> will most likely have to hard-code the correct representation on the
>>>>>> Rust side.
>>>>>
>>>>> You mean in `unsafe_const_init`?
>>>>
>>>> No, I mean we would have `unsafe_const_new` directly set `state` to
>>>> the right value and let `unsafe_const_init` be a no-op.
>>>
>>> But how do you set the right value of a list_head? The value will be
>>> moved.
>>
>> Right ... we probably can't get around needing a macro. Can statics
>> even reference themselves?
>
> Looks like they can:
>
> use std::ptr::addr_of;
>
> struct MyStruct {
> ptr: *const MyStruct,
> }
>
> static mut MY_STRUCT: MyStruct = MyStruct {
> ptr: addr_of!(MY_STRUCT),
> };
That's useful to know...
But I don't see a way to get pinned-init to work with this. I would need
a lot of currently experimental features (const closures, const traits)
and a way to initialize a static without providing a direct value, since
I can't just do
static mut MY_STRUCT: MyStruct = {
unsafe { __pinned_init(addr_of_mut!(MY_STRUCT), /* initializer */) };
unsafe { addr_of!(MY_STRUCT).read() }
};
It (rightfully) complains that I am initializing the static with itself.
We /might/ be able to do something special for `Mutex`/ other locks, but
I haven't tried yet. So the unsafe approach seems the best at the moment.
---
Cheers,
Benno
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2] rust: add global lock support
2024-09-02 22:16 ` Benno Lossin
@ 2024-09-04 10:32 ` Alice Ryhl
2024-09-10 7:10 ` Benno Lossin
0 siblings, 1 reply; 14+ messages in thread
From: Alice Ryhl @ 2024-09-04 10:32 UTC (permalink / raw)
To: Benno Lossin
Cc: Miguel Ojeda, Alex Gaynor, Wedson Almeida Filho, Boqun Feng,
Gary Guo, Björn Roy Baron, Andreas Hindborg, rust-for-linux,
linux-kernel
On Tue, Sep 3, 2024 at 12:17 AM Benno Lossin <benno.lossin@proton.me> wrote:
>
> On 02.09.24 13:42, Alice Ryhl wrote:
> > On Mon, Sep 2, 2024 at 1:37 PM Alice Ryhl <aliceryhl@google.com> wrote:
> >>
> >> On Fri, Aug 30, 2024 at 3:22 PM Benno Lossin <benno.lossin@proton.me> wrote:
> >>>
> >>> On 30.08.24 07:34, Alice Ryhl wrote:
> >>>> On Thu, Aug 29, 2024 at 8:17 PM Benno Lossin <benno.lossin@proton.me> wrote:
> >>>>>
> >>>>> On 27.08.24 10:41, Alice Ryhl wrote:
> >>>>>> For architectures that don't use all-zeros for the unlocked case, we
> >>>>>> will most likely have to hard-code the correct representation on the
> >>>>>> Rust side.
> >>>>>
> >>>>> You mean in `unsafe_const_init`?
> >>>>
> >>>> No, I mean we would have `unsafe_const_new` directly set `state` to
> >>>> the right value and let `unsafe_const_init` be a no-op.
> >>>
> >>> But how do you set the right value of a list_head? The value will be
> >>> moved.
> >>
> >> Right ... we probably can't get around needing a macro. Can statics
> >> even reference themselves?
> >
> > Looks like they can:
> >
> > use std::ptr::addr_of;
> >
> > struct MyStruct {
> > ptr: *const MyStruct,
> > }
> >
> > static mut MY_STRUCT: MyStruct = MyStruct {
> > ptr: addr_of!(MY_STRUCT),
> > };
>
> That's useful to know...
> But I don't see a way to get pinned-init to work with this. I would need
> a lot of currently experimental features (const closures, const traits)
> and a way to initialize a static without providing a direct value, since
> I can't just do
>
> static mut MY_STRUCT: MyStruct = {
> unsafe { __pinned_init(addr_of_mut!(MY_STRUCT), /* initializer */) };
> unsafe { addr_of!(MY_STRUCT).read() }
> };
>
> It (rightfully) complains that I am initializing the static with itself.
>
> We /might/ be able to do something special for `Mutex`/ other locks, but
> I haven't tried yet. So the unsafe approach seems the best at the moment.
It sounds like we'll just want a macro that generates a global wrapped
in a Mutex/SpinLock for now ...
If we're going to do that, we could take the extra step and have it
generate special Guard and LockedBy types so that you can have a
LockedBy that doesn't need to make any runtime checks.
Alice
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2] rust: add global lock support
2024-09-04 10:32 ` Alice Ryhl
@ 2024-09-10 7:10 ` Benno Lossin
0 siblings, 0 replies; 14+ messages in thread
From: Benno Lossin @ 2024-09-10 7:10 UTC (permalink / raw)
To: Alice Ryhl
Cc: Miguel Ojeda, Alex Gaynor, Wedson Almeida Filho, Boqun Feng,
Gary Guo, Björn Roy Baron, Andreas Hindborg, rust-for-linux,
linux-kernel
On 04.09.24 12:32, Alice Ryhl wrote:
> On Tue, Sep 3, 2024 at 12:17 AM Benno Lossin <benno.lossin@proton.me> wrote:
>>
>> On 02.09.24 13:42, Alice Ryhl wrote:
>>> On Mon, Sep 2, 2024 at 1:37 PM Alice Ryhl <aliceryhl@google.com> wrote:
>>>>
>>>> On Fri, Aug 30, 2024 at 3:22 PM Benno Lossin <benno.lossin@proton.me> wrote:
>>>>>
>>>>> On 30.08.24 07:34, Alice Ryhl wrote:
>>>>>> On Thu, Aug 29, 2024 at 8:17 PM Benno Lossin <benno.lossin@proton.me> wrote:
>>>>>>>
>>>>>>> On 27.08.24 10:41, Alice Ryhl wrote:
>>>>>>>> For architectures that don't use all-zeros for the unlocked case, we
>>>>>>>> will most likely have to hard-code the correct representation on the
>>>>>>>> Rust side.
>>>>>>>
>>>>>>> You mean in `unsafe_const_init`?
>>>>>>
>>>>>> No, I mean we would have `unsafe_const_new` directly set `state` to
>>>>>> the right value and let `unsafe_const_init` be a no-op.
>>>>>
>>>>> But how do you set the right value of a list_head? The value will be
>>>>> moved.
>>>>
>>>> Right ... we probably can't get around needing a macro. Can statics
>>>> even reference themselves?
>>>
>>> Looks like they can:
>>>
>>> use std::ptr::addr_of;
>>>
>>> struct MyStruct {
>>> ptr: *const MyStruct,
>>> }
>>>
>>> static mut MY_STRUCT: MyStruct = MyStruct {
>>> ptr: addr_of!(MY_STRUCT),
>>> };
>>
>> That's useful to know...
>> But I don't see a way to get pinned-init to work with this. I would need
>> a lot of currently experimental features (const closures, const traits)
>> and a way to initialize a static without providing a direct value, since
>> I can't just do
>>
>> static mut MY_STRUCT: MyStruct = {
>> unsafe { __pinned_init(addr_of_mut!(MY_STRUCT), /* initializer */) };
>> unsafe { addr_of!(MY_STRUCT).read() }
>> };
>>
>> It (rightfully) complains that I am initializing the static with itself.
>>
>> We /might/ be able to do something special for `Mutex`/ other locks, but
>> I haven't tried yet. So the unsafe approach seems the best at the moment.
>
> It sounds like we'll just want a macro that generates a global wrapped
> in a Mutex/SpinLock for now ...
Yeah.
> If we're going to do that, we could take the extra step and have it
> generate special Guard and LockedBy types so that you can have a
> LockedBy that doesn't need to make any runtime checks.
Oh that is a good idea!
---
Cheers,
Benno
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2024-09-10 7:10 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-27 8:41 [PATCH v2] rust: add global lock support Alice Ryhl
2024-08-29 18:16 ` Benno Lossin
2024-08-30 5:34 ` Alice Ryhl
2024-08-30 13:21 ` Benno Lossin
2024-09-02 11:37 ` Alice Ryhl
2024-09-02 11:42 ` Alice Ryhl
2024-09-02 14:18 ` Boqun Feng
2024-09-02 14:19 ` Alice Ryhl
2024-09-02 22:16 ` Benno Lossin
2024-09-04 10:32 ` Alice Ryhl
2024-09-10 7:10 ` Benno Lossin
2024-09-02 21:37 ` Benno Lossin
2024-08-30 15:09 ` Gary Guo
2024-09-02 10:46 ` Alice Ryhl
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).