1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// SPDX-License-Identifier: GPL-2.0
//! Completion support.
//!
//! Reference: <https://docs.kernel.org/scheduler/completion.html>
//!
//! C header: [`include/linux/completion.h`](srctree/include/linux/completion.h)
use crate::;
/// Synchronization primitive to signal when a certain task has been completed.
///
/// The [`Completion`] synchronization primitive signals when a certain task has been completed by
/// waking up other tasks that have been queued up to wait for the [`Completion`] to be completed.
///
/// # Examples
///
/// ```
/// use kernel::sync::{Arc, Completion};
/// use kernel::workqueue::{self, impl_has_work, new_work, Work, WorkItem};
///
/// #[pin_data]
/// struct MyTask {
/// #[pin]
/// work: Work<MyTask>,
/// #[pin]
/// done: Completion,
/// }
///
/// impl_has_work! {
/// impl HasWork<Self> for MyTask { self.work }
/// }
///
/// impl MyTask {
/// fn new() -> Result<Arc<Self>> {
/// let this = Arc::pin_init(pin_init!(MyTask {
/// work <- new_work!("MyTask::work"),
/// done <- Completion::new(),
/// }), GFP_KERNEL)?;
///
/// let _ = workqueue::system().enqueue(this.clone());
///
/// Ok(this)
/// }
///
/// fn wait_for_completion(&self) {
/// self.done.wait_for_completion();
///
/// pr_info!("Completion: task complete\n");
/// }
/// }
///
/// impl WorkItem for MyTask {
/// type Pointer = Arc<MyTask>;
///
/// fn run(this: Arc<MyTask>) {
/// // process this task
/// this.done.complete_all();
/// }
/// }
///
/// let task = MyTask::new()?;
/// task.wait_for_completion();
/// # Ok::<(), Error>(())
/// ```
// SAFETY: `Completion` is safe to be send to any task.
unsafe
// SAFETY: `Completion` is safe to be accessed concurrently.
unsafe