From: "Benno Lossin" <lossin@kernel.org>
To: "Danilo Krummrich" <dakr@kernel.org>,
<gregkh@linuxfoundation.org>, <rafael@kernel.org>,
<ojeda@kernel.org>, <alex.gaynor@gmail.com>,
<boqun.feng@gmail.com>, <gary@garyguo.net>,
<bjorn3_gh@protonmail.com>, <benno.lossin@proton.me>,
<a.hindborg@kernel.org>, <aliceryhl@google.com>,
<tmgross@umich.edu>, <chrisi.schrefl@gmail.com>
Cc: <rust-for-linux@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
"Ingo Molnar" <mingo@redhat.com>,
"Peter Zijlstra" <peterz@infradead.org>,
"Juri Lelli" <juri.lelli@redhat.com>,
"Vincent Guittot" <vincent.guittot@linaro.org>,
"Dietmar Eggemann" <dietmar.eggemann@arm.com>,
"Steven Rostedt" <rostedt@goodmis.org>,
"Ben Segall" <bsegall@google.com>, "Mel Gorman" <mgorman@suse.de>,
"Valentin Schneider" <vschneid@redhat.com>
Subject: Re: [PATCH 1/3] rust: completion: implement initial abstraction
Date: Thu, 12 Jun 2025 09:58:30 +0200 [thread overview]
Message-ID: <DAKE8OYKXUWH.1NRVGV5IKW7I9@kernel.org> (raw)
In-Reply-To: <20250603205416.49281-2-dakr@kernel.org>
On Tue Jun 3, 2025 at 10:48 PM CEST, Danilo Krummrich wrote:
> Implement a minimal abstraction for the completion synchronization
> primitive.
>
> This initial abstraction only adds complete_all() and
> wait_for_completion(), since that is what is required for the subsequent
> Devres patch.
>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Juri Lelli <juri.lelli@redhat.com>
> Cc: Vincent Guittot <vincent.guittot@linaro.org>
> Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
> Cc: Steven Rostedt <rostedt@goodmis.org>
> Cc: Ben Segall <bsegall@google.com>
> Cc: Mel Gorman <mgorman@suse.de>
> Cc: Valentin Schneider <vschneid@redhat.com>
> Signed-off-by: Danilo Krummrich <dakr@kernel.org>
I have a couple comments on the documentation, but the rest seems good.
So with those fixed:
Reviewed-by: Benno Lossin <lossin@kernel.org>
> ---
> rust/bindings/bindings_helper.h | 1 +
> rust/helpers/completion.c | 8 +++
> rust/helpers/helpers.c | 1 +
> rust/kernel/sync.rs | 2 +
> rust/kernel/sync/completion.rs | 111 ++++++++++++++++++++++++++++++++
> 5 files changed, 123 insertions(+)
> create mode 100644 rust/helpers/completion.c
> create mode 100644 rust/kernel/sync/completion.rs
>
> diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
> index a5a6fb45d405..9da3fe89295c 100644
> --- a/rust/bindings/bindings_helper.h
> +++ b/rust/bindings/bindings_helper.h
> @@ -17,6 +17,7 @@
> #include <linux/blk_types.h>
> #include <linux/blkdev.h>
> #include <linux/clk.h>
> +#include <linux/completion.h>
> #include <linux/configfs.h>
> #include <linux/cpu.h>
> #include <linux/cpufreq.h>
> diff --git a/rust/helpers/completion.c b/rust/helpers/completion.c
> new file mode 100644
> index 000000000000..b2443262a2ae
> --- /dev/null
> +++ b/rust/helpers/completion.c
> @@ -0,0 +1,8 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <linux/completion.h>
> +
> +void rust_helper_init_completion(struct completion *x)
> +{
> + init_completion(x);
> +}
> diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c
> index 805307018f0e..7a5c520be8cb 100644
> --- a/rust/helpers/helpers.c
> +++ b/rust/helpers/helpers.c
> @@ -13,6 +13,7 @@
> #include "build_assert.c"
> #include "build_bug.c"
> #include "clk.c"
> +#include "completion.c"
> #include "cpufreq.c"
> #include "cpumask.c"
> #include "cred.c"
> diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs
> index 36a719015583..c23a12639924 100644
> --- a/rust/kernel/sync.rs
> +++ b/rust/kernel/sync.rs
> @@ -10,6 +10,7 @@
> use pin_init;
>
> mod arc;
> +pub mod completion;
> mod condvar;
> pub mod lock;
> mod locked_by;
> @@ -17,6 +18,7 @@
> pub mod rcu;
>
> pub use arc::{Arc, ArcBorrow, UniqueArc};
> +pub use completion::Completion;
> pub use condvar::{new_condvar, CondVar, CondVarTimeoutResult};
> pub use lock::global::{global_lock, GlobalGuard, GlobalLock, GlobalLockBackend, GlobalLockedBy};
> pub use lock::mutex::{new_mutex, Mutex, MutexGuard};
> diff --git a/rust/kernel/sync/completion.rs b/rust/kernel/sync/completion.rs
> new file mode 100644
> index 000000000000..4ec4c2aa73a5
> --- /dev/null
> +++ b/rust/kernel/sync/completion.rs
> @@ -0,0 +1,111 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +//! Completion support.
> +//!
> +//! Reference: <https://docs.kernel.org/scheduler/completion.html>
> +//!
> +//! C header: [`include/linux/completion.h`](srctree/include/linux/completion.h)
> +
> +use crate::{bindings, prelude::*, types::Opaque};
> +
> +/// Synchronization primitive to signal when a certain task has been completed.
> +///
> +/// The [`Completion`] synchronization primitive signales when a certain task has been completed by
> +/// waking up other tasks that can queue themselves up to wait for the [`Completion`] to be
s/can queue themselves/have been queued/
> +/// completed.
> +///
> +/// # Examples
> +///
> +/// ```
> +/// use kernel::sync::{Arc, Completion};
> +/// use kernel::workqueue::{self, impl_has_work, new_work, Work, WorkItem};
> +///
> +/// #[pin_data]
> +/// struct MyTask {
> +/// #[pin]
> +/// work: Work<MyTask>,
Can we maybe add a dummy value like `Mutex<i32>` here that the task
changes, so we can print the value of it below (after waiting for the
task)?
> +/// #[pin]
> +/// done: Completion,
> +/// }
> +///
> +/// impl_has_work! {
> +/// impl HasWork<Self> for MyTask { self.work }
> +/// }
> +///
> +/// impl MyTask {
> +/// fn new() -> Result<Arc<Self>> {
> +/// let this = Arc::pin_init(pin_init!(MyTask {
> +/// work <- new_work!("MyTask::work"),
> +/// done <- Completion::new(),
> +/// }), GFP_KERNEL)?;
> +///
> +/// let _ = workqueue::system().enqueue(this.clone());
> +///
> +/// Ok(this)
> +/// }
> +///
> +/// fn wait_for_completion(&self) {
> +/// self.done.wait_for_completion();
> +///
> +/// pr_info!("Completion: task complete\n");
> +/// }
> +/// }
> +///
> +/// impl WorkItem for MyTask {
> +/// type Pointer = Arc<MyTask>;
> +///
> +/// fn run(this: Arc<MyTask>) {
> +/// // process this task
> +/// this.done.complete_all();
> +/// }
> +/// }
> +///
> +/// let task = MyTask::new()?;
> +/// task.wait_for_completion();
> +/// # Ok::<(), Error>(())
> +/// ```
> +#[pin_data]
> +pub struct Completion {
> + #[pin]
> + inner: Opaque<bindings::completion>,
> +}
> +
> +impl Completion {
> + /// Create an initializer for a new [`Completion`].
> + pub fn new() -> impl PinInit<Self> {
> + pin_init!(Self {
> + inner <- Opaque::ffi_init(|slot: *mut bindings::completion| {
> + // SAFETY: `slot` is a valid pointer to an uninitialized `struct completion`.
> + unsafe { bindings::init_completion(slot) };
> + }),
> + })
> + }
> +
> + fn as_raw(&self) -> *mut bindings::completion {
> + self.inner.get()
> + }
> +
> + /// Signal all tasks waiting on this completion.
> + ///
> + /// This method wakes up all tasks waiting on this completion; after this operation the
> + /// completion is permanently done.
> + pub fn complete_all(&self) {
> + // SAFETY: `self.as_raw()` is a pointer to a valid `struct completion`.
> + unsafe { bindings::complete_all(self.as_raw()) };
> + }
> +
> + /// Wait for completion of a task.
> + ///
> + /// This method waits for the completion of a task; it is not interruptible and there is no
I personally would write:
s/waits for/blocks on/
But if `wait` is the more common kernel term then let's go with your
version instead.
> + /// timeout.
I would mention the `complete_all` method above.
> + pub fn wait_for_completion(&self) {
> + // SAFETY: `self.as_raw()` is a pointer to a valid `struct completion`.
> + unsafe { bindings::wait_for_completion(self.as_raw()) };
> + }
> +}
> +
> +// SAFETY: `Completion` is safe to be send to any task.
> +unsafe impl Send for Completion {}
> +
> +// SAFETY: `Completion` is safe to be accessed concurrently.
> +unsafe impl Sync for Completion {}
Please move these to the struct definition, that way one can more easily
see them when looking at the code.
---
Cheers,
Benno
next prev parent reply other threads:[~2025-06-12 7:58 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-03 20:48 [PATCH 0/3] Fix race condition in Devres Danilo Krummrich
2025-06-03 20:48 ` [PATCH 1/3] rust: completion: implement initial abstraction Danilo Krummrich
2025-06-06 9:00 ` Alice Ryhl
2025-06-11 20:01 ` Boqun Feng
2025-06-12 7:58 ` Benno Lossin [this message]
2025-06-12 10:47 ` Danilo Krummrich
2025-06-12 11:23 ` Alice Ryhl
2025-06-12 8:15 ` Benno Lossin
2025-06-12 10:35 ` Danilo Krummrich
2025-06-12 10:53 ` Benno Lossin
2025-06-12 11:06 ` Danilo Krummrich
2025-06-12 11:15 ` Benno Lossin
2025-06-03 20:48 ` [PATCH 2/3] rust: revocable: indicate whether `data` has been revoked already Danilo Krummrich
2025-06-12 7:59 ` Benno Lossin
2025-06-03 20:48 ` [PATCH 3/3] rust: devres: fix race in Devres::drop() Danilo Krummrich
2025-06-03 23:26 ` Boqun Feng
2025-06-04 9:49 ` Danilo Krummrich
2025-06-12 15:24 ` Boqun Feng
2025-06-12 15:44 ` Danilo Krummrich
2025-06-12 15:48 ` Boqun Feng
2025-06-12 8:13 ` Benno Lossin
2025-06-12 8:15 ` Alice Ryhl
2025-06-12 8:47 ` Benno Lossin
2025-06-12 10:26 ` Danilo Krummrich
2025-06-12 10:59 ` Benno Lossin
2025-06-12 10:31 ` Danilo Krummrich
2025-06-12 11:04 ` Benno Lossin
2025-06-04 12:36 ` [PATCH 0/3] Fix race condition in Devres Miguel Ojeda
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=DAKE8OYKXUWH.1NRVGV5IKW7I9@kernel.org \
--to=lossin@kernel.org \
--cc=a.hindborg@kernel.org \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=benno.lossin@proton.me \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=bsegall@google.com \
--cc=chrisi.schrefl@gmail.com \
--cc=dakr@kernel.org \
--cc=dietmar.eggemann@arm.com \
--cc=gary@garyguo.net \
--cc=gregkh@linuxfoundation.org \
--cc=juri.lelli@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mgorman@suse.de \
--cc=mingo@redhat.com \
--cc=ojeda@kernel.org \
--cc=peterz@infradead.org \
--cc=rafael@kernel.org \
--cc=rostedt@goodmis.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tmgross@umich.edu \
--cc=vincent.guittot@linaro.org \
--cc=vschneid@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.