osal_rs/freertos/
mutex.rs1use core::cell::UnsafeCell;
21use core::fmt::{Debug, Display, Formatter};
22use core::ops::{Deref, DerefMut};
23use core::marker::PhantomData;
24
25use alloc::sync::Arc;
26
27use super::ffi::{MutexHandle, pdFALSE, pdTRUE};
28use super::system::System;
29use crate::traits::SystemFn;
30use crate::traits::{MutexGuardFn, RawMutexFn, MutexFn, ToTick};
31use crate::utils::{Result, Error, OsalRsBool, MAX_DELAY};
32use crate::{vSemaphoreDelete, xSemaphoreCreateRecursiveMutex, xSemaphoreGiveFromISR, xSemaphoreGiveRecursive, xSemaphoreTake, xSemaphoreTakeFromISR, xSemaphoreTakeRecursive};
33
34
35struct RawMutex(MutexHandle);
36
37unsafe impl Send for RawMutex {}
38unsafe impl Sync for RawMutex {}
39
40impl RawMutexFn for RawMutex {
41 fn new() -> Result<Self> {
42 let handle = xSemaphoreCreateRecursiveMutex!();
43 if handle.is_null() {
44 Err(Error::OutOfMemory)
45 } else {
46 Ok(RawMutex(handle))
47 }
48 }
49
50 fn lock(&self) -> OsalRsBool {
51 let res = xSemaphoreTakeRecursive!(self.0, MAX_DELAY.to_ticks());
52 if res == pdTRUE {
53 OsalRsBool::True
54 } else {
55 OsalRsBool::False
56 }
57 }
58
59 fn lock_from_isr(&self) -> OsalRsBool {
60 let mut higher_priority_task_woken = pdFALSE;
61 let res = xSemaphoreTakeFromISR!(self.0, &mut higher_priority_task_woken);
62 if res == pdTRUE {
63
64 System::yield_from_isr(higher_priority_task_woken);
65
66 OsalRsBool::True
67 } else {
68 OsalRsBool::False
69 }
70 }
71
72 fn unlock(&self) -> OsalRsBool {
73 let res = xSemaphoreGiveRecursive!(self.0);
74 if res == pdTRUE {
75 OsalRsBool::True
76 } else {
77 OsalRsBool::False
78 }
79 }
80
81
82 fn unlock_from_isr(&self) -> OsalRsBool {
83 let mut higher_priority_task_woken = pdFALSE;
84 let res = xSemaphoreGiveFromISR!(self.0, &mut higher_priority_task_woken);
85 if res == pdTRUE {
86
87 System::yield_from_isr(higher_priority_task_woken);
88
89 OsalRsBool::True
90 } else {
91 OsalRsBool::False
92 }
93 }
94
95 fn delete(&mut self) {
96 vSemaphoreDelete!(self.0);
97 self.0 = core::ptr::null();
98 }
99}
100
101impl Drop for RawMutex {
102 fn drop(&mut self) {
103 if self.0.is_null() {
104 return;
105 }
106 self.delete();
107 }
108}
109
110impl Deref for RawMutex {
111 type Target = MutexHandle;
112
113 fn deref(&self) -> &MutexHandle {
114 &self.0
115 }
116}
117
118
119impl Debug for RawMutex {
120 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
121 f.debug_struct("RawMutex")
122 .field("handle", &self.0)
123 .finish()
124 }
125}
126
127impl Display for RawMutex {
128 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
129 write!(f, "RawMutex {{ handle: {:?} }}", self.0)
130 }
131}
132
133pub struct Mutex<T: ?Sized> {
134 inner: RawMutex,
135 data: UnsafeCell<T>
136}
137
138
139unsafe impl<T: ?Sized + Send> Send for Mutex<T> {}
140unsafe impl<T: ?Sized + Send> Sync for Mutex<T> {}
141
142impl<T: ?Sized> MutexFn<T> for Mutex<T> {
143 type Guard<'a> = MutexGuard<'a, T> where Self: 'a, T: 'a;
144 type GuardFromIsr<'a> = MutexGuardFromIsr<'a, T> where Self: 'a, T: 'a;
145
146 fn new(data: T) -> Self
147 where
148 T: Sized
149 {
150 Self {
151 inner: RawMutex::new().unwrap(),
152 data: UnsafeCell::new(data),
153 }
154 }
155
156 fn lock(&self) -> Result<Self::Guard<'_>> {
157 match self.inner.lock() {
158 OsalRsBool::True => Ok(MutexGuard {
159 mutex: self,
160 _phantom: PhantomData,
161 }),
162 OsalRsBool::False => Err(Error::MutexLockFailed),
163 }
164 }
165
166 fn lock_from_isr(&self) -> Result<Self::GuardFromIsr<'_>> {
167 match self.inner.lock_from_isr() {
168 OsalRsBool::True => Ok(MutexGuardFromIsr {
169 mutex: self,
170 _phantom: PhantomData,
171 }),
172 OsalRsBool::False => Err(Error::MutexLockFailed),
173 }
174 }
175
176 fn into_inner(self) -> Result<T>
177 where
178 Self: Sized,
179 T: Sized
180 {
181 Ok(self.data.into_inner())
182 }
183
184 fn get_mut(&mut self) -> &mut T {
185 self.data.get_mut()
186 }
187}
188
189impl<T: ?Sized> Mutex<T> {
190 pub fn lock_from_isr_explicit(&self) -> Result<MutexGuardFromIsr<'_, T>> {
192 match self.inner.lock_from_isr() {
193 OsalRsBool::True => Ok(MutexGuardFromIsr {
194 mutex: self,
195 _phantom: PhantomData,
196 }),
197 OsalRsBool::False => Err(Error::MutexLockFailed),
198 }
199 }
200}
201
202impl<T> Mutex<T> {
203 pub fn new_arc(data: T) -> Arc<Self> {
212 Arc::new(Self::new(data))
213 }
214}
215
216impl<T> Debug for Mutex<T>
217where
218 T: ?Sized {
219 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
220 f.debug_struct("Mutex")
221 .field("inner", &self.inner)
222 .finish()
223 }
224}
225
226impl<T> Display for Mutex<T>
227where
228 T: ?Sized {
229 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
230 write!(f, "Mutex {{ inner: {} }}", self.inner)
231 }
232}
233
234pub struct MutexGuard<'a, T: ?Sized + 'a> {
236 mutex: &'a Mutex<T>,
237 _phantom: PhantomData<&'a mut T>,
238}
239
240impl<'a, T: ?Sized> Deref for MutexGuard<'a, T> {
241 type Target = T;
242
243 fn deref(&self) -> &T {
244 unsafe { &*self.mutex.data.get() }
245 }
246}
247
248impl<'a, T: ?Sized> DerefMut for MutexGuard<'a, T> {
249 fn deref_mut(&mut self) -> &mut T {
250 unsafe { &mut *self.mutex.data.get() }
251 }
252}
253
254impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> {
255 fn drop(&mut self) {
256 self.mutex.inner.unlock();
257 }
258}
259
260impl<'a, T: ?Sized> MutexGuardFn<'a, T> for MutexGuard<'a, T> {}
261
262pub struct MutexGuardFromIsr<'a, T: ?Sized + 'a> {
263 mutex: &'a Mutex<T>,
264 _phantom: PhantomData<&'a mut T>,
265}
266
267impl<'a, T: ?Sized> Deref for MutexGuardFromIsr<'a, T> {
268 type Target = T;
269
270 fn deref(&self) -> &T {
271 unsafe { &*self.mutex.data.get() }
272 }
273}
274
275impl<'a, T: ?Sized> DerefMut for MutexGuardFromIsr<'a, T> {
276 fn deref_mut(&mut self) -> &mut T {
277 unsafe { &mut *self.mutex.data.get() }
278 }
279}
280
281impl<'a, T: ?Sized> Drop for MutexGuardFromIsr<'a, T> {
282 fn drop(&mut self) {
283 self.mutex.inner.unlock_from_isr();
284 }
285}
286
287impl<'a, T: ?Sized> MutexGuardFn<'a, T> for MutexGuardFromIsr<'a, T> {}