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