File Index
Files and directories
Sign in
FILE

completion.rs

File preview with syntax highlighting.

linux-6.19.14/rust/kernel/sync/completion.rs RUST
  1// SPDX-License-Identifier: GPL-2.0
  2
  3//! Completion support.
  4//!
  5//! Reference: <https://docs.kernel.org/scheduler/completion.html>
  6//!
  7//! C header: [`include/linux/completion.h`](srctree/include/linux/completion.h)
  8
  9use crate::{bindings, prelude::*, types::Opaque};
 10
 11/// Synchronization primitive to signal when a certain task has been completed.
 12///
 13/// The [`Completion`] synchronization primitive signals when a certain task has been completed by
 14/// waking up other tasks that have been queued up to wait for the [`Completion`] to be completed.
 15///
 16/// # Examples
 17///
 18/// ```
 19/// use kernel::sync::{Arc, Completion};
 20/// use kernel::workqueue::{self, impl_has_work, new_work, Work, WorkItem};
 21///
 22/// #[pin_data]
 23/// struct MyTask {
 24///     #[pin]
 25///     work: Work<MyTask>,
 26///     #[pin]
 27///     done: Completion,
 28/// }
 29///
 30/// impl_has_work! {
 31///     impl HasWork<Self> for MyTask { self.work }
 32/// }
 33///
 34/// impl MyTask {
 35///     fn new() -> Result<Arc<Self>> {
 36///         let this = Arc::pin_init(pin_init!(MyTask {
 37///             work <- new_work!("MyTask::work"),
 38///             done <- Completion::new(),
 39///         }), GFP_KERNEL)?;
 40///
 41///         let _ = workqueue::system().enqueue(this.clone());
 42///
 43///         Ok(this)
 44///     }
 45///
 46///     fn wait_for_completion(&self) {
 47///         self.done.wait_for_completion();
 48///
 49///         pr_info!("Completion: task complete\n");
 50///     }
 51/// }
 52///
 53/// impl WorkItem for MyTask {
 54///     type Pointer = Arc<MyTask>;
 55///
 56///     fn run(this: Arc<MyTask>) {
 57///         // process this task
 58///         this.done.complete_all();
 59///     }
 60/// }
 61///
 62/// let task = MyTask::new()?;
 63/// task.wait_for_completion();
 64/// # Ok::<(), Error>(())
 65/// ```
 66#[pin_data]
 67pub struct Completion {
 68    #[pin]
 69    inner: Opaque<bindings::completion>,
 70}
 71
 72// SAFETY: `Completion` is safe to be send to any task.
 73unsafe impl Send for Completion {}
 74
 75// SAFETY: `Completion` is safe to be accessed concurrently.
 76unsafe impl Sync for Completion {}
 77
 78impl Completion {
 79    /// Create an initializer for a new [`Completion`].
 80    pub fn new() -> impl PinInit<Self> {
 81        pin_init!(Self {
 82            inner <- Opaque::ffi_init(|slot: *mut bindings::completion| {
 83                // SAFETY: `slot` is a valid pointer to an uninitialized `struct completion`.
 84                unsafe { bindings::init_completion(slot) };
 85            }),
 86        })
 87    }
 88
 89    fn as_raw(&self) -> *mut bindings::completion {
 90        self.inner.get()
 91    }
 92
 93    /// Signal all tasks waiting on this completion.
 94    ///
 95    /// This method wakes up all tasks waiting on this completion; after this operation the
 96    /// completion is permanently done, i.e. signals all current and future waiters.
 97    pub fn complete_all(&self) {
 98        // SAFETY: `self.as_raw()` is a pointer to a valid `struct completion`.
 99        unsafe { bindings::complete_all(self.as_raw()) };
100    }
101
102    /// Wait for completion of a task.
103    ///
104    /// This method waits for the completion of a task; it is not interruptible and there is no
105    /// timeout.
106    ///
107    /// See also [`Completion::complete_all`].
108    pub fn wait_for_completion(&self) {
109        // SAFETY: `self.as_raw()` is a pointer to a valid `struct completion`.
110        unsafe { bindings::wait_for_completion(self.as_raw()) };
111    }
112}
~/ Read-only file preview.