1use super::MTX_UNOWNED;
2use crate::context::{BorrowedArc, current_thread};
3use alloc::rc::Rc;
4use core::cell::UnsafeCell;
5use core::marker::PhantomData;
6use core::ops::{Deref, DerefMut};
7use core::sync::atomic::{AtomicUsize, Ordering};
8
9pub struct Mutex<T> {
11 data: UnsafeCell<T>,
12 owning: AtomicUsize, phantom: PhantomData<Rc<()>>, }
15
16impl<T> Mutex<T> {
17 pub const fn new(data: T) -> Self {
19 Self {
20 data: UnsafeCell::new(data),
21 owning: AtomicUsize::new(MTX_UNOWNED),
22 phantom: PhantomData,
23 }
24 }
25
26 pub fn lock(&self) -> MutexGuard<T> {
28 let td = current_thread();
30
31 if !td.can_sleep() {
32 panic!("locking a mutex in a non-sleeping context is not supported");
33 }
34
35 if self
37 .owning
38 .compare_exchange(
39 MTX_UNOWNED,
40 BorrowedArc::as_ptr(&td) as usize,
41 Ordering::Acquire,
42 Ordering::Relaxed,
43 )
44 .is_err()
45 {
46 todo!()
47 }
48
49 td.set_active_mutexes(td.active_mutexes() + 1);
50
51 MutexGuard {
52 data: self.data.get(),
53 lock: &self.owning,
54 phantom: PhantomData,
55 }
56 }
57
58 unsafe fn unlock(lock: &AtomicUsize) {
63 let td = current_thread();
64
65 td.set_active_mutexes(td.active_mutexes() - 1);
66
67 if lock
69 .compare_exchange(
70 BorrowedArc::as_ptr(&td) as usize,
71 MTX_UNOWNED,
72 Ordering::Release,
73 Ordering::Relaxed,
74 )
75 .is_err()
76 {
77 todo!()
78 }
79 }
80}
81
82impl<T: Default> Default for Mutex<T> {
83 fn default() -> Self {
84 Self::new(T::default())
85 }
86}
87
88unsafe impl<T: Send> Send for Mutex<T> {}
89unsafe impl<T: Send> Sync for Mutex<T> {}
90
91pub struct MutexGuard<'a, T> {
96 data: *mut T,
97 lock: *const AtomicUsize,
98 phantom: PhantomData<&'a Mutex<T>>,
99}
100
101impl<'a, T> MutexGuard<'a, T> {
102 pub fn map<O, F>(this: Self, f: F) -> MappedMutex<'a, O>
103 where
104 F: FnOnce(&'a mut T) -> O + 'a,
105 {
106 let data = unsafe { f(&mut *this.data) };
107 let lock = this.lock;
108
109 core::mem::forget(this);
110
111 MappedMutex {
112 data,
113 lock,
114 phantom: PhantomData,
115 }
116 }
117}
118
119impl<T> Drop for MutexGuard<'_, T> {
120 fn drop(&mut self) {
121 unsafe { Mutex::<T>::unlock(&*self.lock) };
123 }
124}
125
126impl<T> Deref for MutexGuard<'_, T> {
127 type Target = T;
128
129 fn deref(&self) -> &Self::Target {
130 unsafe { &*self.data }
131 }
132}
133
134impl<T> DerefMut for MutexGuard<'_, T> {
135 fn deref_mut(&mut self) -> &mut Self::Target {
136 unsafe { &mut *self.data }
137 }
138}
139
140unsafe impl<T: Sync> Sync for MutexGuard<'_, T> {}
141
142pub struct MappedMutex<'a, T> {
146 data: T,
147 lock: *const AtomicUsize,
148 phantom: PhantomData<&'a Mutex<T>>,
149}
150
151impl<T> Drop for MappedMutex<'_, T> {
152 fn drop(&mut self) {
153 unsafe { Mutex::<T>::unlock(&*self.lock) };
155 }
156}
157
158impl<T> Deref for MappedMutex<'_, T> {
159 type Target = T;
160
161 fn deref(&self) -> &Self::Target {
162 &self.data
163 }
164}
165
166impl<T> DerefMut for MappedMutex<'_, T> {
167 fn deref_mut(&mut self) -> &mut Self::Target {
168 &mut self.data
169 }
170}
171
172unsafe impl<T: Sync> Sync for MappedMutex<'_, T> {}