freertos_rust/
mutex.rs

1use crate::prelude::v1::*;
2use crate::base::*;
3use crate::units::*;
4use crate::shim::*;
5
6pub type Mutex<T> = MutexImpl<T, MutexNormal>;
7pub type RecursiveMutex<T> = MutexImpl<T, MutexRecursive>;
8
9unsafe impl<T: Sync + Send, M> Send for MutexImpl<T, M> {}
10
11unsafe impl<T: Sync + 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> where M: MutexInnerImpl + fmt::Debug {
21    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
22        write!(f, "Mutex address: {:?}", self.mutex)
23    }
24}
25
26impl<T> MutexImpl<T, MutexNormal> {
27    /// Create a new mutex with the given inner value
28    pub fn new(t: T) -> Result<Self, FreeRtosError> {
29        Ok(MutexImpl {
30            mutex: MutexNormal::create()?,
31            data: UnsafeCell::new(t),
32        })
33    }
34}
35
36impl<T> MutexImpl<T, MutexRecursive> {
37    /// Create a new recursive mutex with the given inner value
38    pub fn new(t: T) -> Result<Self, FreeRtosError> {
39        Ok(MutexImpl {
40            mutex: MutexRecursive::create()?,
41            data: UnsafeCell::new(t),
42        })
43    }
44}
45
46impl<T, M> MutexImpl<T, M> where M: MutexInnerImpl {
47    /// Try to obtain a lock and mutable access to our inner value
48    pub fn lock<D: DurationTicks>(&self, max_wait: D) -> Result<MutexGuard<T, M>, FreeRtosError> {
49        self.mutex.take(max_wait)?;
50
51        Ok(MutexGuard {
52            __mutex: &self.mutex,
53            __data: &self.data,
54        })
55    }
56
57    /// Consume the mutex and return its inner value
58    pub fn into_inner(self) -> T {
59        // Manually deconstruct the structure, because it implements Drop
60        // and we cannot move the data value out of it.
61        unsafe {
62            let (mutex, data) = {
63                let Self { ref mutex, ref data } = self;
64                (ptr::read(mutex), ptr::read(data))
65            };
66            mem::forget(self);
67
68            drop(mutex);
69
70            data.into_inner()
71        }
72    }
73}
74
75/// Holds the mutex until we are dropped
76pub struct MutexGuard<'a, T: ?Sized + 'a, M: 'a> where M: MutexInnerImpl {
77    __mutex: &'a M,
78    __data: &'a UnsafeCell<T>,
79}
80
81impl<'mutex, T: ?Sized, M> Deref for MutexGuard<'mutex, T, M> where M: MutexInnerImpl {
82    type Target = T;
83
84    fn deref<'a>(&'a self) -> &'a T {
85        unsafe { &*self.__data.get() }
86    }
87}
88
89impl<'mutex, T: ?Sized, M> DerefMut for MutexGuard<'mutex, T, M> where M: MutexInnerImpl {
90    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
91        unsafe { &mut *self.__data.get() }
92    }
93}
94
95impl<'a, T: ?Sized, M> Drop for MutexGuard<'a, T, M> where M: MutexInnerImpl {
96    fn drop(&mut self) {
97        self.__mutex.give();
98    }
99}
100
101
102pub trait MutexInnerImpl where Self: Sized + Drop {
103    fn create() -> Result<Self, FreeRtosError>;
104    fn take<D: DurationTicks>(&self, max_wait: D) -> Result<(), FreeRtosError>;
105    fn give(&self);
106}
107
108pub struct MutexNormal(FreeRtosSemaphoreHandle);
109
110impl MutexInnerImpl for MutexNormal {
111    fn create() -> Result<Self, FreeRtosError> {
112        let m = unsafe { freertos_rs_create_mutex() };
113        if m == 0 as *const _ {
114            return Err(FreeRtosError::OutOfMemory);
115        }
116        Ok(MutexNormal(m))
117    }
118
119    fn take<D: DurationTicks>(&self, max_wait: D) -> Result<(), FreeRtosError> {
120        let res = unsafe { freertos_rs_take_mutex(self.0, max_wait.to_ticks()) };
121
122        if res != 0 {
123            return Err(FreeRtosError::MutexTimeout);
124        }
125
126        Ok(())
127    }
128
129    fn give(&self) {
130        unsafe { freertos_rs_give_mutex(self.0); }
131    }
132}
133
134impl Drop for MutexNormal {
135    fn drop(&mut self) {
136        unsafe { freertos_rs_delete_semaphore(self.0) }
137    }
138}
139
140impl fmt::Debug for MutexNormal {
141    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
142        write!(f, "{:?}", self.0)
143    }
144}
145
146pub struct MutexRecursive(FreeRtosSemaphoreHandle);
147
148impl MutexInnerImpl for MutexRecursive {
149    fn create() -> Result<Self, FreeRtosError> {
150        let m = unsafe { freertos_rs_create_recursive_mutex() };
151        if m == 0 as *const _ {
152            return Err(FreeRtosError::OutOfMemory);
153        }
154        Ok(MutexRecursive(m))
155    }
156
157    fn take<D: DurationTicks>(&self, max_wait: D) -> Result<(), FreeRtosError> {
158        let res = unsafe { freertos_rs_take_recursive_mutex(self.0, max_wait.to_ticks()) };
159
160        if res != 0 {
161            return Err(FreeRtosError::MutexTimeout);
162        }
163
164        Ok(())
165    }
166
167    fn give(&self) {
168        unsafe { freertos_rs_give_recursive_mutex(self.0); }
169    }
170}
171
172impl Drop for MutexRecursive {
173    fn drop(&mut self) {
174        unsafe { freertos_rs_delete_semaphore(self.0) }
175    }
176}
177
178impl fmt::Debug for MutexRecursive {
179    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
180        write!(f, "{:?}", self.0)
181    }
182}