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