mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-10-22 15:03:53 +02:00
rust: completion: implement initial abstraction
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> Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Boqun Feng <boqun.feng@gmail.com> Reviewed-by: Benno Lossin <lossin@kernel.org> Acked-by: Miguel Ojeda <ojeda@kernel.org> Link: https://lore.kernel.org/r/20250612121817.1621-2-dakr@kernel.org Signed-off-by: Danilo Krummrich <dakr@kernel.org>
This commit is contained in:
parent
19272b37aa
commit
1b56e765bf
|
@ -39,6 +39,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>
|
||||
|
|
8
rust/helpers/completion.c
Normal file
8
rust/helpers/completion.c
Normal file
|
@ -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);
|
||||
}
|
|
@ -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"
|
||||
|
|
|
@ -10,6 +10,7 @@ use crate::types::Opaque;
|
|||
use pin_init;
|
||||
|
||||
mod arc;
|
||||
pub mod completion;
|
||||
mod condvar;
|
||||
pub mod lock;
|
||||
mod locked_by;
|
||||
|
@ -17,6 +18,7 @@ pub mod poll;
|
|||
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};
|
||||
|
|
112
rust/kernel/sync/completion.rs
Normal file
112
rust/kernel/sync/completion.rs
Normal file
|
@ -0,0 +1,112 @@
|
|||
// 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 signals when a certain task has been completed by
|
||||
/// waking up other tasks that have been queued up to wait for the [`Completion`] to be 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>,
|
||||
/// #[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>,
|
||||
}
|
||||
|
||||
// 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 {}
|
||||
|
||||
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, i.e. signals all current and future waiters.
|
||||
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
|
||||
/// timeout.
|
||||
///
|
||||
/// See also [`Completion::complete_all`].
|
||||
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()) };
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user