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