1use vstd::atomic_ghost::*;
3use vstd::cell::{self, CellId, pcell::*};
4use vstd::prelude::*;
5use vstd::resource::Loc;
6#[cfg(feature = "irc11")]
7use vstd::thread_view::Objective;
8use vstd_extra::resource::ghost_resource::{count_auth::*, count_ghost::*, csum::*, excl::*};
9use vstd_extra::sum::*;
10use vstd_extra::{prelude::*, resource};
11
12use alloc::sync::Arc;
13use core::char::MAX;
14use core::{
15 cell::UnsafeCell,
16 fmt,
17 marker::PhantomData,
18 ops::{Deref, DerefMut},
19 sync::atomic::{
20 Ordering::{AcqRel, Acquire, Relaxed, Release},
22 },
23};
24
25use super::{
26 PreemptDisabled,
27 guard::{GuardTransfer, SpinGuardian},
28};
29
30verus! {
31
32type NoPerm<T> = EmptyCount<PointsTo<T>>;
34
35type HalfPerm<T> = Count<PointsTo<T>>;
37
38type ReadPerm<T> = (HalfPerm<T>, OneLeftKnowledge<HalfPerm<T>, NoPerm<T>, 3>);
40
41tracked struct RwPerms<T> {
42 core_token: SumResource<HalfPerm<T>, NoPerm<T>, 3>,
47 read_retract_token: TokenResource<MAX_READER_MASK>,
53 upread_retract_token: Option<UniqueToken>,
55 upreader_guard_token: Option<OneLeftOwner<HalfPerm<T>, NoPerm<T>, 3>>,
57 read_guard_token: CountResource<ReadPerm<T>, MAX_READER>,
59}
60
61#[cfg(feature = "irc11")]
62unsafe impl<T> Objective for RwPerms<T> {
63
64}
65
66ghost struct RwId {
67 core_token_id: Loc,
68 frac_id: Loc,
69 read_retract_token_id: Loc,
70 upread_retract_token_id: Loc,
71 read_guard_token_id: Loc,
72}
73
74pub closed spec fn no_max_reader_overflow(v: usize) -> bool {
80 v & MAX_READER_MASK < MAX_READER_MASK
81}
82
83struct_with_invariants! {
84pub struct RwLock<T , Guard > {
163 guard: PhantomData<Guard>,
164 lock: AtomicUsize<_, RwPerms<T>,_>,
170 val: PCell<T>,
172 ghost_id: Ghost<RwId>,
173}
174
175closed spec fn wf(self) -> bool {
177 invariant on lock with (val, guard, ghost_id) is (v: usize, g: RwPerms<T>) {
178 let has_writer_bit: bool = (v & WRITER) != 0;
180 let has_upgrade_bit: bool = (v & UPGRADEABLE_READER) != 0;
181 let has_max_reader_bit: bool = (v & MAX_READER) != 0;
182 let total_reader_bits: int = (v & MAX_READER_MASK) as int;
185 let reader_bits: int = if has_max_reader_bit { MAX_READER as int } else { (v & READER_MASK) as int };
189
190 let active_writer: bool = g.core_token.is_right();
198 let active_upgrade_guard: bool = !active_writer && g.upreader_guard_token is None;
200 let active_read_guards: int = if g.read_guard_token.is_resource_vacant() {
202 0
203 } else {
204 MAX_READER - g.read_guard_token.frac()
205 };
206 let pending_failed_upread_attempt: bool = g.upread_retract_token is None;
208 let failed_reader_attempts: int = MAX_READER_MASK - g.read_retract_token.frac();
210
211 &&& if g.core_token.is_left() {
212 let resource = g.read_guard_token.resource();
213 let read_half_cell_perm = resource.0;
214 let mode_knowledge = resource.1;
215 &&& !g.read_guard_token.is_resource_vacant()
216 &&& mode_knowledge.id() == ghost_id@.core_token_id
217 &&& read_half_cell_perm.id() == ghost_id@.frac_id
218 &&& read_half_cell_perm.resource().id() == val.id()
219 &&& read_half_cell_perm.frac() == 1
220 } else {
221 &&& g.upreader_guard_token is None
222 &&& g.read_guard_token.is_resource_vacant()
223 }
224 &&& has_upgrade_bit <==> (active_upgrade_guard || pending_failed_upread_attempt)
226 &&& !(active_upgrade_guard && pending_failed_upread_attempt)
228 &&& total_reader_bits == active_read_guards + failed_reader_attempts
230 &&& active_writer <==> has_writer_bit
232 &&& 0 <= active_read_guards <= reader_bits <= total_reader_bits
234 &&& !(active_writer && (active_read_guards + if active_upgrade_guard { 1int } else { 0 }) > 0)
236 &&& g.core_token.id() == ghost_id@.core_token_id
237 &&& g.core_token.wf()
238 &&& g.core_token.is_left() ==> {
239 &&& !g.core_token.is_resource_owner()
240 &&& g.core_token.frac() == 1
241 }
242 &&& g.core_token.is_right() ==> {
243 let empty = g.core_token.resource_right();
244 &&& empty.id() == ghost_id@.frac_id
245 &&& g.core_token.frac() == 2
246 &&& g.core_token.has_resource()
247 }
248 &&& g.read_retract_token.wf()
249 &&& g.read_retract_token.id() == ghost_id@.read_retract_token_id
250 &&& g.upread_retract_token is Some ==>
251 {
252 let token = g.upread_retract_token->0;
253 &&& token.wf()
254 &&& token.id() == ghost_id@.upread_retract_token_id
255 }
256 &&& g.upreader_guard_token is Some ==> {
257 let token = g.upreader_guard_token->0;
258 wf_upgradeable_guard_token(ghost_id@.core_token_id, ghost_id@.frac_id, val.id(), token)
259 }
260 &&& g.read_guard_token.wf()
261 &&& g.read_guard_token.id() == ghost_id@.read_guard_token_id
262 }
263}
264
265}
266
267const READER: usize = 1;
268
269const WRITER: usize = 1 << (usize::BITS - 1);
270
271const UPGRADEABLE_READER: usize = 1 << (usize::BITS - 2);
272
273const BEING_UPGRADED: usize = 1 << (usize::BITS - 3);
274
275const MAX_READER: usize = 1 << (usize::BITS - 4);
290
291const READER_MASK: usize = usize::MAX >> 4;
293
294const MAX_READER_MASK: usize = usize::MAX >> 3;
296
297impl<T, G> RwLock<T, G> {
298 pub closed spec fn cell_id(self) -> cell::CellId {
300 self.val.id()
301 }
302
303 pub closed spec fn core_token_id(self) -> Loc {
304 self.ghost_id@.core_token_id
305 }
306
307 pub closed spec fn frac_id(self) -> Loc {
308 self.ghost_id@.frac_id
309 }
310
311 pub closed spec fn upread_retract_token_id(self) -> Loc {
312 self.ghost_id@.upread_retract_token_id
313 }
314
315 pub closed spec fn read_guard_token_id(self) -> Loc {
316 self.ghost_id@.read_guard_token_id
317 }
318
319 #[verifier::type_invariant]
321 pub closed spec fn type_inv(self) -> bool {
322 self.wf()
323 }
324}
325
326closed spec fn wf_upgradeable_guard_token<T>(
327 core_token_id: Loc,
328 frac_id: Loc,
329 cell_id: CellId,
330 token: OneLeftOwner<HalfPerm<T>, NoPerm<T>, 3>,
331) -> bool {
332 let half_cell_perm = token.resource();
333 &&& token.id() == core_token_id
334 &&& half_cell_perm.id() == frac_id
335 &&& half_cell_perm.resource().id() == cell_id
336 &&& token.has_resource()
337 &&& half_cell_perm.frac() == 1
338 &&& half_cell_perm.has_authority()
339 &&& token.wf()
340}
341
342impl<T, G> RwLock<T, G> {
343 pub const fn new(val: T) -> Self {
345 let (val, Tracked(perm)) = PCell::new(val);
346
347 proof {
349 lemma_consts_properties();
350 }
351 let tracked mut frac_perm = Count::<PointsTo<T>>::alloc(perm);
352 let tracked read_half_cell_perm = frac_perm.split(1int);
353 let ghost frac_id = frac_perm.id();
354 let tracked mut core_token = SumResource::alloc_left(frac_perm);
355 let tracked read_retract_token = TokenResource::<MAX_READER_MASK>::alloc(());
356 let tracked upread_retract_token = UniqueToken::alloc(());
357 let tracked upreader_guard_token = core_token.split_one_left_owner();
358 let tracked left_token = core_token.split_one_left_knowledge();
359 let tracked read_guard_token = CountResource::<ReadPerm<T>, MAX_READER>::alloc(
360 (read_half_cell_perm, left_token),
361 );
362 let ghost ghost_id = RwId {
363 frac_id,
364 core_token_id: core_token.id(),
365 upread_retract_token_id: upread_retract_token.id(),
366 read_retract_token_id: read_retract_token.id(),
367 read_guard_token_id: read_guard_token.id(),
368 };
369 let tracked perms = RwPerms {
370 core_token,
371 read_retract_token,
372 upread_retract_token: Some(upread_retract_token),
373 upreader_guard_token: Some(upreader_guard_token),
374 read_guard_token,
375 };
376
377 Self {
378 guard: PhantomData,
379 lock: AtomicUsize::new(Ghost((val, PhantomData, Ghost(ghost_id))), 0, Tracked(perms)),
381 val: val,
383 ghost_id: Ghost(ghost_id),
384 }
385 }
386}
387
388#[verus_verify]
389impl<T , G: SpinGuardian> RwLock<T, G> {
390 #[verifier::exec_allows_no_decreases_clause]
397 pub fn read(&self) -> RwLockReadGuard<'_, T, G> {
398 loop {
399 if let Some(readguard) = self.try_read() {
400 return readguard;
401 } else {
402 core::hint::spin_loop();
403 }
404 }
405 }
406
407 #[verifier::exec_allows_no_decreases_clause]
414 pub fn write(&self) -> RwLockWriteGuard<'_, T, G> {
415 loop {
416 if let Some(writeguard) = self.try_write() {
417 return writeguard;
418 } else {
419 core::hint::spin_loop();
420 }
421 }
422 }
423
424 #[verifier::exec_allows_no_decreases_clause]
435 pub fn upread(&self) -> RwLockUpgradeableGuard<'_, T, G> {
436 loop {
437 if let Some(guard) = self.try_upread() {
438 return guard;
439 } else {
440 core::hint::spin_loop();
441 }
442 }
443 }
444
445 #[verus_spec]
449 pub fn try_read(&self) -> Option<RwLockReadGuard<'_, T, G>> {
450 proof_decl!{
451 let tracked mut read_token: Option<Count<ReadPerm<T>,MAX_READER>> = None;
452 let tracked mut retract_read_token: Option<Token<MAX_READER_MASK>> = None;
453 }
454 proof!{
455 use_type_invariant(self);
456 lemma_consts_properties();
457 }
458 let guard = G::read_guard();
459
460 let lock =
462 atomic_with_ghost!(
463 self.lock => fetch_add(READER);
464 update prev -> next;
465 ghost g => {
466 let prev_usize = prev as usize;
467 let next_usize = next as usize;
468 assume (no_max_reader_overflow(prev_usize));
469 lemma_consts_properties_value(prev_usize);
470 lemma_consts_properties_prev_next(prev_usize, next_usize);
471 if prev_usize & (WRITER | MAX_READER | BEING_UPGRADED) == 0 {
472 read_token = Some(g.read_guard_token.split_one());
473 } else {
474 retract_read_token = Some(g.read_retract_token.split_one());
475 }
476 }
477 );
478 if lock & (WRITER | MAX_READER | BEING_UPGRADED) == 0 {
479 Some(
480 RwLockReadGuard {
481 inner: self,
482 guard,
483 tracked_token: Tracked(read_token.tracked_unwrap()),
484 },
485 )
486 } else {
487 atomic_with_ghost!(
489 self.lock => fetch_sub(READER);
490 update prev -> next;
491 ghost g => {
492 let prev_usize = prev as usize;
493 let next_usize = next as usize;
494 lemma_consts_properties_value(next_usize);
495 lemma_consts_properties_prev_next(prev_usize, next_usize);
496 g.read_retract_token.combine(retract_read_token.tracked_unwrap());
497 }
498 );
499 None
500 }
501 }
502
503 #[verus_spec]
507 pub fn try_write(&self) -> Option<RwLockWriteGuard<'_, T, G>> {
508 proof_decl!{
509 let tracked mut guard_perm: Option<PointsTo<T>> = None;
510 let tracked mut guard_token: Option<OneRightKnowledge<HalfPerm<T>, NoPerm<T>, 3>> = None;
511 }
512 proof!{
513 use_type_invariant(self);
514 lemma_consts_properties();
515 }
516
517 let guard = G::guard();
518 if atomic_with_ghost!(
523 self.lock => compare_exchange(0, WRITER);
524 update prev -> next;
525 returning res;
526 ghost g => {
527 let prev_usize = prev as usize;
528 let next_usize = next as usize;
529 if res is Ok {
530 let tracked read_resource = g.read_guard_token.take_resource();
532 let tracked (read_half_cell_perm, left_token) = read_resource;
533 g.core_token.join_one_left_knowledge(left_token);
534 let tracked upreader_guard_token = g.upreader_guard_token.tracked_take();
536 g.core_token.join_one_left_owner(upreader_guard_token);
537 let tracked mut pointsto = g.core_token.take_resource_left();
539 pointsto.combine(read_half_cell_perm);
540 let tracked (pointsto, empty) = pointsto.take_resource();
541 guard_perm = Some(pointsto);
542 g.core_token.change_to_right(empty);
543 guard_token = Some(g.core_token.split_one_right_knowledge());
544 }
545 }
546 ).is_ok() {
547 Some(
548 RwLockWriteGuard {
549 inner: self,
550 guard,
551 tracked_perm: Tracked(guard_perm.tracked_unwrap()),
552 tracked_token: Tracked(guard_token.tracked_unwrap()),
553 },
554 )
555 } else {
556 None
557 }
558 }
559
560 pub fn try_upread(&self) -> Option<RwLockUpgradeableGuard<'_, T, G>> {
564 proof_decl!{
565 let tracked mut upgrade_guard_token: Option<OneLeftOwner<HalfPerm<T>, NoPerm<T>, 3>> = None;
566 let tracked mut retract_upgrade_token: Option<UniqueToken> = None;
567 }
568 proof!{
569 use_type_invariant(self);
570 lemma_consts_properties();
571 }
572 let guard = G::guard();
573 let lock =
575 atomic_with_ghost!(
576 self.lock => fetch_or(UPGRADEABLE_READER);
577 update prev -> next;
578 ghost g => {
579 lemma_consts_properties_value(prev);
580 lemma_consts_properties_prev_next(prev, next);
581 if prev & (WRITER | UPGRADEABLE_READER) == 0 {
582 upgrade_guard_token = Some(g.upreader_guard_token.tracked_take());
583 }
584 else if prev & (WRITER | UPGRADEABLE_READER) == WRITER {
585 retract_upgrade_token = Some(g.upread_retract_token.tracked_take());
586 }
587 }
588 )
589 & (WRITER | UPGRADEABLE_READER);
590 if lock == 0 {
591 return Some(
592 RwLockUpgradeableGuard {
593 inner: self,
594 guard,
595 tracked_token: Tracked(upgrade_guard_token.tracked_unwrap()),
596 },
597 );
598 } else if lock == WRITER {
599 atomic_with_ghost!(
601 self.lock => fetch_sub(UPGRADEABLE_READER);
602 update prev -> next;
603 ghost g => {
604 let prev_usize = prev as usize;
605 let next_usize = next as usize;
606 lemma_consts_properties_value(prev_usize);
607 lemma_consts_properties_prev_next(prev_usize, next_usize);
608 if g.upread_retract_token is Some {
609 let tracked mut token = retract_upgrade_token.tracked_unwrap();
610 token.validate_with_other(g.upread_retract_token.tracked_borrow());
611 }
612 else{
613 g.upread_retract_token= retract_upgrade_token;
614 }
615 }
616 );
617 }
618 None
619 }
620}
621
622#[verifier::external]
651unsafe impl<T: Send, G> Send for RwLock<T, G> {
652
653}
654
655#[verifier::external]
656unsafe impl<T: Send + Sync, G> Sync for RwLock<T, G> {
657
658}
659
660impl<T , G: SpinGuardian> !Send for RwLockWriteGuard<'_, T, G> {
661
662}
663
664#[verifier::external]
665unsafe impl<T: Sync, G: SpinGuardian> Sync for RwLockWriteGuard<'_, T, G> {
666
667}
668
669impl<T , G: SpinGuardian> !Send for RwLockReadGuard<'_, T, G> {
670
671}
672
673#[verifier::external]
674unsafe impl<T: Sync, G: SpinGuardian> Sync for RwLockReadGuard<'_, T, G> {
675
676}
677
678impl<T , G: SpinGuardian> !Send for RwLockUpgradeableGuard<'_, T, G> {
679
680}
681
682#[verifier::external]
683unsafe impl<T: Sync, G: SpinGuardian> Sync for RwLockUpgradeableGuard<'_, T, G> {
684
685}
686
687#[verifier::reject_recursive_types(T)]
689#[verifier::reject_recursive_types(G)]
690#[clippy::has_significant_drop]
691#[must_use]
692#[verus_verify]
693pub struct RwLockReadGuard<'a, T , G: SpinGuardian> {
694 guard: G::ReadGuard,
695 inner: &'a RwLock<T, G>,
696 tracked_token: Tracked<Count<ReadPerm<T>, MAX_READER>>,
697}
698
699impl<'a, T, G: SpinGuardian> RwLockReadGuard<'a, T, G> {
708 #[verifier::type_invariant]
709 pub closed spec fn type_inv(self) -> bool {
710 let resource = self.tracked_token@.resource();
711 let read_half_cell_perm = resource.0;
712 let mode_knowledge = resource.1;
713 &&& self.inner.core_token_id() == mode_knowledge.id()
714 &&& self.inner.frac_id() == read_half_cell_perm.id()
715 &&& self.inner.cell_id() == read_half_cell_perm.resource().id()
716 &&& self.tracked_token@.id() == self.inner.read_guard_token_id()
717 &&& read_half_cell_perm.frac() == 1
718 &&& self.tracked_token@.frac() == 1
719 }
720
721 pub closed spec fn value(self) -> T {
723 *self.tracked_token@.resource().0.resource().value()
724 }
725
726 pub open spec fn view(self) -> T {
728 self.value()
729 }
730}
731
732impl<T , G: SpinGuardian> Deref for RwLockReadGuard<'_, T, G> {
733 type Target = T;
734
735 #[verus_spec(returns self.view())]
736 fn deref(&self) -> &T {
737 proof!{
738 use_type_invariant(self);
739 }
740 self.inner.val.borrow(
744 Tracked(self.tracked_token.borrow().tracked_borrow().0.tracked_borrow()),
745 )
746 }
747}
748
749#[verus_verify]
758impl<T , G: SpinGuardian> RwLockReadGuard<'_, T, G> {
759 #[verus_spec]
761 fn drop(self) {
762 proof! {
763 use_type_invariant(&self);
764 use_type_invariant(self.inner);
765 lemma_consts_properties();
766 }
767 proof_decl! {
768 let tracked token = self.tracked_token.get();
769 }
770 atomic_with_ghost!(
772 self.inner.lock => fetch_sub(READER);
773 update prev -> next;
774 ghost g => {
775 let prev_usize = prev as usize;
776 let next_usize = next as usize;
777 assume (no_max_reader_overflow(prev_usize));
778 lemma_consts_properties_value(next_usize);
779 lemma_consts_properties_prev_next(prev_usize, next_usize);
780 g.core_token.validate_with_one_left_knowledge(&token.tracked_borrow().1);
781 g.read_guard_token.combine(token);
782 }
783 );
784 }
785}
786
787#[verifier::reject_recursive_types(T)]
796#[verifier::reject_recursive_types(G)]
797pub struct RwLockWriteGuard<'a, T , G: SpinGuardian> {
798 guard: G::Guard,
799 inner: &'a RwLock<T, G>,
800 tracked_perm: Tracked<PointsTo<T>>,
802 tracked_token: Tracked<OneRightKnowledge<HalfPerm<T>, NoPerm<T>, 3>>,
803}
804
805impl<'a, T, G: SpinGuardian> RwLockWriteGuard<'a, T, G> {
806 #[verifier::type_invariant]
807 spec fn type_inv(self) -> bool {
808 &&& self.inner.cell_id() == self.tracked_perm@.id()
809 &&& self.inner.core_token_id() == self.tracked_token@.id()
810 }
811
812 pub closed spec fn value(self) -> T {
814 *self.tracked_perm@.value()
815 }
816
817 pub open spec fn view(self) -> T {
819 self.value()
820 }
821}
822
823impl<T , G: SpinGuardian> Deref for RwLockWriteGuard<'_, T, G> {
831 type Target = T;
832
833 #[verus_spec(returns self.view())]
834 fn deref(&self) -> &T {
835 proof!{
836 use_type_invariant(self);
837 }
838 self.inner.val.borrow(Tracked(self.tracked_perm.borrow()))
842 }
843}
844
845#[verus_verify]
846impl<T , G: SpinGuardian> DerefMut for RwLockWriteGuard<'_, T, G> {
847 #[verus_spec(ret =>
848 ensures
849 final(self).view() == *final(ret),
850 old(self).view() == *ret,
851 )]
852 fn deref_mut(&mut self) -> &mut Self::Target {
853 proof!{
854 use_type_invariant(&*self);
855 }
856 self.inner.val.borrow_mut(Tracked(&mut *self.tracked_perm))
858 }
859}
860
861impl<T , G: SpinGuardian> RwLockWriteGuard<'_, T, G> {
869 pub fn drop(self) {
871 proof!{
872 use_type_invariant(&self);
873 use_type_invariant(self.inner);
874 lemma_consts_properties();
875 }
876 proof_decl! {
877 let tracked mut perm = self.tracked_perm.get();
878 let tracked token = self.tracked_token.get();
879 }
880 atomic_with_ghost!{
882 self.inner.lock => fetch_and(!WRITER);
883 update prev -> next;
884 ghost g => {
885 let prev_usize = prev as usize;
886 let next_usize = next as usize;
887 lemma_consts_properties_prev_next(prev_usize, next_usize);
888 lemma_consts_properties_value(next_usize);
889 g.core_token.validate_with_one_right_knowledge(&token);
890 g.core_token.join_one_right_knowledge(token);
891 let tracked empty = g.core_token.take_resource_right();
892 let tracked mut full = empty.put_resource(perm);
893 let tracked read_half_cell_perm = full.split(1int);
894 g.core_token.change_to_left(full);
895 let tracked upreader_guard_token = g.core_token.split_one_left_owner();
896 g.upreader_guard_token = Some(upreader_guard_token);
897 let tracked left_token = g.core_token.split_one_left_knowledge();
898 g.read_guard_token.put_resource((read_half_cell_perm, left_token));
899 }
900 };
901 }
902}
903
904#[verifier::reject_recursive_types(T)]
914#[verifier::reject_recursive_types(G)]
915pub struct RwLockUpgradeableGuard<'a, T , G: SpinGuardian> {
916 guard: G::Guard,
917 inner: &'a RwLock<T, G>,
918 tracked_token: Tracked<OneLeftOwner<HalfPerm<T>, NoPerm<T>, 3>>,
919}
920
921impl<'a, T, G: SpinGuardian> RwLockUpgradeableGuard<'a, T, G> {
929 #[verifier::type_invariant]
930 pub closed spec fn type_inv(self) -> bool {
931 wf_upgradeable_guard_token(
932 self.inner.core_token_id(),
933 self.inner.frac_id(),
934 self.inner.cell_id(),
935 self.tracked_token@,
936 )
937 }
938
939 pub closed spec fn value(self) -> T {
941 *self.tracked_token@.resource().resource().value()
942 }
943
944 pub open spec fn view(self) -> T {
946 self.value()
947 }
948}
949
950impl<'a, T , G: SpinGuardian> RwLockUpgradeableGuard<'a, T, G> {
951 #[verifier::exec_allows_no_decreases_clause]
957 pub fn upgrade( self) -> RwLockWriteGuard<'a, T, G> {
958 let mut this = self;
959 proof! {
960 use_type_invariant(&this);
961 use_type_invariant(&this.inner);
962 lemma_consts_properties();
963 }
964 atomic_with_ghost!(
966 this.inner.lock => fetch_or(BEING_UPGRADED);
967 update prev -> next;
968 ghost g => {
969 lemma_consts_properties_prev_next(prev, next);
970 }
971 );
972 loop {
973 this =
975 match this.try_upgrade() {
976 Ok(guard) => return guard,
977 Err(e) => e,
978 };
979 }
980 }
981
982 fn try_upgrade( self) -> Result<RwLockWriteGuard<'a, T, G>, Self> {
990 proof! {
991 use_type_invariant(&self);
992 use_type_invariant(self.inner);
993 lemma_consts_properties();
994 }
995 let mut this = self;
996 proof_decl! {
997 let tracked mut upread_guard_token = this.tracked_token.get();
998 let tracked mut write_perm: Option<PointsTo<T>> = None;
999 let tracked mut err_upread_guard_token: Option<OneLeftOwner<HalfPerm<T>, NoPerm<T>, 3>> = None;
1000 let tracked mut retract_upgrade_token: Option<UniqueToken> = None;
1001 let tracked mut write_guard_token = None;
1002 }
1003
1004 let res =
1011 atomic_with_ghost!(
1012 this.inner.lock => compare_exchange(UPGRADEABLE_READER | BEING_UPGRADED, WRITER | UPGRADEABLE_READER);
1013 update prev -> next;
1014 returning res;
1015 ghost g => {
1016 lemma_consts_properties_prev_next(prev, next);
1017 if res is Ok {
1018 g.core_token.validate_with_one_left_owner(&upread_guard_token);
1019 if g.upreader_guard_token is Some {
1020 upread_guard_token.validate_with_one_left_owner(g.upreader_guard_token.tracked_borrow());
1021 }
1022 g.core_token.join_one_left_owner(upread_guard_token);
1023 let tracked read_resource = g.read_guard_token.take_resource();
1024 let tracked (read_half_cell_perm, left_token) = read_resource;
1025 g.core_token.join_one_left_knowledge(left_token);
1026 let tracked mut pointsto = g.core_token.take_resource_left();
1027 pointsto.combine(read_half_cell_perm);
1028 let tracked (pointsto, empty) = pointsto.take_resource();
1029 write_perm = Some(pointsto);
1030 g.core_token.change_to_right(empty);
1031 write_guard_token = Some(g.core_token.split_one_right_knowledge());
1032 retract_upgrade_token = Some(g.upread_retract_token.tracked_take());
1033 } else {
1034 err_upread_guard_token = Some(upread_guard_token);
1035 }
1036 }
1037 );
1038 if res.is_ok() {
1039 let inner = this.inner;
1040 let guard = this.guard.transfer_to();
1041 atomic_with_ghost!(
1043 inner.lock => fetch_sub(UPGRADEABLE_READER);
1044 update prev -> next;
1045 ghost g => {
1046 let prev_usize = prev as usize;
1047 let next_usize = next as usize;
1048 lemma_consts_properties_value(prev_usize);
1049 lemma_consts_properties_prev_next(prev_usize, next_usize);
1050 let tracked mut token = retract_upgrade_token.tracked_unwrap();
1051 if g.upread_retract_token is Some {
1052 token.validate_with_other(g.upread_retract_token.tracked_borrow());
1053 }
1054 g.upread_retract_token = Some(token);
1055 }
1056 );
1057 Ok(
1058 RwLockWriteGuard {
1059 inner,
1060 guard,
1061 tracked_perm: Tracked(write_perm.tracked_unwrap()),
1062 tracked_token: Tracked(write_guard_token.tracked_unwrap()),
1063 },
1064 )
1065 } else {
1066 Err(
1067 RwLockUpgradeableGuard {
1068 inner: this.inner,
1069 guard: this.guard,
1070 tracked_token: Tracked(err_upread_guard_token.tracked_unwrap()),
1071 },
1072 )
1073 }
1074 }
1075}
1076
1077impl<T , G: SpinGuardian> Deref for RwLockUpgradeableGuard<'_, T, G> {
1078 type Target = T;
1079
1080 #[verus_spec(returns self.view())]
1081 fn deref(&self) -> &T {
1082 proof!{
1083 use_type_invariant(self);
1084 }
1085 self.inner.val.borrow(
1089 Tracked(self.tracked_token.borrow().tracked_borrow().tracked_borrow()),
1090 )
1091 }
1092}
1093
1094impl<T , G: SpinGuardian> RwLockUpgradeableGuard<'_, T, G> {
1102 pub fn drop(self) {
1104 proof! {
1105 use_type_invariant(&self);
1106 use_type_invariant(self.inner);
1107 lemma_consts_properties();
1108 }
1109 proof_decl!{
1110 let tracked guard_token = self.tracked_token.get();
1111 }
1112 atomic_with_ghost!(
1114 self.inner.lock => fetch_sub(UPGRADEABLE_READER);
1115 update prev -> next;
1116 ghost g => {
1117 let prev_usize = prev as usize;
1118 let next_usize = next as usize;
1119 lemma_consts_properties_value(prev_usize);
1120 lemma_consts_properties_prev_next(prev_usize, next_usize);
1121 g.core_token.validate_with_one_left_owner(&guard_token);
1122 if g.upreader_guard_token is Some {
1123 guard_token.validate_with_one_left_owner(g.upreader_guard_token.tracked_borrow());
1124 assert(false);
1125 } else {
1126 g.upreader_guard_token= Some(guard_token);
1127 }
1128 }
1129 );
1130 }
1131}
1132
1133#[verifier::bit_vector]
1142proof fn lemma_consts_properties()
1143 ensures
1144 0 & WRITER == 0,
1145 0 & UPGRADEABLE_READER == 0,
1146 0 & BEING_UPGRADED == 0,
1147 0 & READER_MASK == 0,
1148 0 & MAX_READER_MASK == 0,
1149 0 & MAX_READER == 0,
1150 0 & READER == 0,
1151 WRITER == 0x8000_0000_0000_0000,
1152 UPGRADEABLE_READER == 0x4000_0000_0000_0000,
1153 BEING_UPGRADED == 0x2000_0000_0000_0000,
1154 READER_MASK == 0x0FFF_FFFF_FFFF_FFFF,
1155 MAX_READER_MASK == 0x1FFF_FFFF_FFFF_FFFF,
1156 MAX_READER == 0x1000_0000_0000_0000,
1157 WRITER & WRITER == WRITER,
1158 WRITER & !WRITER == 0,
1159 WRITER & BEING_UPGRADED == 0,
1160 WRITER & READER_MASK == 0,
1161 WRITER & MAX_READER_MASK == 0,
1162 WRITER & MAX_READER == 0,
1163 WRITER & UPGRADEABLE_READER == 0,
1164 BEING_UPGRADED & WRITER == 0,
1165 BEING_UPGRADED & UPGRADEABLE_READER == 0,
1166 UPGRADEABLE_READER & BEING_UPGRADED == 0,
1167 UPGRADEABLE_READER & READER_MASK == 0,
1168 UPGRADEABLE_READER & MAX_READER_MASK == 0,
1169 UPGRADEABLE_READER & MAX_READER == 0,
1170 BEING_UPGRADED & READER_MASK == 0,
1171 BEING_UPGRADED & MAX_READER_MASK == 0,
1172 BEING_UPGRADED & MAX_READER == 0,
1173 (UPGRADEABLE_READER | BEING_UPGRADED) & WRITER == 0,
1174 (UPGRADEABLE_READER | BEING_UPGRADED) & UPGRADEABLE_READER == UPGRADEABLE_READER,
1175 (UPGRADEABLE_READER | BEING_UPGRADED) & BEING_UPGRADED == BEING_UPGRADED,
1176 (UPGRADEABLE_READER | BEING_UPGRADED) & READER_MASK == 0,
1177 (UPGRADEABLE_READER | BEING_UPGRADED) & MAX_READER_MASK == 0,
1178 (UPGRADEABLE_READER | BEING_UPGRADED) & MAX_READER == 0,
1179 (WRITER | UPGRADEABLE_READER) & WRITER == WRITER,
1180 (WRITER | UPGRADEABLE_READER) & UPGRADEABLE_READER == UPGRADEABLE_READER,
1181 (WRITER | UPGRADEABLE_READER) & BEING_UPGRADED == 0,
1182 (WRITER | UPGRADEABLE_READER) & READER_MASK == 0,
1183 (WRITER | UPGRADEABLE_READER) & MAX_READER_MASK == 0,
1184 (WRITER | UPGRADEABLE_READER) & MAX_READER == 0,
1185{
1186}
1187
1188#[verifier::bit_vector]
1189proof fn lemma_consts_properties_value(prev: usize)
1190 ensures
1191 no_max_reader_overflow(prev) ==> prev + READER <= usize::MAX,
1192 prev & (WRITER | MAX_READER | BEING_UPGRADED) == 0 ==> {
1193 &&& prev & WRITER == 0
1194 &&& prev & BEING_UPGRADED == 0
1195 &&& prev & MAX_READER == 0
1196 },
1197 prev & (WRITER | UPGRADEABLE_READER) == 0 ==> {
1198 &&& prev & WRITER == 0
1199 &&& prev & UPGRADEABLE_READER == 0
1200 },
1201 prev & MAX_READER == 0 ==> prev & READER_MASK == prev & MAX_READER_MASK,
1202 prev & MAX_READER != 0 ==> prev & MAX_READER_MASK >= MAX_READER,
1203 prev & (WRITER | UPGRADEABLE_READER) == WRITER ==> {
1204 &&& prev & UPGRADEABLE_READER == 0
1205 &&& prev & WRITER == WRITER
1206 },
1207 prev & UPGRADEABLE_READER != 0 ==> prev >= UPGRADEABLE_READER,
1208 prev & UPGRADEABLE_READER == 0 ==> {
1209 ||| prev & (WRITER | UPGRADEABLE_READER) == 0
1210 ||| prev & (WRITER | UPGRADEABLE_READER) == WRITER
1211 },
1212{
1213}
1214
1215#[verifier::bit_vector]
1216proof fn lemma_consts_properties_prev_next(prev: usize, next: usize)
1217 ensures
1218 prev & READER_MASK < MAX_READER,
1219 next == prev | UPGRADEABLE_READER ==> {
1220 &&& next & UPGRADEABLE_READER != 0
1221 &&& next & WRITER == prev & WRITER
1222 &&& next & READER_MASK == prev & READER_MASK
1223 &&& next & MAX_READER_MASK == prev & MAX_READER_MASK
1224 &&& next & MAX_READER == prev & MAX_READER
1225 &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1226 },
1227 next == prev | BEING_UPGRADED ==> {
1228 &&& next & BEING_UPGRADED != 0
1229 &&& next & WRITER == prev & WRITER
1230 &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1231 &&& next & READER_MASK == prev & READER_MASK
1232 &&& next & MAX_READER_MASK == prev & MAX_READER_MASK
1233 &&& next & MAX_READER == prev & MAX_READER
1234 },
1235 next == prev - UPGRADEABLE_READER && prev & UPGRADEABLE_READER != 0 ==> {
1236 &&& next & UPGRADEABLE_READER == 0
1237 &&& next & WRITER == prev & WRITER
1238 &&& next & READER_MASK == prev & READER_MASK
1239 &&& next & MAX_READER_MASK == prev & MAX_READER_MASK
1240 &&& next & MAX_READER == prev & MAX_READER
1241 &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1242 },
1243 next == prev - READER && prev & READER_MASK != 0 ==> {
1244 &&& next & READER_MASK == (prev & READER_MASK) - READER
1245 &&& next & MAX_READER_MASK == (prev & MAX_READER_MASK) - READER
1246 &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1247 &&& next & WRITER == prev & WRITER
1248 &&& next & MAX_READER == prev & MAX_READER
1249 &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1250 },
1251 next == prev - READER && prev & MAX_READER_MASK != 0 ==> {
1252 &&& next & MAX_READER_MASK == (prev & MAX_READER_MASK) - READER
1253 &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1254 &&& next & WRITER == prev & WRITER
1255 &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1256 },
1257 next == prev + READER && no_max_reader_overflow(prev) ==> {
1258 &&& next & READER_MASK == if (prev & READER_MASK) + READER == MAX_READER {
1259 0
1260 } else {
1261 (prev & READER_MASK) + READER
1262 }
1263 &&& next & MAX_READER_MASK == (prev & MAX_READER_MASK) + READER
1264 &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1265 &&& next & WRITER == prev & WRITER
1266 &&& next & MAX_READER == if (prev & READER_MASK) + READER == MAX_READER {
1267 MAX_READER
1268 } else {
1269 prev & MAX_READER
1270 }
1271 &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1272 },
1273 next == prev & !WRITER ==> {
1274 &&& next & WRITER == 0
1275 &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1276 &&& next & READER_MASK == prev & READER_MASK
1277 &&& next & MAX_READER_MASK == prev & MAX_READER_MASK
1278 &&& next & MAX_READER == prev & MAX_READER
1279 &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1280 },
1281{
1282}
1283
1284}