mutex.rs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /*
  2. * Copyright (c) 2006-2025, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2025-10-10 foxglove RT-Thread Mutex implementation
  9. */
  10. use crate::api::*;
  11. use crate::{panic::panic_on_atomic_context, RTTError};
  12. use alloc::fmt;
  13. pub use alloc::sync::{Arc, Weak};
  14. use core::cell::UnsafeCell;
  15. use core::ops::{Deref, DerefMut};
  16. use core::sync::atomic::*;
  17. const RT_WAITING_FOREVER: isize = -1;
  18. unsafe impl<T: Send, M: RawMutexOps + Sized> Send for Mutex<T, M> {}
  19. unsafe impl<T: Send, M: RawMutexOps + Sized> Sync for Mutex<T, M> {}
  20. pub struct Mutex<T: ?Sized, M = SleepMutex>
  21. where
  22. M: RawMutexOps + Sized,
  23. {
  24. mutex: M,
  25. data: UnsafeCell<T>,
  26. }
  27. /* Impl for Default Mutex<M = SleepMutex, NAME = UnnamedObj> */
  28. impl<T> Mutex<T> {
  29. pub fn new(t: T) -> Result<Self, RTTError> {
  30. Ok(Mutex {
  31. mutex: SleepMutex::create("Unnamed")?,
  32. data: UnsafeCell::new(t),
  33. })
  34. }
  35. pub fn new_with_name(t: T, name: &str) -> Result<Self, RTTError> {
  36. Ok(Mutex {
  37. mutex: SleepMutex::create(name)?,
  38. data: UnsafeCell::new(t),
  39. })
  40. }
  41. pub fn try_lock(&self, max_wait: isize) -> Result<MutexGuard<'_, SleepMutex, T>, RTTError> {
  42. self.mutex.take(max_wait)?;
  43. Ok(MutexGuard {
  44. __mutex: &self.mutex,
  45. __data: &self.data,
  46. })
  47. }
  48. pub fn lock(&self) -> Result<MutexGuard<'_, SleepMutex, T>, RTTError> {
  49. self.mutex.take(RT_WAITING_FOREVER)?;
  50. Ok(MutexGuard {
  51. __mutex: &self.mutex,
  52. __data: &self.data,
  53. })
  54. }
  55. }
  56. /* Impl for all Mutex */
  57. impl<T, M: RawMutexOps> Mutex<T, M> {
  58. pub fn spec_new(t: T) -> Result<Self, RTTError> {
  59. Ok(Mutex {
  60. mutex: M::create("Unnamed")?,
  61. data: UnsafeCell::new(t),
  62. })
  63. }
  64. pub fn spec_new_with_name(t: T, name: &str) -> Result<Self, RTTError> {
  65. Ok(Mutex {
  66. mutex: M::create(name)?,
  67. data: UnsafeCell::new(t),
  68. })
  69. }
  70. pub fn spec_try_lock(&self, max_wait: isize) -> Result<MutexGuard<'_, M, T>, RTTError> {
  71. self.mutex.take(max_wait)?;
  72. Ok(MutexGuard {
  73. __mutex: &self.mutex,
  74. __data: &self.data,
  75. })
  76. }
  77. pub fn spec_lock(&self) -> Result<MutexGuard<'_, M, T>, RTTError> {
  78. self.mutex.take(RT_WAITING_FOREVER)?;
  79. Ok(MutexGuard {
  80. __mutex: &self.mutex,
  81. __data: &self.data,
  82. })
  83. }
  84. }
  85. impl<T: ?Sized> fmt::Debug for Mutex<T> {
  86. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  87. write!(f, "Mutex address: {:?}", self.mutex)
  88. }
  89. }
  90. pub struct MutexGuard<'a, M: RawMutexOps + 'a, T: ?Sized + 'a> {
  91. __mutex: &'a M,
  92. __data: &'a UnsafeCell<T>,
  93. }
  94. impl<'mutex, M: RawMutexOps, T: ?Sized> Deref for MutexGuard<'mutex, M, T> {
  95. type Target = T;
  96. fn deref(&self) -> &T {
  97. unsafe { &*self.__data.get() }
  98. }
  99. }
  100. impl<'mutex, M: RawMutexOps, T: ?Sized> DerefMut for MutexGuard<'mutex, M, T> {
  101. fn deref_mut(&mut self) -> &mut T {
  102. unsafe { &mut *self.__data.get() }
  103. }
  104. }
  105. impl<'a, M: RawMutexOps, T: ?Sized> Drop for MutexGuard<'a, M, T> {
  106. fn drop(&mut self) {
  107. self.__mutex.release();
  108. }
  109. }
  110. pub type CommonMutex = SleepMutex;
  111. pub struct SleepMutex(APIRawMutex);
  112. impl fmt::Debug for SleepMutex {
  113. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  114. write!(f, "{:?}", self.0)
  115. }
  116. }
  117. pub struct AtomicMutex(UnsafeCell<InterruptFlag>, AtomicBool);
  118. pub trait RawMutexOps: Sized {
  119. fn create(name: &str) -> Result<Self, RTTError>;
  120. fn take(&self, max_wait: isize) -> Result<(), RTTError>;
  121. fn release(&self);
  122. fn drop(&mut self);
  123. }
  124. impl RawMutexOps for AtomicMutex {
  125. fn create(_name: &str) -> Result<Self, RTTError> {
  126. Ok(AtomicMutex {
  127. 0: UnsafeCell::new(INTERRUPT_FLAG_INIT),
  128. 1: AtomicBool::new(false),
  129. })
  130. }
  131. fn take(&self, max_wait: isize) -> Result<(), RTTError> {
  132. let f;
  133. unsafe {
  134. f = self.0.get();
  135. *f = interrupt_disable();
  136. }
  137. let ret = if max_wait == RT_WAITING_FOREVER {
  138. while self
  139. .1
  140. .compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed)
  141. .is_err()
  142. {
  143. while self.1.load(Ordering::Relaxed) {}
  144. }
  145. Ok(())
  146. } else {
  147. if self
  148. .1
  149. .compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed)
  150. .is_ok()
  151. {
  152. Ok(())
  153. } else {
  154. unsafe {
  155. interrupt_enable(*f);
  156. }
  157. Err(RTTError::MutexTakeTimeout)
  158. }
  159. };
  160. return ret;
  161. }
  162. fn release(&self) {
  163. self.1.store(false, Ordering::Release);
  164. let f;
  165. unsafe {
  166. f = self.0.get();
  167. interrupt_enable(*f);
  168. }
  169. }
  170. fn drop(&mut self) {}
  171. }
  172. impl RawMutexOps for SleepMutex {
  173. fn create(name: &str) -> Result<Self, RTTError> {
  174. panic_on_atomic_context("create");
  175. mutex_create(name)
  176. .ok_or(RTTError::OutOfMemory)
  177. .map(|m| SleepMutex(m))
  178. }
  179. fn take(&self, max_wait: isize) -> Result<(), RTTError> {
  180. panic_on_atomic_context("take");
  181. let ret = mutex_take(self.0, max_wait);
  182. if !is_eok(ret) {
  183. return Err(RTTError::MutexTakeTimeout);
  184. }
  185. Ok(())
  186. }
  187. fn release(&self) {
  188. panic_on_atomic_context("release");
  189. mutex_release(self.0);
  190. }
  191. fn drop(&mut self) {
  192. panic_on_atomic_context("drop");
  193. mutex_delete(self.0);
  194. }
  195. }