|
13 | 13 | // See the License for the specific language governing permissions and
|
14 | 14 | // limitations under the License.
|
15 | 15 |
|
16 |
| -use core::option::{None, Some}; |
17 |
| -use core::ty::Unsafe; |
18 |
| -use core::kinds::marker; |
19 |
| -use core::kinds::Share; |
| 16 | +//! Condition variables |
20 | 17 |
|
21 |
| -use hal::cortex_m3::sched::NoInterrupts; |
22 |
| -use util::queue::{Queue, Node}; |
23 |
| -use os::task::{TaskDescriptor, Tasks}; |
| 18 | +pub use os::cond_var::internal::{CondVar, COND_VAR_INIT}; |
24 | 19 |
|
25 |
| -pub struct CondVar { |
26 |
| - waiting: Queue<*mut TaskDescriptor> |
27 |
| -} |
| 20 | +#[cfg(multitasking)] |
| 21 | +mod internal { |
| 22 | + use core::option::{None, Some}; |
| 23 | + use core::ty::Unsafe; |
| 24 | + use core::kinds::marker; |
| 25 | + use core::kinds::Share; |
28 | 26 |
|
29 |
| -pub static COND_VAR_INIT: CondVar = CondVar { |
30 |
| - waiting: Queue { |
31 |
| - head: Unsafe { value: 0 as *mut Node<*mut TaskDescriptor>, marker1: marker::InvariantType }, |
32 |
| - tail: Unsafe { value: 0 as *mut Node<*mut TaskDescriptor>, marker1: marker::InvariantType }, |
33 |
| - } |
34 |
| -}; |
| 27 | + use hal::cortex_m3::sched::NoInterrupts; |
| 28 | + use util::queue::{Queue, Node}; |
| 29 | + use os::task::{TaskDescriptor, Tasks}; |
35 | 30 |
|
36 |
| -impl CondVar { |
37 |
| - pub fn new() -> CondVar { |
38 |
| - CondVar { waiting: Queue::new() } |
| 31 | + /// A condition variable |
| 32 | + pub struct CondVar { |
| 33 | + waiting: Queue<*mut TaskDescriptor> |
39 | 34 | }
|
40 | 35 |
|
41 |
| - /// Wait on a condition variable. |
42 |
| - pub fn wait<'a>(&'a self) { |
43 |
| - /* |
44 |
| - * The signalling thread is responsible for removing the waiting |
45 |
| - * thread which ensures that a signal wakes up exactly one thread |
46 |
| - * whenever there is one waiting. |
47 |
| - */ |
48 |
| - unsafe { |
49 |
| - let crit = NoInterrupts::new(); |
50 |
| - let mut waiting = Node::new(Tasks.current_task() as *mut TaskDescriptor); |
51 |
| - self.waiting.push(&mut waiting, &crit); |
52 |
| - Tasks.current_task().block(crit); |
| 36 | + /// Static initializer |
| 37 | + pub const COND_VAR_INIT: CondVar = CondVar { |
| 38 | + waiting: Queue { |
| 39 | + head: Unsafe { value: 0 as *mut Node<*mut TaskDescriptor>, marker1: marker::InvariantType }, |
| 40 | + tail: Unsafe { value: 0 as *mut Node<*mut TaskDescriptor>, marker1: marker::InvariantType }, |
| 41 | + } |
| 42 | + }; |
| 43 | + |
| 44 | + impl CondVar { |
| 45 | + /// Create a new condition variable |
| 46 | + pub fn new() -> CondVar { |
| 47 | + CondVar { waiting: Queue::new() } |
53 | 48 | }
|
54 |
| - } |
55 | 49 |
|
56 |
| - /// Wake up a thread waiting on a condition variable. |
57 |
| - pub fn signal<'a>(&'a self) { |
58 |
| - unsafe { |
59 |
| - let crit = NoInterrupts::new(); |
60 |
| - match self.waiting.pop(&crit) { |
61 |
| - None => { }, |
62 |
| - Some(task) => (*(*task).data).unblock(&crit) |
| 50 | + /// Wait on a condition variable. |
| 51 | + pub fn wait(&self) { |
| 52 | + /* |
| 53 | + * The signalling thread is responsible for removing the waiting |
| 54 | + * thread which ensures that a signal wakes up exactly one thread |
| 55 | + * whenever there is one waiting. |
| 56 | + */ |
| 57 | + unsafe { |
| 58 | + let crit = NoInterrupts::new(); |
| 59 | + let mut waiting = Node::new(Tasks.current_task() as *mut TaskDescriptor); |
| 60 | + self.waiting.push(&mut waiting, &crit); |
| 61 | + Tasks.current_task().block(crit); |
63 | 62 | }
|
64 | 63 | }
|
65 |
| - } |
66 | 64 |
|
67 |
| - /// Wake up all threads waiting on a condition variable. |
68 |
| - pub fn broadcast<'a>(&'a self) { |
69 |
| - unsafe { |
70 |
| - let crit = NoInterrupts::new(); |
71 |
| - loop { |
| 65 | + /// Wake up a thread waiting on a condition variable. |
| 66 | + pub fn signal(&self) { |
| 67 | + unsafe { |
| 68 | + let crit = NoInterrupts::new(); |
72 | 69 | match self.waiting.pop(&crit) {
|
73 |
| - None => break, |
| 70 | + None => { }, |
74 | 71 | Some(task) => (*(*task).data).unblock(&crit)
|
75 | 72 | }
|
76 | 73 | }
|
77 | 74 | }
|
| 75 | + |
| 76 | + /// Wake up all threads waiting on a condition variable. |
| 77 | + pub fn broadcast(&self) { |
| 78 | + unsafe { |
| 79 | + let crit = NoInterrupts::new(); |
| 80 | + loop { |
| 81 | + match self.waiting.pop(&crit) { |
| 82 | + None => break, |
| 83 | + Some(task) => (*(*task).data).unblock(&crit) |
| 84 | + } |
| 85 | + } |
| 86 | + } |
| 87 | + } |
78 | 88 | }
|
| 89 | + |
| 90 | + impl Share for CondVar {} |
79 | 91 | }
|
80 | 92 |
|
81 |
| -impl Share for CondVar {} |
| 93 | +#[cfg(not(multitasking))] |
| 94 | +mod internal { |
| 95 | + use core::kinds::marker; |
| 96 | + use core::kinds::Share; |
| 97 | + use core::cell::UnsafeCell; |
| 98 | + |
| 99 | + /// A condition variable |
| 100 | + pub struct CondVar { |
| 101 | + waiting: UnsafeCell<bool>, |
| 102 | + nocopy: marker::NoCopy |
| 103 | + } |
| 104 | + |
| 105 | + /// Static initializer |
| 106 | + pub const COND_VAR_INIT: CondVar = CondVar { |
| 107 | + waiting: UnsafeCell { value: false }, |
| 108 | + nocopy: marker::NoCopy, |
| 109 | + }; |
| 110 | + |
| 111 | + impl CondVar { |
| 112 | + /// Create a new condition variable |
| 113 | + pub fn new() -> CondVar { |
| 114 | + CondVar { |
| 115 | + waiting: UnsafeCell::new(false), |
| 116 | + nocopy: marker::NoCopy, |
| 117 | + } |
| 118 | + } |
| 119 | + |
| 120 | + /// Wait on a condition variable. |
| 121 | + pub fn wait(&self) { |
| 122 | + unsafe { |
| 123 | + while *self.waiting.get() { |
| 124 | + asm!("wfi") |
| 125 | + } |
| 126 | + } |
| 127 | + } |
| 128 | + |
| 129 | + /// Wake up a thread waiting on a condition variable. |
| 130 | + pub fn signal(&self) { |
| 131 | + unsafe { |
| 132 | + *self.waiting.get() = true; |
| 133 | + } |
| 134 | + } |
| 135 | + |
| 136 | + /// Wake up all threads waiting on a condition variable. |
| 137 | + pub fn broadcast(&self) { |
| 138 | + self.signal(); |
| 139 | + } |
| 140 | + } |
| 141 | + |
| 142 | + impl Share for CondVar {} |
| 143 | +} |
0 commit comments