freertos_rust/
mutex.rs

1use crate::base::*;
2use crate::prelude::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
13/// Mutual exclusion access to a contained value. Can be recursive -
14/// the current owner of a lock can re-lock it.
15pub 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    /// Create a new mutex with the given inner value
34    pub fn new(value: T) -> Result<Self, FreeRtosError> {
35        Ok(Self::from_parts(M::create()?, value))
36    }
37
38    /// Try to obtain a lock and mutable access to our inner value
39    pub fn lock<D: DurationTicks>(&self, max_wait: D) -> Result<MutexGuard<'_, T, M>, FreeRtosError> {
40        self.mutex.take(max_wait)?;
41
42        Ok(MutexGuard {
43            __mutex: &self.mutex,
44            __data: &self.data,
45        })
46    }
47
48    /// Consume the mutex and return its inner value
49    pub fn into_inner(self) -> T {
50        self.into_parts().1
51    }
52
53    /// Get mutable reference to inner value.
54    ///
55    /// This method does not lock the mutex because mutable reference guarantees exclusive access.
56    pub fn get_mut(&mut self) -> &mut T {
57        self.data.get_mut()
58    }
59
60    /// Create owning mutex from non-owning mutex and inner value.
61    ///
62    /// It is safe to pass an already locked `mutex` although it is not recommended.
63    pub fn from_parts(mutex: M, value: T) -> Self {
64        Self {
65            mutex,
66            data: UnsafeCell::new(value),
67        }
68    }
69
70    /// Split owning mutex into non-owning mutex and inner value.
71    pub fn into_parts(self) -> (M, T) {
72        (self.mutex, self.data.into_inner())
73    }
74
75    /// Get mutable reference to inner non-owning mutex.
76    pub fn inner_mutex_mut(&mut self) -> &mut M {
77        &mut self.mutex
78    }
79}
80
81/// Holds the mutex until we are dropped
82pub struct MutexGuard<'a, T: ?Sized + 'a, M: 'a>
83where
84    M: MutexInnerImpl,
85{
86    __mutex: &'a M,
87    __data: &'a UnsafeCell<T>,
88}
89
90impl<'mutex, T: ?Sized, M> Deref for MutexGuard<'mutex, T, M>
91where
92    M: MutexInnerImpl,
93{
94    type Target = T;
95
96    fn deref<'a>(&'a self) -> &'a T {
97        unsafe { &*self.__data.get() }
98    }
99}
100
101impl<'mutex, T: ?Sized, M> DerefMut for MutexGuard<'mutex, T, M>
102where
103    M: MutexInnerImpl,
104{
105    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
106        unsafe { &mut *self.__data.get() }
107    }
108}
109
110impl<'a, T: ?Sized, M> Drop for MutexGuard<'a, T, M>
111where
112    M: MutexInnerImpl,
113{
114    fn drop(&mut self) {
115        self.__mutex.give();
116    }
117}
118
119pub trait MutexInnerImpl
120where
121    Self: Sized,
122{
123    fn create() -> Result<Self, FreeRtosError>;
124    fn take<D: DurationTicks>(&self, max_wait: D) -> Result<(), FreeRtosError>;
125    fn give(&self);
126
127    /// # Safety
128    ///
129    /// `handle` must be a valid FreeRTOS mutex handle.
130    ///
131    /// The type of `handle` (normal or recursive mutex) must match the type
132    /// of instance being created ([`MutexNormal`] or [`MutexRecursive`] respectively).
133    unsafe fn from_raw_handle(handle: FreeRtosSemaphoreHandle) -> Self;
134    fn raw_handle(&self) -> FreeRtosSemaphoreHandle;
135}
136
137pub struct MutexNormal(FreeRtosSemaphoreHandle);
138
139impl MutexInnerImpl for MutexNormal {
140    fn create() -> Result<Self, FreeRtosError> {
141        let m = unsafe { freertos_rs_create_mutex() };
142        if m == 0 as *const _ {
143            return Err(FreeRtosError::OutOfMemory);
144        }
145        Ok(MutexNormal(m))
146    }
147
148    fn take<D: DurationTicks>(&self, max_wait: D) -> Result<(), FreeRtosError> {
149        let res = unsafe { freertos_rs_take_semaphore(self.0, max_wait.to_ticks()) };
150
151        if res != 0 {
152            return Err(FreeRtosError::MutexTimeout);
153        }
154
155        Ok(())
156    }
157
158    fn give(&self) {
159        unsafe {
160            freertos_rs_give_semaphore(self.0);
161        }
162    }
163
164    #[inline]
165    unsafe fn from_raw_handle(handle: FreeRtosSemaphoreHandle) -> Self {
166        Self(handle)
167    }
168
169    #[inline]
170    fn raw_handle(&self) -> FreeRtosSemaphoreHandle {
171        self.0
172    }
173}
174
175impl Drop for MutexNormal {
176    fn drop(&mut self) {
177        unsafe { freertos_rs_delete_semaphore(self.0) }
178    }
179}
180
181impl fmt::Debug for MutexNormal {
182    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
183        write!(f, "{:?}", self.0)
184    }
185}
186
187pub struct MutexRecursive(FreeRtosSemaphoreHandle);
188
189impl MutexInnerImpl for MutexRecursive {
190    fn create() -> Result<Self, FreeRtosError> {
191        let m = unsafe { freertos_rs_create_recursive_mutex() };
192        if m == 0 as *const _ {
193            return Err(FreeRtosError::OutOfMemory);
194        }
195        Ok(MutexRecursive(m))
196    }
197
198    fn take<D: DurationTicks>(&self, max_wait: D) -> Result<(), FreeRtosError> {
199        let res = unsafe { freertos_rs_take_recursive_semaphore(self.0, max_wait.to_ticks()) };
200
201        if res != 0 {
202            return Err(FreeRtosError::MutexTimeout);
203        }
204
205        Ok(())
206    }
207
208    fn give(&self) {
209        unsafe {
210            freertos_rs_give_recursive_semaphore(self.0);
211        }
212    }
213
214    #[inline]
215    unsafe fn from_raw_handle(handle: FreeRtosSemaphoreHandle) -> Self {
216        Self(handle)
217    }
218
219    #[inline]
220    fn raw_handle(&self) -> FreeRtosSemaphoreHandle {
221        self.0
222    }
223}
224
225impl Drop for MutexRecursive {
226    fn drop(&mut self) {
227        unsafe { freertos_rs_delete_semaphore(self.0) }
228    }
229}
230
231impl fmt::Debug for MutexRecursive {
232    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
233        write!(f, "{:?}", self.0)
234    }
235}