rust-for-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1 1/3] rust: sync: set_once: Add fast-path check to avoid expensive cmpxchg
@ 2025-12-11 23:09 FUJITA Tomonori
  2025-12-11 23:09 ` [PATCH v1 2/3] rust: sync: set_once: Implement Send and Sync FUJITA Tomonori
  2025-12-11 23:09 ` [PATCH v1 3/3] rust: sync: set_once: fix doc section heading FUJITA Tomonori
  0 siblings, 2 replies; 5+ messages in thread
From: FUJITA Tomonori @ 2025-12-11 23:09 UTC (permalink / raw)
  To: ojeda, a.hindborg
  Cc: aliceryhl, bjorn3_gh, boqun.feng, dakr, gary, lossin, tmgross,
	rust-for-linux

Check if already initialized before calling cmpxchg in populate().

When SetOnce is already populated, this avoids the expensive LOCK
CMPXCHG operation and uses a simple load instead.

The Relaxed load is safe here because it's only a hint; the subsequent
cmpxchg provides the actual synchronization. Even if we read a stale
value (0), the cmpxchg will correctly fail.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
 rust/kernel/sync/set_once.rs | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/rust/kernel/sync/set_once.rs b/rust/kernel/sync/set_once.rs
index bdba601807d8..889d37dfd17f 100644
--- a/rust/kernel/sync/set_once.rs
+++ b/rust/kernel/sync/set_once.rs
@@ -80,6 +80,10 @@ pub fn as_ref(&self) -> Option<&T> {
     ///
     /// Returns `true` if the [`SetOnce`] was successfully populated.
     pub fn populate(&self, value: T) -> bool {
+        // Avoid expensive cmpxchg if already initialized.
+        if self.init.load(Relaxed) != 0 {
+            return false;
+        }
         // INVARIANT: If the swap succeeds:
         //  - We increase `init`.
         //  - We write the valid value `1` to `init`.

base-commit: d358e5254674b70f34c847715ca509e46eb81e6f
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v1 2/3] rust: sync: set_once: Implement Send and Sync
  2025-12-11 23:09 [PATCH v1 1/3] rust: sync: set_once: Add fast-path check to avoid expensive cmpxchg FUJITA Tomonori
@ 2025-12-11 23:09 ` FUJITA Tomonori
  2025-12-12  0:34   ` Gary Guo
  2025-12-11 23:09 ` [PATCH v1 3/3] rust: sync: set_once: fix doc section heading FUJITA Tomonori
  1 sibling, 1 reply; 5+ messages in thread
From: FUJITA Tomonori @ 2025-12-11 23:09 UTC (permalink / raw)
  To: ojeda, a.hindborg
  Cc: aliceryhl, bjorn3_gh, boqun.feng, dakr, gary, lossin, tmgross,
	rust-for-linux

Implement Send and Sync for SetOnce<T> to allow it to be used across
thread boundaries.

Send: SetOnce<T> can be transferred across threads when T: Send, as
the contained value is also transferred and will be dropped on the
destination thread.

Sync: SetOnce<T> can be shared across threads when T: Sync, as
as_ref() provides shared references &T and atomic operations ensure
proper synchronization.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
 rust/kernel/sync/set_once.rs | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/rust/kernel/sync/set_once.rs b/rust/kernel/sync/set_once.rs
index 889d37dfd17f..5894d0dda14e 100644
--- a/rust/kernel/sync/set_once.rs
+++ b/rust/kernel/sync/set_once.rs
@@ -127,3 +127,10 @@ fn drop(&mut self) {
         }
     }
 }
+
+// SAFETY: `SetOnce` can be transferred across thread boundaries iff the data it contains can.
+unsafe impl<T: Send> Send for SetOnce<T> {}
+
+// SAFETY: `SetOnce` synchronises access to the inner value via atomic operations, so it is `Sync`
+// as long as the data it contains is `Sync`.
+unsafe impl<T: Sync> Sync for SetOnce<T> {}
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v1 3/3] rust: sync: set_once: fix doc section heading
  2025-12-11 23:09 [PATCH v1 1/3] rust: sync: set_once: Add fast-path check to avoid expensive cmpxchg FUJITA Tomonori
  2025-12-11 23:09 ` [PATCH v1 2/3] rust: sync: set_once: Implement Send and Sync FUJITA Tomonori
@ 2025-12-11 23:09 ` FUJITA Tomonori
  1 sibling, 0 replies; 5+ messages in thread
From: FUJITA Tomonori @ 2025-12-11 23:09 UTC (permalink / raw)
  To: ojeda, a.hindborg
  Cc: aliceryhl, bjorn3_gh, boqun.feng, dakr, gary, lossin, tmgross,
	rust-for-linux

The documentation section uses multiple examples, so the heading
should be "Examples" instead of "Example". This also matches the
headings used in other parts of the code for consistency.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
 rust/kernel/sync/set_once.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/rust/kernel/sync/set_once.rs b/rust/kernel/sync/set_once.rs
index 5894d0dda14e..ab362410119d 100644
--- a/rust/kernel/sync/set_once.rs
+++ b/rust/kernel/sync/set_once.rs
@@ -23,7 +23,7 @@
 /// - `init == 2` if and only if `value` is initialized and valid for shared
 ///   access.
 ///
-/// # Example
+/// # Examples
 ///
 /// ```
 /// # use kernel::sync::SetOnce;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v1 2/3] rust: sync: set_once: Implement Send and Sync
  2025-12-11 23:09 ` [PATCH v1 2/3] rust: sync: set_once: Implement Send and Sync FUJITA Tomonori
@ 2025-12-12  0:34   ` Gary Guo
  2025-12-12  2:07     ` FUJITA Tomonori
  0 siblings, 1 reply; 5+ messages in thread
From: Gary Guo @ 2025-12-12  0:34 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: ojeda, a.hindborg, aliceryhl, bjorn3_gh, boqun.feng, dakr, lossin,
	tmgross, rust-for-linux

On Fri, 12 Dec 2025 08:09:18 +0900
FUJITA Tomonori <fujita.tomonori@gmail.com> wrote:

> Implement Send and Sync for SetOnce<T> to allow it to be used across
> thread boundaries.
> 
> Send: SetOnce<T> can be transferred across threads when T: Send, as
> the contained value is also transferred and will be dropped on the
> destination thread.
> 
> Sync: SetOnce<T> can be shared across threads when T: Sync, as
> as_ref() provides shared references &T and atomic operations ensure
> proper synchronization.
> 
> Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
> ---
>  rust/kernel/sync/set_once.rs | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/rust/kernel/sync/set_once.rs b/rust/kernel/sync/set_once.rs
> index 889d37dfd17f..5894d0dda14e 100644
> --- a/rust/kernel/sync/set_once.rs
> +++ b/rust/kernel/sync/set_once.rs
> @@ -127,3 +127,10 @@ fn drop(&mut self) {
>          }
>      }
>  }
> +
> +// SAFETY: `SetOnce` can be transferred across thread boundaries iff the data it contains can.
> +unsafe impl<T: Send> Send for SetOnce<T> {}
> +
> +// SAFETY: `SetOnce` synchronises access to the inner value via atomic operations, so it is `Sync`
> +// as long as the data it contains is `Sync`.
> +unsafe impl<T: Sync> Sync for SetOnce<T> {}

This needs to be `T: Send + Sync` as `T` can be destroyed on a
different thread that creates it.

Best,
Gary


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v1 2/3] rust: sync: set_once: Implement Send and Sync
  2025-12-12  0:34   ` Gary Guo
@ 2025-12-12  2:07     ` FUJITA Tomonori
  0 siblings, 0 replies; 5+ messages in thread
From: FUJITA Tomonori @ 2025-12-12  2:07 UTC (permalink / raw)
  To: gary
  Cc: fujita.tomonori, ojeda, a.hindborg, aliceryhl, bjorn3_gh,
	boqun.feng, dakr, lossin, tmgross, rust-for-linux

On Fri, 12 Dec 2025 00:34:01 +0000
Gary Guo <gary@garyguo.net> wrote:

> On Fri, 12 Dec 2025 08:09:18 +0900
> FUJITA Tomonori <fujita.tomonori@gmail.com> wrote:
> 
>> Implement Send and Sync for SetOnce<T> to allow it to be used across
>> thread boundaries.
>> 
>> Send: SetOnce<T> can be transferred across threads when T: Send, as
>> the contained value is also transferred and will be dropped on the
>> destination thread.
>> 
>> Sync: SetOnce<T> can be shared across threads when T: Sync, as
>> as_ref() provides shared references &T and atomic operations ensure
>> proper synchronization.
>> 
>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
>> ---
>>  rust/kernel/sync/set_once.rs | 7 +++++++
>>  1 file changed, 7 insertions(+)
>> 
>> diff --git a/rust/kernel/sync/set_once.rs b/rust/kernel/sync/set_once.rs
>> index 889d37dfd17f..5894d0dda14e 100644
>> --- a/rust/kernel/sync/set_once.rs
>> +++ b/rust/kernel/sync/set_once.rs
>> @@ -127,3 +127,10 @@ fn drop(&mut self) {
>>          }
>>      }
>>  }
>> +
>> +// SAFETY: `SetOnce` can be transferred across thread boundaries iff the data it contains can.
>> +unsafe impl<T: Send> Send for SetOnce<T> {}
>> +
>> +// SAFETY: `SetOnce` synchronises access to the inner value via atomic operations, so it is `Sync`
>> +// as long as the data it contains is `Sync`.
>> +unsafe impl<T: Sync> Sync for SetOnce<T> {}
> 
> This needs to be `T: Send + Sync` as `T` can be destroyed on a
> different thread that creates it.

Thanks!

You're right. T must also be `Send` in order for `SetOnce<t>` to be
`Sync`.

I'll update the `Sync` impl to require `T: Send + Sync` and adjust the
SAFETY comment in v2.


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2025-12-12  2:07 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-11 23:09 [PATCH v1 1/3] rust: sync: set_once: Add fast-path check to avoid expensive cmpxchg FUJITA Tomonori
2025-12-11 23:09 ` [PATCH v1 2/3] rust: sync: set_once: Implement Send and Sync FUJITA Tomonori
2025-12-12  0:34   ` Gary Guo
2025-12-12  2:07     ` FUJITA Tomonori
2025-12-11 23:09 ` [PATCH v1 3/3] rust: sync: set_once: fix doc section heading FUJITA Tomonori

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