1use super::{AtomicLock, AttemptStatus};
2use crate::platform::types::c_int;
3use core::{
4 cell::UnsafeCell,
5 ops::{Deref, DerefMut},
6 sync::atomic::{AtomicI32 as AtomicInt, Ordering},
7};
8
9pub(crate) const UNLOCKED: c_int = 0;
10pub(crate) const LOCKED: c_int = 1;
11pub(crate) const WAITING: c_int = 2;
12
13pub struct Mutex<T> {
14 pub(crate) lock: AtomicLock,
15 content: UnsafeCell<T>,
16}
17unsafe impl<T: Send> Send for Mutex<T> {}
18unsafe impl<T: Send> Sync for Mutex<T> {}
19
20pub(crate) unsafe fn manual_try_lock_generic(word: &AtomicInt) -> bool {
21 word.compare_exchange(UNLOCKED, LOCKED, Ordering::Acquire, Ordering::Relaxed)
22 .is_ok()
23}
24pub(crate) unsafe fn manual_lock_generic(word: &AtomicInt) {
25 crate::sync::wait_until_generic(
26 word,
27 |lock| {
28 lock.compare_exchange_weak(UNLOCKED, LOCKED, Ordering::Acquire, Ordering::Relaxed)
29 .map(|_| AttemptStatus::Desired)
30 .unwrap_or_else(|e| match e {
31 WAITING => AttemptStatus::Waiting,
32 _ => AttemptStatus::Other,
33 })
34 },
35 |lock| match lock
36 .compare_exchange_weak(LOCKED, WAITING, Ordering::SeqCst, Ordering::SeqCst)
38 .unwrap_or_else(|e| e)
39 {
40 UNLOCKED => AttemptStatus::Desired,
41 WAITING => AttemptStatus::Waiting,
42 _ => AttemptStatus::Other,
43 },
44 WAITING,
45 );
46}
47pub(crate) unsafe fn manual_unlock_generic(word: &AtomicInt) {
48 if word.swap(UNLOCKED, Ordering::Release) == WAITING {
49 crate::sync::futex_wake(word, i32::MAX);
50 }
51}
52
53impl<T> Mutex<T> {
54 pub const fn new(content: T) -> Self {
56 Self {
57 lock: AtomicLock::new(UNLOCKED),
58 content: UnsafeCell::new(content),
59 }
60 }
61 pub unsafe fn locked(content: T) -> Self {
68 Self {
69 lock: AtomicLock::new(LOCKED),
70 content: UnsafeCell::new(content),
71 }
72 }
73
74 pub unsafe fn manual_try_lock(&self) -> Result<&mut T, c_int> {
79 if unsafe { manual_try_lock_generic(&self.lock) } {
80 Ok(unsafe { &mut *self.content.get() })
81 } else {
82 Err(0)
83 }
84 }
85 pub unsafe fn manual_lock(&self) -> &mut T {
89 unsafe { manual_lock_generic(&self.lock) };
90 unsafe { &mut *self.content.get() }
91 }
92 pub unsafe fn manual_unlock(&self) {
94 unsafe { manual_unlock_generic(&self.lock) }
95 }
96 pub fn as_ptr(&self) -> *mut T {
97 self.content.get()
98 }
99
100 pub fn try_lock(&self) -> Option<MutexGuard<'_, T>> {
103 unsafe {
104 self.manual_try_lock().ok().map(|content| MutexGuard {
105 mutex: self,
106 content,
107 })
108 }
109 }
110 pub fn lock(&self) -> MutexGuard<'_, T> {
113 MutexGuard {
114 mutex: self,
115 content: unsafe { self.manual_lock() },
116 }
117 }
118}
119
120pub struct MutexGuard<'a, T: 'a> {
121 pub(crate) mutex: &'a Mutex<T>,
122 content: &'a mut T,
123}
124impl<'a, T> Deref for MutexGuard<'a, T> {
125 type Target = T;
126
127 fn deref(&self) -> &Self::Target {
128 self.content
129 }
130}
131impl<'a, T> DerefMut for MutexGuard<'a, T> {
132 fn deref_mut(&mut self) -> &mut Self::Target {
133 self.content
134 }
135}
136impl<'a, T> Drop for MutexGuard<'a, T> {
137 fn drop(&mut self) {
138 unsafe {
139 self.mutex.manual_unlock();
140 }
141 }
142}