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> {
33 let td = current_thread();
35
36 if !td.can_sleep() {
37 panic!("locking a mutex in a non-sleeping context is not supported");
38 }
39
40 if self
42 .owning
43 .compare_exchange(
44 MTX_UNOWNED,
45 BorrowedArc::as_ptr(&td) as usize,
46 Ordering::Acquire,
47 Ordering::Relaxed,
48 )
49 .is_err()
50 {
51 todo!()
52 }
53
54 td.set_active_mutexes(td.active_mutexes() + 1);
55
56 MutexGuard {
57 data: self.data.get(),
58 lock: &self.owning,
59 phantom: PhantomData,
60 }
61 }
62
63 unsafe fn unlock(lock: &AtomicUsize) {
68 let td = current_thread();
69
70 td.set_active_mutexes(td.active_mutexes() - 1);
71
72 if lock
74 .compare_exchange(
75 BorrowedArc::as_ptr(&td) as usize,
76 MTX_UNOWNED,
77 Ordering::Release,
78 Ordering::Relaxed,
79 )
80 .is_err()
81 {
82 todo!()
83 }
84 }
85}
86
87impl<T: Default> Default for Mutex<T> {
88 fn default() -> Self {
89 Self::new(T::default())
90 }
91}
92
93unsafe impl<T: Send> Send for Mutex<T> {}
94unsafe impl<T: Send> Sync for Mutex<T> {}
95
96pub struct MutexGuard<'a, T> {
101 data: *mut T,
102 lock: *const AtomicUsize,
103 phantom: PhantomData<&'a Mutex<T>>,
104}
105
106impl<'a, T> MutexGuard<'a, T> {
107 pub fn map<O, F>(this: Self, f: F) -> MappedMutex<'a, O>
108 where
109 F: FnOnce(&'a mut T) -> O + 'a,
110 {
111 let data = unsafe { f(&mut *this.data) };
112 let lock = this.lock;
113
114 core::mem::forget(this);
115
116 MappedMutex {
117 data,
118 lock,
119 phantom: PhantomData,
120 }
121 }
122}
123
124impl<T> Drop for MutexGuard<'_, T> {
125 fn drop(&mut self) {
126 unsafe { Mutex::<T>::unlock(&*self.lock) };
128 }
129}
130
131impl<T> Deref for MutexGuard<'_, T> {
132 type Target = T;
133
134 fn deref(&self) -> &Self::Target {
135 unsafe { &*self.data }
136 }
137}
138
139impl<T> DerefMut for MutexGuard<'_, T> {
140 fn deref_mut(&mut self) -> &mut Self::Target {
141 unsafe { &mut *self.data }
142 }
143}
144
145unsafe impl<T: Sync> Sync for MutexGuard<'_, T> {}
146
147pub struct MappedMutex<'a, T> {
151 data: T,
152 lock: *const AtomicUsize,
153 phantom: PhantomData<&'a Mutex<T>>,
154}
155
156impl<T> Drop for MappedMutex<'_, T> {
157 fn drop(&mut self) {
158 unsafe { Mutex::<T>::unlock(&*self.lock) };
160 }
161}
162
163impl<T> Deref for MappedMutex<'_, T> {
164 type Target = T;
165
166 fn deref(&self) -> &Self::Target {
167 &self.data
168 }
169}
170
171impl<T> DerefMut for MappedMutex<'_, T> {
172 fn deref_mut(&mut self) -> &mut Self::Target {
173 &mut self.data
174 }
175}
176
177unsafe impl<T: Sync> Sync for MappedMutex<'_, T> {}