xref: /linux/rust/kernel/sync/completion.rs (revision 229f135e0680da3dd0bcce515c07be87858f1d12)
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 
9 use 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]
67 pub struct Completion {
68     #[pin]
69     inner: Opaque<bindings::completion>,
70 }
71 
72 // SAFETY: `Completion` is safe to be send to any task.
73 unsafe impl Send for Completion {}
74 
75 // SAFETY: `Completion` is safe to be accessed concurrently.
76 unsafe impl Sync for Completion {}
77 
78 impl Completion {
79     /// Create an initializer for a new [`Completion`].
new() -> impl PinInit<Self>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 
as_raw(&self) -> *mut bindings::completion89     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.
complete_all(&self)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`].
wait_for_completion(&self)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 }
113