1use crate::base::*;
2use crate::base_type::v1::*;
3use crate::shim::*;
4use crate::units::*;
5
6pub type Mutex<T> = MutexImpl<T, MutexNormal>;
7pub type RecursiveMutex<T> = MutexImpl<T, MutexRecursive>;
8
9unsafe impl<T: Send, M> Send for MutexImpl<T, M> {}
10
11unsafe impl<T: Send, M> Sync for MutexImpl<T, M> {}
12
13pub struct MutexImpl<T: ?Sized, M> {
16 mutex: M,
17 data: UnsafeCell<T>,
18}
19
20impl<T: ?Sized, M> fmt::Debug for MutexImpl<T, M>
21where
22 M: MutexInnerImpl + fmt::Debug,
23{
24 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
25 write!(f, "Mutex address: {:?}", self.mutex)
26 }
27}
28
29impl<T, M> MutexImpl<T, M>
30where
31 M: MutexInnerImpl,
32{
33 pub fn new(value: T) -> Result<Self, FreeRtosError> {
35 Ok(Self::from_parts(M::create()?, value))
36 }
37
38 pub fn lock<D: DurationTicks>(
40 &self,
41 max_wait: D,
42 ) -> Result<MutexGuard<'_, T, M>, FreeRtosError> {
43 self.mutex.take(max_wait)?;
44
45 Ok(MutexGuard {
46 __mutex: &self.mutex,
47 __data: &self.data,
48 })
49 }
50
51 pub fn into_inner(self) -> T {
53 self.into_parts().1
54 }
55
56 pub fn get_mut(&mut self) -> &mut T {
60 self.data.get_mut()
61 }
62
63 pub fn from_parts(mutex: M, value: T) -> Self {
67 Self {
68 mutex,
69 data: UnsafeCell::new(value),
70 }
71 }
72
73 pub fn into_parts(self) -> (M, T) {
75 (self.mutex, self.data.into_inner())
76 }
77
78 pub fn inner_mutex_mut(&mut self) -> &mut M {
80 &mut self.mutex
81 }
82}
83
84pub struct MutexGuard<'a, T: ?Sized + 'a, M: 'a>
86where
87 M: MutexInnerImpl,
88{
89 __mutex: &'a M,
90 __data: &'a UnsafeCell<T>,
91}
92
93impl<'mutex, T: ?Sized, M> Deref for MutexGuard<'mutex, T, M>
94where
95 M: MutexInnerImpl,
96{
97 type Target = T;
98
99 fn deref<'a>(&'a self) -> &'a T {
100 unsafe { &*self.__data.get() }
101 }
102}
103
104impl<'mutex, T: ?Sized, M> DerefMut for MutexGuard<'mutex, T, M>
105where
106 M: MutexInnerImpl,
107{
108 fn deref_mut<'a>(&'a mut self) -> &'a mut T {
109 unsafe { &mut *self.__data.get() }
110 }
111}
112
113impl<'a, T: ?Sized, M> Drop for MutexGuard<'a, T, M>
114where
115 M: MutexInnerImpl,
116{
117 fn drop(&mut self) {
118 self.__mutex.give();
119 }
120}
121
122pub trait MutexInnerImpl
123where
124 Self: Sized,
125{
126 fn create() -> Result<Self, FreeRtosError>;
127 fn take<D: DurationTicks>(&self, max_wait: D) -> Result<(), FreeRtosError>;
128 fn give(&self);
129
130 unsafe fn from_raw_handle(handle: FreeRtosSemaphoreHandle) -> Self;
137 fn raw_handle(&self) -> FreeRtosSemaphoreHandle;
138}
139
140pub struct MutexNormal(FreeRtosSemaphoreHandle);
141
142impl MutexInnerImpl for MutexNormal {
143 fn create() -> Result<Self, FreeRtosError> {
144 let m = unsafe { freertos_rs_create_mutex() };
145 if m == 0 as *const _ {
146 return Err(FreeRtosError::OutOfMemory);
147 }
148 Ok(MutexNormal(m))
149 }
150
151 fn take<D: DurationTicks>(&self, max_wait: D) -> Result<(), FreeRtosError> {
152 let res = unsafe { freertos_rs_take_semaphore(self.0, max_wait.to_ticks()) };
153
154 if res != 0 {
155 return Err(FreeRtosError::MutexTimeout);
156 }
157
158 Ok(())
159 }
160
161 fn give(&self) {
162 unsafe {
163 freertos_rs_give_semaphore(self.0);
164 }
165 }
166
167 #[inline]
168 unsafe fn from_raw_handle(handle: FreeRtosSemaphoreHandle) -> Self {
169 Self(handle)
170 }
171
172 #[inline]
173 fn raw_handle(&self) -> FreeRtosSemaphoreHandle {
174 self.0
175 }
176}
177
178impl Drop for MutexNormal {
179 fn drop(&mut self) {
180 unsafe { freertos_rs_delete_semaphore(self.0) }
181 }
182}
183
184impl fmt::Debug for MutexNormal {
185 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
186 write!(f, "{:?}", self.0)
187 }
188}
189
190pub struct MutexRecursive(FreeRtosSemaphoreHandle);
191
192#[cfg(feature = "recursive-mutex")]
193impl MutexInnerImpl for MutexRecursive {
194 fn create() -> Result<Self, FreeRtosError> {
195 let m = unsafe { freertos_rs_create_recursive_mutex() };
196 if m == 0 as *const _ {
197 return Err(FreeRtosError::OutOfMemory);
198 }
199 Ok(MutexRecursive(m))
200 }
201
202 fn take<D: DurationTicks>(&self, max_wait: D) -> Result<(), FreeRtosError> {
203 let res = unsafe { freertos_rs_take_recursive_semaphore(self.0, max_wait.to_ticks()) };
204
205 if res != 0 {
206 return Err(FreeRtosError::MutexTimeout);
207 }
208
209 Ok(())
210 }
211
212 fn give(&self) {
213 unsafe {
214 freertos_rs_give_recursive_semaphore(self.0);
215 }
216 }
217
218 #[inline]
219 unsafe fn from_raw_handle(handle: FreeRtosSemaphoreHandle) -> Self {
220 Self(handle)
221 }
222
223 #[inline]
224 fn raw_handle(&self) -> FreeRtosSemaphoreHandle {
225 self.0
226 }
227}
228
229#[cfg(feature = "recursive-mutex")]
230impl Drop for MutexRecursive {
231 fn drop(&mut self) {
232 unsafe { freertos_rs_delete_semaphore(self.0) }
233 }
234}
235
236impl fmt::Debug for MutexRecursive {
237 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
238 write!(f, "{:?}", self.0)
239 }
240}
241
242use mutex_traits::{ConstInit, RawMutex};
243pub struct FreeRtosRawMutex {
245 inner: UnsafeCell<FreeRtosSemaphoreHandle>,
246}
247
248impl FreeRtosRawMutex {
249 pub const fn empty() -> Self {
251 Self {
252 inner: UnsafeCell::new(core::ptr::null()),
253 }
254 }
255
256 fn get_inner(&self) -> &FreeRtosSemaphoreHandle {
257 let inner = unsafe { &mut *self.inner.get() };
258 if (*inner).is_null() {
259 critical_section::with(|_| {
260 if (*inner).is_null() {
261 let m = unsafe { freertos_rs_create_mutex() };
262 if m.is_null() {
263 panic!();
264 }
265 *inner = m;
266 }
267 });
268 }
269 inner
270 }
271
272 #[inline]
273 fn try_lock_block(&self, block: bool) -> bool {
274 let t = if block {
275 FreeRtosTimeUnitsShimmed::get_max_wait()
276 } else {
277 0
278 };
279 let res = unsafe { freertos_rs_take_semaphore(*self.get_inner(), t) };
280 res == 0
281 }
282}
283
284unsafe impl Send for FreeRtosRawMutex {}
285
286impl ConstInit for FreeRtosRawMutex {
287 const INIT: Self = Self::empty();
288}
289
290unsafe impl RawMutex for FreeRtosRawMutex {
291 type GuardMarker = *mut ();
292
293 #[inline]
294 fn lock(&self) {
295 if !self.try_lock() {
296 panic!("Deadlocked");
297 }
298 }
299
300 #[inline]
301 fn try_lock(&self) -> bool {
302 self.try_lock_block(true)
303 }
304
305 #[inline]
306 unsafe fn unlock(&self) {
307 unsafe {
308 freertos_rs_give_semaphore(*self.get_inner());
309 }
310 }
311
312 #[inline]
313 fn is_locked(&self) -> bool {
314 if self.try_lock_block(false) {
315 unsafe {
316 self.unlock();
317 }
318 false
319 } else {
320 true
321 }
322 }
323}
324
325impl Drop for FreeRtosRawMutex {
326 fn drop(&mut self) {
327 unsafe { freertos_rs_delete_semaphore(*self.get_inner()) }
328 }
329}