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