Something went wrong. Try again.
Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115// 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. #[inline] 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`]. #[inline] 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()) }; }}