Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rust: completion: implement initial abstraction

Implement a minimal abstraction for the completion synchronization
primitive.

This initial abstraction only adds complete_all() and
wait_for_completion(), since that is what is required for the subsequent
Devres patch.

Cc: Ingo Molnar <mingo@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Juri Lelli <juri.lelli@redhat.com>
Cc: Vincent Guittot <vincent.guittot@linaro.org>
Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Ben Segall <bsegall@google.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Valentin Schneider <vschneid@redhat.com>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Boqun Feng <boqun.feng@gmail.com>
Reviewed-by: Benno Lossin <lossin@kernel.org>
Acked-by: Miguel Ojeda <ojeda@kernel.org>
Link: https://lore.kernel.org/r/20250612121817.1621-2-dakr@kernel.org
Signed-off-by: Danilo Krummrich <dakr@kernel.org>

+124
+1
rust/bindings/bindings_helper.h
··· 39 39 #include <linux/blk_types.h> 40 40 #include <linux/blkdev.h> 41 41 #include <linux/clk.h> 42 + #include <linux/completion.h> 42 43 #include <linux/configfs.h> 43 44 #include <linux/cpu.h> 44 45 #include <linux/cpufreq.h>
+8
rust/helpers/completion.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/completion.h> 4 + 5 + void rust_helper_init_completion(struct completion *x) 6 + { 7 + init_completion(x); 8 + }
+1
rust/helpers/helpers.c
··· 13 13 #include "build_assert.c" 14 14 #include "build_bug.c" 15 15 #include "clk.c" 16 + #include "completion.c" 16 17 #include "cpufreq.c" 17 18 #include "cpumask.c" 18 19 #include "cred.c"
+2
rust/kernel/sync.rs
··· 10 10 use pin_init; 11 11 12 12 mod arc; 13 + pub mod completion; 13 14 mod condvar; 14 15 pub mod lock; 15 16 mod locked_by; ··· 18 17 pub mod rcu; 19 18 20 19 pub use arc::{Arc, ArcBorrow, UniqueArc}; 20 + pub use completion::Completion; 21 21 pub use condvar::{new_condvar, CondVar, CondVarTimeoutResult}; 22 22 pub use lock::global::{global_lock, GlobalGuard, GlobalLock, GlobalLockBackend, GlobalLockedBy}; 23 23 pub use lock::mutex::{new_mutex, Mutex, MutexGuard};
+112
rust/kernel/sync/completion.rs
··· 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`]. 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 + }