1use vstd::atomic_ghost::*;
3use vstd::cell::{self, pcell::{self, *}};
4use vstd::prelude::*;
5use vstd_extra::prelude::*;
6use vstd_extra::resource::ghost_resource::excl::*;
7
8use alloc::sync::Arc;
9use core::{
10 cell::UnsafeCell,
11 fmt,
12 ops::{Deref, DerefMut},
13 sync::atomic::Ordering,
14};
15
16use super::WaitQueue;
17
18verus! {
19
20struct_with_invariants! {
21
22pub struct Mutex<T > {
24 lock: AtomicBool<_, Option<PointsTo<T>>, _>,
25 queue: WaitQueue,
26 val: PCell<T>,
28}
29
30closed spec fn wf(self) -> bool {
31 invariant on lock with (val) is (v: bool, g: Option<PointsTo<T>>) {
32 let active_guard = g is None;
33 &&& v <==> active_guard
34 &&& g is Some ==> g->Some_0.id() == val.id()
35 }
36}
37}
38
39impl<T> Mutex<T> {
40 pub closed spec fn cell_id(self) -> cell::CellId {
41 self.val.id()
42 }
43
44 #[verifier::type_invariant]
45 pub closed spec fn type_inv(self) -> bool {
46 self.wf()
47 }
48
49 pub const fn new(val: T) -> Self {
51 let (val, Tracked(perm)) = PCell::new(val);
52 Self {
53 lock: AtomicBool::new(
54 Ghost(val),
55 false,
56 Tracked(Some(perm)),
57 ),
58 queue: WaitQueue::new(),
59 val: val,
60 }
61 }
62}
63
64#[verus_verify]
65impl<T > Mutex<T> {
66 #[track_caller]
70 pub fn lock(&self) -> MutexGuard<'_, T> {
71 self.queue.wait_until(|| self.try_lock())
72 }
73
74 #[verus_spec]
76 pub fn try_lock(&self) -> Option<MutexGuard<T>> {
77 proof_decl! {
81 let tracked mut locked_state: Option<PointsTo<T>> = None;
82 }
83 {#[verus_spec(with => Tracked(locked_state))] self.acquire_lock()}.then(
84 || requires
85 locked_state is Some,
86 locked_state -> Some_0.id() == self.cell_id(),
87 {unsafe { proof_with!{Tracked(locked_state.tracked_unwrap())};
88 MutexGuard::new(self) }})
89 }
90
91 #[verus_spec(
102 with
103 Tracked(perm): Tracked<PointsTo<T>>,
104 requires
105 perm.id() == self.cell_id(),
106 )]
107 fn unlock(&self)
108 {
109 proof_with!(Tracked(perm));
110 self.release_lock();
111 self.queue.wake_one();
112 }
113
114 #[verus_spec(ret =>
115 with
116 -> locked_state: Tracked<Option<PointsTo<T>>>,
117 ensures
118 ret ==> locked_state@ is Some && locked_state@->Some_0.id() == self.cell_id(),
119 !ret ==> locked_state@ is None,
120 )]
121 fn acquire_lock(&self) -> bool {
122 proof_decl! {
123 let tracked mut locked_state: Option<PointsTo<T>> = None;
124 }
125 proof! {
126 use_type_invariant(self);
127 }
128 proof_with! { |= Tracked(locked_state) }
129 atomic_with_ghost! {
130 self.lock => compare_exchange(false, true);
131 returning res;
132 ghost perms => {
133 if res is Ok {
134 let tracked perm = perms.tracked_take();
135 locked_state = Some(perm);
136 }
137 }
138 }.is_ok()
139 }
140
141 #[verus_spec(
142 with
143 Tracked(perm): Tracked<PointsTo<T>>,
144 requires
145 perm.id() == self.cell_id(),
146 )]
147 fn release_lock(&self)
148 {
149 proof! {
150 use_type_invariant(self);
151 }
152 atomic_with_ghost! {
153 self.lock => store(false);
154 ghost perms => {
155 perms = Some(perm);
156 }
157 }
158 }
159}
160
161#[verifier::external]
168unsafe impl<T: Send> Send for Mutex<T> {}
169#[verifier::external]
170unsafe impl<T: Send> Sync for Mutex<T> {}
171
172#[verifier::reject_recursive_types(T)]
174#[clippy::has_significant_drop]
175#[must_use]
176#[verus_verify]
177pub struct MutexGuard<'a, T > {
178 mutex: &'a Mutex<T>,
179 v_perm: Tracked<PointsTo<T>>,
180}
181
182impl<'a, T > MutexGuard<'a, T> {
183 #[verifier::type_invariant]
184 closed spec fn type_inv(self) -> bool {
185 self.v_perm@.id() == self.mutex.cell_id()
186 }
187
188 pub closed spec fn value(self) -> T {
190 *self.v_perm@.value()
191 }
192
193 pub open spec fn view(self) -> T {
195 self.value()
196 }
197}
198
199impl<'a, T > MutexGuard<'a, T> {
200 #[verus_spec(ret =>
205 with
206 Tracked(perm): Tracked<PointsTo<T>>,
207 requires
208 perm.id() == mutex.cell_id(),
209 )]
210 unsafe fn new(mutex: &'a Mutex<T>) -> (r: MutexGuard<'a, T>)
211 {
212 MutexGuard { mutex, v_perm: Tracked(perm) }
213 }
214
215 #[verus_spec]
218 pub fn drop(self) {
219 proof! {
220 use_type_invariant(&self);
221 use_type_invariant(&*self.mutex);
222 }
223 proof_with!{self.v_perm}
224 self.mutex.release_lock();
225 self.mutex.queue.wake_one();
226 }
227}
228
229#[verus_verify]
230impl<T> Deref for MutexGuard<'_, T> {
231 type Target = T;
232
233 #[verus_spec(returns self.view())]
234 fn deref(&self) -> &Self::Target {
235 proof! {
236 use_type_invariant(self);
237 }
238 self.mutex.val.borrow(Tracked(self.v_perm.borrow()))
240 }
241}
242
243#[verus_verify]
244impl<T> DerefMut for MutexGuard<'_, T> {
245 #[verus_spec(ret =>
246 ensures
247 final(self).view() == *final(ret),
248 )]
249 fn deref_mut(&mut self) -> &mut Self::Target
250 {
251 proof!{
252 use_type_invariant(&*self);
253 }
254 pcell_borrow_mut(&self.mutex.val, &mut self.v_perm)
256 }
257}
258
259impl<T > !Send for MutexGuard<'_, T> {}
276
277impl<'a, T > MutexGuard<'a, T> {
279 pub fn get_lock(guard: &MutexGuard<'a, T>) -> &'a Mutex<T> {
281 guard.mutex
282 }
283}
284
285} #[cfg(ktest)]
287mod test {
288 use super::*;
289 use crate::prelude::*;
290
291 #[ktest]
293 fn test_mutex_try_lock_does_not_unlock() {
294 let lock = Mutex::new(0);
295 assert!(!lock.lock.load(Ordering::Relaxed));
296
297 let guard1 = lock.lock();
299 assert!(lock.lock.load(Ordering::Relaxed));
300
301 assert!(lock.try_lock().is_none());
303 assert!(lock.lock.load(Ordering::Relaxed));
304
305 drop(guard1);
307 }
308}