1use vstd::atomic_ghost::*;
3use vstd::cell::{self, CellId, pcell::*};
4use vstd::prelude::*;
5use vstd::resource::Loc;
6use vstd_extra::resource::ghost_resource::{count_auth::*, count_ghost::*, csum::*, excl::*};
7use vstd_extra::sum::*;
8use vstd_extra::{prelude::*, resource};
9
10use alloc::sync::Arc;
11use core::char::MAX;
12use core::{
13 cell::UnsafeCell,
14 fmt,
15 marker::PhantomData,
16 ops::{Deref, DerefMut},
17 sync::atomic::{
18 Ordering::{AcqRel, Acquire, Relaxed, Release},
20 },
21};
22
23use super::{
24 PreemptDisabled,
25 guard::{GuardTransfer, SpinGuardian},
26};
27
28verus! {
29
30type NoPerm<T> = EmptyCount<PointsTo<T>>;
32
33type HalfPerm<T> = Count<PointsTo<T>>;
35
36type ReadPerm<T> = (HalfPerm<T>, OneLeftKnowledge<HalfPerm<T>, NoPerm<T>, 3>);
38
39tracked struct RwPerms<T> {
40 core_token: SumResource<HalfPerm<T>, NoPerm<T>, 3>,
45 read_retract_token: TokenResource<MAX_READER_MASK>,
51 upread_retract_token: Option<UniqueToken>,
53 upreader_guard_token: Option<OneLeftOwner<HalfPerm<T>, NoPerm<T>, 3>>,
55 read_guard_token: CountResource<ReadPerm<T>, MAX_READER>,
57}
58
59ghost struct RwId {
60 core_token_id: Loc,
61 frac_id: Loc,
62 read_retract_token_id: Loc,
63 upread_retract_token_id: Loc,
64 read_guard_token_id: Loc,
65}
66
67pub closed spec fn no_max_reader_overflow(v: usize) -> bool {
73 v & MAX_READER_MASK < MAX_READER_MASK
74}
75
76struct_with_invariants! {
77pub struct RwLock<T , Guard > {
156 guard: PhantomData<Guard>,
157 lock: AtomicUsize<_, RwPerms<T>,_>,
163 val: PCell<T>,
165 ghost_id: Ghost<RwId>,
166}
167
168closed spec fn wf(self) -> bool {
170 invariant on lock with (val, guard, ghost_id) is (v: usize, g: RwPerms<T>) {
171 let has_writer_bit: bool = (v & WRITER) != 0;
173 let has_upgrade_bit: bool = (v & UPGRADEABLE_READER) != 0;
174 let has_max_reader_bit: bool = (v & MAX_READER) != 0;
175 let total_reader_bits: int = (v & MAX_READER_MASK) as int;
178 let reader_bits: int = if has_max_reader_bit { MAX_READER as int } else { (v & READER_MASK) as int };
182
183 let active_writer: bool = g.core_token.is_right();
191 let active_upgrade_guard: bool = !active_writer && g.upreader_guard_token is None;
193 let active_read_guards: int = if g.read_guard_token.is_resource_vacant() {
195 0
196 } else {
197 MAX_READER - g.read_guard_token.frac()
198 };
199 let pending_failed_upread_attempt: bool = g.upread_retract_token is None;
201 let failed_reader_attempts: int = MAX_READER_MASK - g.read_retract_token.frac();
203
204 &&& if g.core_token.is_left() {
205 let resource = g.read_guard_token.resource();
206 let read_half_cell_perm = resource.0;
207 let mode_knowledge = resource.1;
208 &&& !g.read_guard_token.is_resource_vacant()
209 &&& mode_knowledge.id() == ghost_id@.core_token_id
210 &&& read_half_cell_perm.id() == ghost_id@.frac_id
211 &&& read_half_cell_perm.resource().id() == val.id()
212 &&& read_half_cell_perm.frac() == 1
213 } else {
214 &&& g.upreader_guard_token is None
215 &&& g.read_guard_token.is_resource_vacant()
216 }
217 &&& has_upgrade_bit <==> (active_upgrade_guard || pending_failed_upread_attempt)
219 &&& !(active_upgrade_guard && pending_failed_upread_attempt)
221 &&& total_reader_bits == active_read_guards + failed_reader_attempts
223 &&& active_writer <==> has_writer_bit
225 &&& 0 <= active_read_guards <= reader_bits <= total_reader_bits
227 &&& !(active_writer && (active_read_guards + if active_upgrade_guard { 1int } else { 0 }) > 0)
229 &&& g.core_token.id() == ghost_id@.core_token_id
230 &&& g.core_token.wf()
231 &&& g.core_token.is_left() ==> {
232 &&& !g.core_token.is_resource_owner()
233 &&& g.core_token.frac() == 1
234 }
235 &&& g.core_token.is_right() ==> {
236 let empty = g.core_token.resource_right();
237 &&& empty.id() == ghost_id@.frac_id
238 &&& g.core_token.frac() == 2
239 &&& g.core_token.has_resource()
240 }
241 &&& g.read_retract_token.wf()
242 &&& g.read_retract_token.id() == ghost_id@.read_retract_token_id
243 &&& g.upread_retract_token is Some ==>
244 {
245 let token = g.upread_retract_token->0;
246 &&& token.wf()
247 &&& token.id() == ghost_id@.upread_retract_token_id
248 }
249 &&& g.upreader_guard_token is Some ==> {
250 let token = g.upreader_guard_token->0;
251 wf_upgradeable_guard_token(ghost_id@.core_token_id, ghost_id@.frac_id, val.id(), token)
252 }
253 &&& g.read_guard_token.wf()
254 &&& g.read_guard_token.id() == ghost_id@.read_guard_token_id
255 }
256}
257
258}
259
260const READER: usize = 1;
261
262const WRITER: usize = 1 << (usize::BITS - 1);
263
264const UPGRADEABLE_READER: usize = 1 << (usize::BITS - 2);
265
266const BEING_UPGRADED: usize = 1 << (usize::BITS - 3);
267
268const MAX_READER: usize = 1 << (usize::BITS - 4);
283
284const READER_MASK: usize = usize::MAX >> 4;
286
287const MAX_READER_MASK: usize = usize::MAX >> 3;
289
290impl<T, G> RwLock<T, G> {
291 pub closed spec fn cell_id(self) -> cell::CellId {
293 self.val.id()
294 }
295
296 pub closed spec fn core_token_id(self) -> Loc {
297 self.ghost_id@.core_token_id
298 }
299
300 pub closed spec fn frac_id(self) -> Loc {
301 self.ghost_id@.frac_id
302 }
303
304 pub closed spec fn upread_retract_token_id(self) -> Loc {
305 self.ghost_id@.upread_retract_token_id
306 }
307
308 pub closed spec fn read_guard_token_id(self) -> Loc {
309 self.ghost_id@.read_guard_token_id
310 }
311
312 #[verifier::type_invariant]
314 pub closed spec fn type_inv(self) -> bool {
315 self.wf()
316 }
317}
318
319closed spec fn wf_upgradeable_guard_token<T>(
320 core_token_id: Loc,
321 frac_id: Loc,
322 cell_id: CellId,
323 token: OneLeftOwner<HalfPerm<T>, NoPerm<T>, 3>,
324) -> bool {
325 let half_cell_perm = token.resource();
326 &&& token.id() == core_token_id
327 &&& half_cell_perm.id() == frac_id
328 &&& half_cell_perm.resource().id() == cell_id
329 &&& token.has_resource()
330 &&& half_cell_perm.frac() == 1
331 &&& half_cell_perm.has_authority()
332 &&& token.wf()
333}
334
335impl<T, G> RwLock<T, G> {
336 pub const fn new(val: T) -> Self {
338 let (val, Tracked(perm)) = PCell::new(val);
339
340 proof {
342 lemma_consts_properties();
343 }
344 let tracked mut frac_perm = Count::<PointsTo<T>>::alloc(perm);
345 let tracked read_half_cell_perm = frac_perm.split(1int);
346 let ghost frac_id = frac_perm.id();
347 let tracked mut core_token = SumResource::alloc_left(frac_perm);
348 let tracked read_retract_token = TokenResource::<MAX_READER_MASK>::alloc(());
349 let tracked upread_retract_token = UniqueToken::alloc(());
350 let tracked upreader_guard_token = core_token.split_one_left_owner();
351 let tracked left_token = core_token.split_one_left_knowledge();
352 let tracked read_guard_token = CountResource::<ReadPerm<T>, MAX_READER>::alloc(
353 (read_half_cell_perm, left_token),
354 );
355 let ghost ghost_id = RwId {
356 frac_id,
357 core_token_id: core_token.id(),
358 upread_retract_token_id: upread_retract_token.id(),
359 read_retract_token_id: read_retract_token.id(),
360 read_guard_token_id: read_guard_token.id(),
361 };
362 let tracked perms = RwPerms {
363 core_token,
364 read_retract_token,
365 upread_retract_token: Some(upread_retract_token),
366 upreader_guard_token: Some(upreader_guard_token),
367 read_guard_token,
368 };
369
370 Self {
371 guard: PhantomData,
372 lock: AtomicUsize::new(Ghost((val, PhantomData, Ghost(ghost_id))), 0, Tracked(perms)),
374 val: val,
376 ghost_id: Ghost(ghost_id),
377 }
378 }
379}
380
381#[verus_verify]
382impl<T , G: SpinGuardian> RwLock<T, G> {
383 #[verifier::exec_allows_no_decreases_clause]
390 pub fn read(&self) -> RwLockReadGuard<'_, T, G> {
391 loop {
392 if let Some(readguard) = self.try_read() {
393 return readguard;
394 } else {
395 core::hint::spin_loop();
396 }
397 }
398 }
399
400 #[verifier::exec_allows_no_decreases_clause]
407 pub fn write(&self) -> RwLockWriteGuard<'_, T, G> {
408 loop {
409 if let Some(writeguard) = self.try_write() {
410 return writeguard;
411 } else {
412 core::hint::spin_loop();
413 }
414 }
415 }
416
417 #[verifier::exec_allows_no_decreases_clause]
428 pub fn upread(&self) -> RwLockUpgradeableGuard<'_, T, G> {
429 loop {
430 if let Some(guard) = self.try_upread() {
431 return guard;
432 } else {
433 core::hint::spin_loop();
434 }
435 }
436 }
437
438 #[verus_spec]
442 pub fn try_read(&self) -> Option<RwLockReadGuard<'_, T, G>> {
443 proof_decl!{
444 let tracked mut read_token: Option<Count<ReadPerm<T>,MAX_READER>> = None;
445 let tracked mut retract_read_token: Option<Token<MAX_READER_MASK>> = None;
446 }
447 proof!{
448 use_type_invariant(self);
449 lemma_consts_properties();
450 }
451 let guard = G::read_guard();
452
453 let lock =
455 atomic_with_ghost!(
456 self.lock => fetch_add(READER);
457 update prev -> next;
458 ghost g => {
459 let prev_usize = prev as usize;
460 let next_usize = next as usize;
461 assume (no_max_reader_overflow(prev_usize));
462 lemma_consts_properties_value(prev_usize);
463 lemma_consts_properties_prev_next(prev_usize, next_usize);
464 if prev_usize & (WRITER | MAX_READER | BEING_UPGRADED) == 0 {
465 read_token = Some(g.read_guard_token.split_one());
466 } else {
467 retract_read_token = Some(g.read_retract_token.split_one());
468 }
469 }
470 );
471 if lock & (WRITER | MAX_READER | BEING_UPGRADED) == 0 {
472 Some(
473 RwLockReadGuard {
474 inner: self,
475 guard,
476 tracked_token: Tracked(read_token.tracked_unwrap()),
477 },
478 )
479 } else {
480 atomic_with_ghost!(
482 self.lock => fetch_sub(READER);
483 update prev -> next;
484 ghost g => {
485 let prev_usize = prev as usize;
486 let next_usize = next as usize;
487 lemma_consts_properties_value(next_usize);
488 lemma_consts_properties_prev_next(prev_usize, next_usize);
489 g.read_retract_token.combine(retract_read_token.tracked_unwrap());
490 }
491 );
492 None
493 }
494 }
495
496 #[verus_spec]
500 pub fn try_write(&self) -> Option<RwLockWriteGuard<'_, T, G>> {
501 proof_decl!{
502 let tracked mut guard_perm: Option<PointsTo<T>> = None;
503 let tracked mut guard_token: Option<OneRightKnowledge<HalfPerm<T>, NoPerm<T>, 3>> = None;
504 }
505 proof!{
506 use_type_invariant(self);
507 lemma_consts_properties();
508 }
509
510 let guard = G::guard();
511 if atomic_with_ghost!(
516 self.lock => compare_exchange(0, WRITER);
517 update prev -> next;
518 returning res;
519 ghost g => {
520 let prev_usize = prev as usize;
521 let next_usize = next as usize;
522 if res is Ok {
523 let tracked read_resource = g.read_guard_token.take_resource();
525 let tracked (read_half_cell_perm, left_token) = read_resource;
526 g.core_token.join_one_left_knowledge(left_token);
527 let tracked upreader_guard_token = g.upreader_guard_token.tracked_take();
529 g.core_token.join_one_left_owner(upreader_guard_token);
530 let tracked mut pointsto = g.core_token.take_resource_left();
532 pointsto.combine(read_half_cell_perm);
533 let tracked (pointsto, empty) = pointsto.take_resource();
534 guard_perm = Some(pointsto);
535 g.core_token.change_to_right(empty);
536 guard_token = Some(g.core_token.split_one_right_knowledge());
537 }
538 }
539 ).is_ok() {
540 Some(
541 RwLockWriteGuard {
542 inner: self,
543 guard,
544 tracked_perm: Tracked(guard_perm.tracked_unwrap()),
545 tracked_token: Tracked(guard_token.tracked_unwrap()),
546 },
547 )
548 } else {
549 None
550 }
551 }
552
553 pub fn try_upread(&self) -> Option<RwLockUpgradeableGuard<'_, T, G>> {
557 proof_decl!{
558 let tracked mut upgrade_guard_token: Option<OneLeftOwner<HalfPerm<T>, NoPerm<T>, 3>> = None;
559 let tracked mut retract_upgrade_token: Option<UniqueToken> = None;
560 }
561 proof!{
562 use_type_invariant(self);
563 lemma_consts_properties();
564 }
565 let guard = G::guard();
566 let lock =
568 atomic_with_ghost!(
569 self.lock => fetch_or(UPGRADEABLE_READER);
570 update prev -> next;
571 ghost g => {
572 lemma_consts_properties_value(prev);
573 lemma_consts_properties_prev_next(prev, next);
574 if prev & (WRITER | UPGRADEABLE_READER) == 0 {
575 upgrade_guard_token = Some(g.upreader_guard_token.tracked_take());
576 }
577 else if prev & (WRITER | UPGRADEABLE_READER) == WRITER {
578 retract_upgrade_token = Some(g.upread_retract_token.tracked_take());
579 }
580 }
581 )
582 & (WRITER | UPGRADEABLE_READER);
583 if lock == 0 {
584 return Some(
585 RwLockUpgradeableGuard {
586 inner: self,
587 guard,
588 tracked_token: Tracked(upgrade_guard_token.tracked_unwrap()),
589 },
590 );
591 } else if lock == WRITER {
592 atomic_with_ghost!(
594 self.lock => fetch_sub(UPGRADEABLE_READER);
595 update prev -> next;
596 ghost g => {
597 let prev_usize = prev as usize;
598 let next_usize = next as usize;
599 lemma_consts_properties_value(prev_usize);
600 lemma_consts_properties_prev_next(prev_usize, next_usize);
601 if g.upread_retract_token is Some {
602 let tracked mut token = retract_upgrade_token.tracked_unwrap();
603 token.validate_with_other(g.upread_retract_token.tracked_borrow());
604 }
605 else{
606 g.upread_retract_token= retract_upgrade_token;
607 }
608 }
609 );
610 }
611 None
612 }
613}
614
615#[verifier::external]
644unsafe impl<T: Send, G> Send for RwLock<T, G> {
645
646}
647
648#[verifier::external]
649unsafe impl<T: Send + Sync, G> Sync for RwLock<T, G> {
650
651}
652
653impl<T , G: SpinGuardian> !Send for RwLockWriteGuard<'_, T, G> {
654
655}
656
657#[verifier::external]
658unsafe impl<T: Sync, G: SpinGuardian> Sync for RwLockWriteGuard<'_, T, G> {
659
660}
661
662impl<T , G: SpinGuardian> !Send for RwLockReadGuard<'_, T, G> {
663
664}
665
666#[verifier::external]
667unsafe impl<T: Sync, G: SpinGuardian> Sync for RwLockReadGuard<'_, T, G> {
668
669}
670
671impl<T , G: SpinGuardian> !Send for RwLockUpgradeableGuard<'_, T, G> {
672
673}
674
675#[verifier::external]
676unsafe impl<T: Sync, G: SpinGuardian> Sync for RwLockUpgradeableGuard<'_, T, G> {
677
678}
679
680#[verifier::reject_recursive_types(T)]
682#[verifier::reject_recursive_types(G)]
683#[clippy::has_significant_drop]
684#[must_use]
685#[verus_verify]
686pub struct RwLockReadGuard<'a, T , G: SpinGuardian> {
687 guard: G::ReadGuard,
688 inner: &'a RwLock<T, G>,
689 tracked_token: Tracked<Count<ReadPerm<T>, MAX_READER>>,
690}
691
692impl<'a, T, G: SpinGuardian> RwLockReadGuard<'a, T, G> {
701 #[verifier::type_invariant]
702 pub closed spec fn type_inv(self) -> bool {
703 let resource = self.tracked_token@.resource();
704 let read_half_cell_perm = resource.0;
705 let mode_knowledge = resource.1;
706 &&& self.inner.core_token_id() == mode_knowledge.id()
707 &&& self.inner.frac_id() == read_half_cell_perm.id()
708 &&& self.inner.cell_id() == read_half_cell_perm.resource().id()
709 &&& self.tracked_token@.id() == self.inner.read_guard_token_id()
710 &&& read_half_cell_perm.frac() == 1
711 &&& self.tracked_token@.frac() == 1
712 }
713
714 pub closed spec fn value(self) -> T {
716 *self.tracked_token@.resource().0.resource().value()
717 }
718
719 pub open spec fn view(self) -> T {
721 self.value()
722 }
723}
724
725impl<T , G: SpinGuardian> Deref for RwLockReadGuard<'_, T, G> {
726 type Target = T;
727
728 #[verus_spec(returns self.view())]
729 fn deref(&self) -> &T {
730 proof!{
731 use_type_invariant(self);
732 }
733 self.inner.val.borrow(
737 Tracked(self.tracked_token.borrow().tracked_borrow().0.tracked_borrow()),
738 )
739 }
740}
741
742#[verus_verify]
751impl<T , G: SpinGuardian> RwLockReadGuard<'_, T, G> {
752 #[verus_spec]
754 fn drop(self) {
755 proof! {
756 use_type_invariant(&self);
757 use_type_invariant(self.inner);
758 lemma_consts_properties();
759 }
760 proof_decl! {
761 let tracked token = self.tracked_token.get();
762 }
763 atomic_with_ghost!(
765 self.inner.lock => fetch_sub(READER);
766 update prev -> next;
767 ghost g => {
768 let prev_usize = prev as usize;
769 let next_usize = next as usize;
770 assume (no_max_reader_overflow(prev_usize));
771 lemma_consts_properties_value(next_usize);
772 lemma_consts_properties_prev_next(prev_usize, next_usize);
773 g.core_token.validate_with_one_left_knowledge(&token.tracked_borrow().1);
774 g.read_guard_token.combine(token);
775 }
776 );
777 }
778}
779
780#[verifier::reject_recursive_types(T)]
789#[verifier::reject_recursive_types(G)]
790pub struct RwLockWriteGuard<'a, T , G: SpinGuardian> {
791 guard: G::Guard,
792 inner: &'a RwLock<T, G>,
793 tracked_perm: Tracked<PointsTo<T>>,
795 tracked_token: Tracked<OneRightKnowledge<HalfPerm<T>, NoPerm<T>, 3>>,
796}
797
798impl<'a, T, G: SpinGuardian> RwLockWriteGuard<'a, T, G> {
799 #[verifier::type_invariant]
800 spec fn type_inv(self) -> bool {
801 &&& self.inner.cell_id() == self.tracked_perm@.id()
802 &&& self.inner.core_token_id() == self.tracked_token@.id()
803 }
804
805 pub closed spec fn value(self) -> T {
807 *self.tracked_perm@.value()
808 }
809
810 pub open spec fn view(self) -> T {
812 self.value()
813 }
814}
815
816impl<T , G: SpinGuardian> Deref for RwLockWriteGuard<'_, T, G> {
824 type Target = T;
825
826 #[verus_spec(returns self.view())]
827 fn deref(&self) -> &T {
828 proof!{
829 use_type_invariant(self);
830 }
831 self.inner.val.borrow(Tracked(self.tracked_perm.borrow()))
835 }
836}
837
838#[verus_verify]
839impl<T , G: SpinGuardian> DerefMut for RwLockWriteGuard<'_, T, G> {
840 #[verus_spec(ret =>
841 ensures
842 final(self).view() == *final(ret),
843 old(self).view() == *ret,
844 )]
845 fn deref_mut(&mut self) -> &mut Self::Target {
846 proof!{
847 use_type_invariant(&*self);
848 }
849 self.inner.val.borrow_mut(Tracked(&mut *self.tracked_perm))
851 }
852}
853
854impl<T , G: SpinGuardian> RwLockWriteGuard<'_, T, G> {
862 pub fn drop(self) {
864 proof!{
865 use_type_invariant(&self);
866 use_type_invariant(self.inner);
867 lemma_consts_properties();
868 }
869 proof_decl! {
870 let tracked mut perm = self.tracked_perm.get();
871 let tracked token = self.tracked_token.get();
872 }
873 atomic_with_ghost!{
875 self.inner.lock => fetch_and(!WRITER);
876 update prev -> next;
877 ghost g => {
878 let prev_usize = prev as usize;
879 let next_usize = next as usize;
880 lemma_consts_properties_prev_next(prev_usize, next_usize);
881 lemma_consts_properties_value(next_usize);
882 g.core_token.validate_with_one_right_knowledge(&token);
883 g.core_token.join_one_right_knowledge(token);
884 let tracked empty = g.core_token.take_resource_right();
885 let tracked mut full = empty.put_resource(perm);
886 let tracked read_half_cell_perm = full.split(1int);
887 g.core_token.change_to_left(full);
888 let tracked upreader_guard_token = g.core_token.split_one_left_owner();
889 g.upreader_guard_token = Some(upreader_guard_token);
890 let tracked left_token = g.core_token.split_one_left_knowledge();
891 g.read_guard_token.put_resource((read_half_cell_perm, left_token));
892 }
893 };
894 }
895}
896
897#[verifier::reject_recursive_types(T)]
907#[verifier::reject_recursive_types(G)]
908pub struct RwLockUpgradeableGuard<'a, T , G: SpinGuardian> {
909 guard: G::Guard,
910 inner: &'a RwLock<T, G>,
911 tracked_token: Tracked<OneLeftOwner<HalfPerm<T>, NoPerm<T>, 3>>,
912}
913
914impl<'a, T, G: SpinGuardian> RwLockUpgradeableGuard<'a, T, G> {
922 #[verifier::type_invariant]
923 pub closed spec fn type_inv(self) -> bool {
924 wf_upgradeable_guard_token(
925 self.inner.core_token_id(),
926 self.inner.frac_id(),
927 self.inner.cell_id(),
928 self.tracked_token@,
929 )
930 }
931
932 pub closed spec fn value(self) -> T {
934 *self.tracked_token@.resource().resource().value()
935 }
936
937 pub open spec fn view(self) -> T {
939 self.value()
940 }
941}
942
943impl<'a, T , G: SpinGuardian> RwLockUpgradeableGuard<'a, T, G> {
944 #[verifier::exec_allows_no_decreases_clause]
950 pub fn upgrade( self) -> RwLockWriteGuard<'a, T, G> {
951 let mut this = self;
952 proof! {
953 use_type_invariant(&this);
954 use_type_invariant(&this.inner);
955 lemma_consts_properties();
956 }
957 atomic_with_ghost!(
959 this.inner.lock => fetch_or(BEING_UPGRADED);
960 update prev -> next;
961 ghost g => {
962 lemma_consts_properties_prev_next(prev, next);
963 }
964 );
965 loop {
966 this =
968 match this.try_upgrade() {
969 Ok(guard) => return guard,
970 Err(e) => e,
971 };
972 }
973 }
974
975 fn try_upgrade( self) -> Result<RwLockWriteGuard<'a, T, G>, Self> {
983 proof! {
984 use_type_invariant(&self);
985 use_type_invariant(self.inner);
986 lemma_consts_properties();
987 }
988 let mut this = self;
989 proof_decl! {
990 let tracked mut upread_guard_token = this.tracked_token.get();
991 let tracked mut write_perm: Option<PointsTo<T>> = None;
992 let tracked mut err_upread_guard_token: Option<OneLeftOwner<HalfPerm<T>, NoPerm<T>, 3>> = None;
993 let tracked mut retract_upgrade_token: Option<UniqueToken> = None;
994 let tracked mut write_guard_token = None;
995 }
996
997 let res =
1004 atomic_with_ghost!(
1005 this.inner.lock => compare_exchange(UPGRADEABLE_READER | BEING_UPGRADED, WRITER | UPGRADEABLE_READER);
1006 update prev -> next;
1007 returning res;
1008 ghost g => {
1009 lemma_consts_properties_prev_next(prev, next);
1010 if res is Ok {
1011 g.core_token.validate_with_one_left_owner(&upread_guard_token);
1012 if g.upreader_guard_token is Some {
1013 upread_guard_token.validate_with_one_left_owner(g.upreader_guard_token.tracked_borrow());
1014 }
1015 g.core_token.join_one_left_owner(upread_guard_token);
1016 let tracked read_resource = g.read_guard_token.take_resource();
1017 let tracked (read_half_cell_perm, left_token) = read_resource;
1018 g.core_token.join_one_left_knowledge(left_token);
1019 let tracked mut pointsto = g.core_token.take_resource_left();
1020 pointsto.combine(read_half_cell_perm);
1021 let tracked (pointsto, empty) = pointsto.take_resource();
1022 write_perm = Some(pointsto);
1023 g.core_token.change_to_right(empty);
1024 write_guard_token = Some(g.core_token.split_one_right_knowledge());
1025 retract_upgrade_token = Some(g.upread_retract_token.tracked_take());
1026 } else {
1027 err_upread_guard_token = Some(upread_guard_token);
1028 }
1029 }
1030 );
1031 if res.is_ok() {
1032 let inner = this.inner;
1033 let guard = this.guard.transfer_to();
1034 atomic_with_ghost!(
1036 inner.lock => fetch_sub(UPGRADEABLE_READER);
1037 update prev -> next;
1038 ghost g => {
1039 let prev_usize = prev as usize;
1040 let next_usize = next as usize;
1041 lemma_consts_properties_value(prev_usize);
1042 lemma_consts_properties_prev_next(prev_usize, next_usize);
1043 let tracked mut token = retract_upgrade_token.tracked_unwrap();
1044 if g.upread_retract_token is Some {
1045 token.validate_with_other(g.upread_retract_token.tracked_borrow());
1046 }
1047 g.upread_retract_token = Some(token);
1048 }
1049 );
1050 Ok(
1051 RwLockWriteGuard {
1052 inner,
1053 guard,
1054 tracked_perm: Tracked(write_perm.tracked_unwrap()),
1055 tracked_token: Tracked(write_guard_token.tracked_unwrap()),
1056 },
1057 )
1058 } else {
1059 Err(
1060 RwLockUpgradeableGuard {
1061 inner: this.inner,
1062 guard: this.guard,
1063 tracked_token: Tracked(err_upread_guard_token.tracked_unwrap()),
1064 },
1065 )
1066 }
1067 }
1068}
1069
1070impl<T , G: SpinGuardian> Deref for RwLockUpgradeableGuard<'_, T, G> {
1071 type Target = T;
1072
1073 #[verus_spec(returns self.view())]
1074 fn deref(&self) -> &T {
1075 proof!{
1076 use_type_invariant(self);
1077 }
1078 self.inner.val.borrow(
1082 Tracked(self.tracked_token.borrow().tracked_borrow().tracked_borrow()),
1083 )
1084 }
1085}
1086
1087impl<T , G: SpinGuardian> RwLockUpgradeableGuard<'_, T, G> {
1095 pub fn drop(self) {
1097 proof! {
1098 use_type_invariant(&self);
1099 use_type_invariant(self.inner);
1100 lemma_consts_properties();
1101 }
1102 proof_decl!{
1103 let tracked guard_token = self.tracked_token.get();
1104 }
1105 atomic_with_ghost!(
1107 self.inner.lock => fetch_sub(UPGRADEABLE_READER);
1108 update prev -> next;
1109 ghost g => {
1110 let prev_usize = prev as usize;
1111 let next_usize = next as usize;
1112 lemma_consts_properties_value(prev_usize);
1113 lemma_consts_properties_prev_next(prev_usize, next_usize);
1114 g.core_token.validate_with_one_left_owner(&guard_token);
1115 if g.upreader_guard_token is Some {
1116 guard_token.validate_with_one_left_owner(g.upreader_guard_token.tracked_borrow());
1117 assert(false);
1118 } else {
1119 g.upreader_guard_token= Some(guard_token);
1120 }
1121 }
1122 );
1123 }
1124}
1125
1126#[verifier::bit_vector]
1135proof fn lemma_consts_properties()
1136 ensures
1137 0 & WRITER == 0,
1138 0 & UPGRADEABLE_READER == 0,
1139 0 & BEING_UPGRADED == 0,
1140 0 & READER_MASK == 0,
1141 0 & MAX_READER_MASK == 0,
1142 0 & MAX_READER == 0,
1143 0 & READER == 0,
1144 WRITER == 0x8000_0000_0000_0000,
1145 UPGRADEABLE_READER == 0x4000_0000_0000_0000,
1146 BEING_UPGRADED == 0x2000_0000_0000_0000,
1147 READER_MASK == 0x0FFF_FFFF_FFFF_FFFF,
1148 MAX_READER_MASK == 0x1FFF_FFFF_FFFF_FFFF,
1149 MAX_READER == 0x1000_0000_0000_0000,
1150 WRITER & WRITER == WRITER,
1151 WRITER & !WRITER == 0,
1152 WRITER & BEING_UPGRADED == 0,
1153 WRITER & READER_MASK == 0,
1154 WRITER & MAX_READER_MASK == 0,
1155 WRITER & MAX_READER == 0,
1156 WRITER & UPGRADEABLE_READER == 0,
1157 BEING_UPGRADED & WRITER == 0,
1158 BEING_UPGRADED & UPGRADEABLE_READER == 0,
1159 UPGRADEABLE_READER & BEING_UPGRADED == 0,
1160 UPGRADEABLE_READER & READER_MASK == 0,
1161 UPGRADEABLE_READER & MAX_READER_MASK == 0,
1162 UPGRADEABLE_READER & MAX_READER == 0,
1163 BEING_UPGRADED & READER_MASK == 0,
1164 BEING_UPGRADED & MAX_READER_MASK == 0,
1165 BEING_UPGRADED & MAX_READER == 0,
1166 (UPGRADEABLE_READER | BEING_UPGRADED) & WRITER == 0,
1167 (UPGRADEABLE_READER | BEING_UPGRADED) & UPGRADEABLE_READER == UPGRADEABLE_READER,
1168 (UPGRADEABLE_READER | BEING_UPGRADED) & BEING_UPGRADED == BEING_UPGRADED,
1169 (UPGRADEABLE_READER | BEING_UPGRADED) & READER_MASK == 0,
1170 (UPGRADEABLE_READER | BEING_UPGRADED) & MAX_READER_MASK == 0,
1171 (UPGRADEABLE_READER | BEING_UPGRADED) & MAX_READER == 0,
1172 (WRITER | UPGRADEABLE_READER) & WRITER == WRITER,
1173 (WRITER | UPGRADEABLE_READER) & UPGRADEABLE_READER == UPGRADEABLE_READER,
1174 (WRITER | UPGRADEABLE_READER) & BEING_UPGRADED == 0,
1175 (WRITER | UPGRADEABLE_READER) & READER_MASK == 0,
1176 (WRITER | UPGRADEABLE_READER) & MAX_READER_MASK == 0,
1177 (WRITER | UPGRADEABLE_READER) & MAX_READER == 0,
1178{
1179}
1180
1181#[verifier::bit_vector]
1182proof fn lemma_consts_properties_value(prev: usize)
1183 ensures
1184 no_max_reader_overflow(prev) ==> prev + READER <= usize::MAX,
1185 prev & (WRITER | MAX_READER | BEING_UPGRADED) == 0 ==> {
1186 &&& prev & WRITER == 0
1187 &&& prev & BEING_UPGRADED == 0
1188 &&& prev & MAX_READER == 0
1189 },
1190 prev & (WRITER | UPGRADEABLE_READER) == 0 ==> {
1191 &&& prev & WRITER == 0
1192 &&& prev & UPGRADEABLE_READER == 0
1193 },
1194 prev & MAX_READER == 0 ==> prev & READER_MASK == prev & MAX_READER_MASK,
1195 prev & MAX_READER != 0 ==> prev & MAX_READER_MASK >= MAX_READER,
1196 prev & (WRITER | UPGRADEABLE_READER) == WRITER ==> {
1197 &&& prev & UPGRADEABLE_READER == 0
1198 &&& prev & WRITER == WRITER
1199 },
1200 prev & UPGRADEABLE_READER != 0 ==> prev >= UPGRADEABLE_READER,
1201 prev & UPGRADEABLE_READER == 0 ==> {
1202 ||| prev & (WRITER | UPGRADEABLE_READER) == 0
1203 ||| prev & (WRITER | UPGRADEABLE_READER) == WRITER
1204 },
1205{
1206}
1207
1208#[verifier::bit_vector]
1209proof fn lemma_consts_properties_prev_next(prev: usize, next: usize)
1210 ensures
1211 prev & READER_MASK < MAX_READER,
1212 next == prev | UPGRADEABLE_READER ==> {
1213 &&& next & UPGRADEABLE_READER != 0
1214 &&& next & WRITER == prev & WRITER
1215 &&& next & READER_MASK == prev & READER_MASK
1216 &&& next & MAX_READER_MASK == prev & MAX_READER_MASK
1217 &&& next & MAX_READER == prev & MAX_READER
1218 &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1219 },
1220 next == prev | BEING_UPGRADED ==> {
1221 &&& next & BEING_UPGRADED != 0
1222 &&& next & WRITER == prev & WRITER
1223 &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1224 &&& next & READER_MASK == prev & READER_MASK
1225 &&& next & MAX_READER_MASK == prev & MAX_READER_MASK
1226 &&& next & MAX_READER == prev & MAX_READER
1227 },
1228 next == prev - UPGRADEABLE_READER && prev & UPGRADEABLE_READER != 0 ==> {
1229 &&& next & UPGRADEABLE_READER == 0
1230 &&& next & WRITER == prev & WRITER
1231 &&& next & READER_MASK == prev & READER_MASK
1232 &&& next & MAX_READER_MASK == prev & MAX_READER_MASK
1233 &&& next & MAX_READER == prev & MAX_READER
1234 &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1235 },
1236 next == prev - READER && prev & READER_MASK != 0 ==> {
1237 &&& next & READER_MASK == (prev & READER_MASK) - READER
1238 &&& next & MAX_READER_MASK == (prev & MAX_READER_MASK) - READER
1239 &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1240 &&& next & WRITER == prev & WRITER
1241 &&& next & MAX_READER == prev & MAX_READER
1242 &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1243 },
1244 next == prev - READER && prev & MAX_READER_MASK != 0 ==> {
1245 &&& next & MAX_READER_MASK == (prev & MAX_READER_MASK) - READER
1246 &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1247 &&& next & WRITER == prev & WRITER
1248 &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1249 },
1250 next == prev + READER && no_max_reader_overflow(prev) ==> {
1251 &&& next & READER_MASK == if (prev & READER_MASK) + READER == MAX_READER {
1252 0
1253 } else {
1254 (prev & READER_MASK) + READER
1255 }
1256 &&& next & MAX_READER_MASK == (prev & MAX_READER_MASK) + READER
1257 &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1258 &&& next & WRITER == prev & WRITER
1259 &&& next & MAX_READER == if (prev & READER_MASK) + READER == MAX_READER {
1260 MAX_READER
1261 } else {
1262 prev & MAX_READER
1263 }
1264 &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1265 },
1266 next == prev & !WRITER ==> {
1267 &&& next & WRITER == 0
1268 &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1269 &&& next & READER_MASK == prev & READER_MASK
1270 &&& next & MAX_READER_MASK == prev & MAX_READER_MASK
1271 &&& next & MAX_READER == prev & MAX_READER
1272 &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1273 },
1274{
1275}
1276
1277}