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