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 guard,
482 inner: self,
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 guard,
550 inner: self,
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 guard,
594 inner: self,
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 }}
637
638#[verifier::external]
648unsafe impl<T: Send, G> Send for RwLock<T, G> {
649
650}
651
652#[verifier::external]
653unsafe impl<T: Send + Sync, G> Sync for RwLock<T, G> {
654
655}
656
657impl<T , G: SpinGuardian> !Send for RwLockWriteGuard<'_, T, G> {
658
659}
660
661#[verifier::external]
662unsafe impl<T: Sync, G: SpinGuardian> Sync for RwLockWriteGuard<'_, T, G> {
663
664}
665
666impl<T , G: SpinGuardian> !Send for RwLockReadGuard<'_, T, G> {
667
668}
669
670#[verifier::external]
671unsafe impl<T: Sync, G: SpinGuardian> Sync for RwLockReadGuard<'_, T, G> {
672
673}
674
675impl<T , G: SpinGuardian> !Send for RwLockUpgradeableGuard<'_, T, G> {
676
677}
678
679#[verifier::external]
680unsafe impl<T: Sync, G: SpinGuardian> Sync for RwLockUpgradeableGuard<'_, T, G> {
681
682}
683
684#[verifier::reject_recursive_types(T)]
686#[verifier::reject_recursive_types(G)]
687#[clippy::has_significant_drop]
688#[must_use]
689#[verus_verify]
690pub struct RwLockReadGuard<'a, T , G: SpinGuardian> {
691 guard: G::ReadGuard,
692 inner: &'a RwLock<T, G>,
693 tracked_token: Tracked<Count<ReadPerm<T>, MAX_READER>>,
694}
695
696impl<'a, T, G: SpinGuardian> RwLockReadGuard<'a, T, G> {
705 #[verifier::type_invariant]
706 pub closed spec fn type_inv(self) -> bool {
707 let resource = self.tracked_token@.resource();
708 let read_half_cell_perm = resource.0;
709 let mode_knowledge = resource.1;
710 &&& self.inner.core_token_id() == mode_knowledge.id()
711 &&& self.inner.frac_id() == read_half_cell_perm.id()
712 &&& self.inner.cell_id() == read_half_cell_perm.resource().id()
713 &&& self.tracked_token@.id() == self.inner.read_guard_token_id()
714 &&& read_half_cell_perm.frac() == 1
715 &&& self.tracked_token@.frac() == 1
716 }
717
718 pub closed spec fn value(self) -> T {
720 *self.tracked_token@.resource().0.resource().value()
721 }
722
723 pub open spec fn view(self) -> T {
725 self.value()
726 }
727}
728
729impl<T , G: SpinGuardian> Deref for RwLockReadGuard<'_, T, G> {
730 type Target = T;
731
732 #[verus_spec(returns self.view())]
733 fn deref(&self) -> &T {
734 proof!{
735 use_type_invariant(self);
736 }
737 self.inner.val.borrow(
741 Tracked(self.tracked_token.borrow().tracked_borrow().0.tracked_borrow()),
742 )
743 }
744}
745
746#[verus_verify]
755impl<T , G: SpinGuardian> RwLockReadGuard<'_, T, G> {
756 #[verus_spec]
758 fn drop(self) {
759 proof! {
760 use_type_invariant(&self);
761 use_type_invariant(self.inner);
762 lemma_consts_properties();
763 }
764 proof_decl! {
765 let tracked token = self.tracked_token.get();
766 }
767 atomic_with_ghost!(
769 self.inner.lock => fetch_sub(READER);
770 update prev -> next;
771 ghost g => {
772 let prev_usize = prev as usize;
773 let next_usize = next as usize;
774 assume (no_max_reader_overflow(prev_usize));
775 lemma_consts_properties_value(next_usize);
776 lemma_consts_properties_prev_next(prev_usize, next_usize);
777 g.core_token.validate_with_one_left_knowledge(&token.tracked_borrow().1);
778 g.read_guard_token.combine(token);
779 }
780 );
781 }
782}
783
784#[verifier::reject_recursive_types(T)]
793#[verifier::reject_recursive_types(G)]
794pub struct RwLockWriteGuard<'a, T , G: SpinGuardian> {
795 guard: G::Guard,
796 inner: &'a RwLock<T, G>,
797 tracked_perm: Tracked<PointsTo<T>>,
799 tracked_token: Tracked<OneRightKnowledge<HalfPerm<T>, NoPerm<T>, 3>>,
800}
801
802impl<'a, T, G: SpinGuardian> RwLockWriteGuard<'a, T, G> {
803 #[verifier::type_invariant]
804 spec fn type_inv(self) -> bool {
805 &&& self.inner.cell_id() == self.tracked_perm@.id()
806 &&& self.inner.core_token_id() == self.tracked_token@.id()
807 }
808
809 pub closed spec fn value(self) -> T {
811 *self.tracked_perm@.value()
812 }
813
814 pub open spec fn view(self) -> T {
816 self.value()
817 }
818}
819
820impl<T , G: SpinGuardian> Deref for RwLockWriteGuard<'_, T, G> {
828 type Target = T;
829
830 #[verus_spec(returns self.view())]
831 fn deref(&self) -> &T {
832 proof!{
833 use_type_invariant(self);
834 }
835 self.inner.val.borrow(Tracked(self.tracked_perm.borrow()))
839 }
840}
841
842#[verus_verify]
843impl<T , G: SpinGuardian> DerefMut for RwLockWriteGuard<'_, T, G> {
844 #[verus_spec(ret =>
845 ensures
846 final(self).view() == *final(ret),
847 old(self).view() == *ret,
848 )]
849 fn deref_mut(&mut self) -> &mut Self::Target {
850 proof!{
851 use_type_invariant(&*self);
852 }
853 self.inner.val.borrow_mut(Tracked(&mut *self.tracked_perm))
855 }
856}
857
858impl<T , G: SpinGuardian> RwLockWriteGuard<'_, T, G> {
866 pub fn drop(self) {
868 proof!{
869 use_type_invariant(&self);
870 use_type_invariant(self.inner);
871 lemma_consts_properties();
872 }
873 proof_decl! {
874 let tracked mut perm = self.tracked_perm.get();
875 let tracked token = self.tracked_token.get();
876 }
877 atomic_with_ghost!{
879 self.inner.lock => fetch_and(!WRITER);
880 update prev -> next;
881 ghost g => {
882 let prev_usize = prev as usize;
883 let next_usize = next as usize;
884 lemma_consts_properties_prev_next(prev_usize, next_usize);
885 lemma_consts_properties_value(next_usize);
886 g.core_token.validate_with_one_right_knowledge(&token);
887 g.core_token.join_one_right_knowledge(token);
888 let tracked empty = g.core_token.take_resource_right();
889 let tracked mut full = empty.put_resource(perm);
890 let tracked read_half_cell_perm = full.split(1int);
891 g.core_token.change_to_left(full);
892 let tracked upreader_guard_token = g.core_token.split_one_left_owner();
893 g.upreader_guard_token = Some(upreader_guard_token);
894 let tracked left_token = g.core_token.split_one_left_knowledge();
895 g.read_guard_token.put_resource((read_half_cell_perm, left_token));
896 }
897 };
898 }
899}
900
901#[verifier::reject_recursive_types(T)]
911#[verifier::reject_recursive_types(G)]
912pub struct RwLockUpgradeableGuard<'a, T , G: SpinGuardian> {
913 guard: G::Guard,
914 inner: &'a RwLock<T, G>,
915 tracked_token: Tracked<OneLeftOwner<HalfPerm<T>, NoPerm<T>, 3>>,
916}
917
918impl<'a, T, G: SpinGuardian> RwLockUpgradeableGuard<'a, T, G> {
926 #[verifier::type_invariant]
927 pub closed spec fn type_inv(self) -> bool {
928 wf_upgradeable_guard_token(
929 self.inner.core_token_id(),
930 self.inner.frac_id(),
931 self.inner.cell_id(),
932 self.tracked_token@,
933 )
934 }
935
936 pub closed spec fn value(self) -> T {
938 *self.tracked_token@.resource().resource().value()
939 }
940
941 pub open spec fn view(self) -> T {
943 self.value()
944 }
945}
946
947impl<'a, T , G: SpinGuardian> RwLockUpgradeableGuard<'a, T, G> {
948 #[verifier::exec_allows_no_decreases_clause]
954 pub fn upgrade(mut self) -> RwLockWriteGuard<'a, T, G> {
955 proof! {
956 use_type_invariant(&self);
957 use_type_invariant(&self.inner);
958 lemma_consts_properties();
959 }
960 atomic_with_ghost!(
962 self.inner.lock => fetch_or(BEING_UPGRADED);
963 update prev -> next;
964 ghost g => {
965 lemma_consts_properties_prev_next(prev, next);
966 }
967 );
968 loop {
969 self =
970 match self.try_upgrade() {
971 Ok(guard) => return guard,
972 Err(e) => e,
973 };
974 }
975 }
976
977 fn try_upgrade(mut self) -> Result<RwLockWriteGuard<'a, T, G>, Self> {
985 proof! {
986 use_type_invariant(&self);
987 use_type_invariant(self.inner);
988 lemma_consts_properties();
989 }
990 proof_decl! {
991 let tracked mut upread_guard_token = self.tracked_token.get();
992 let tracked mut write_perm: Option<PointsTo<T>> = None;
993 let tracked mut err_upread_guard_token: Option<OneLeftOwner<HalfPerm<T>, NoPerm<T>, 3>> = None;
994 let tracked mut retract_upgrade_token: Option<UniqueToken> = None;
995 let tracked mut write_guard_token = None;
996 }
997
998 let res =
1005 atomic_with_ghost!(
1006 self.inner.lock => compare_exchange(UPGRADEABLE_READER | BEING_UPGRADED, WRITER | UPGRADEABLE_READER);
1007 update prev -> next;
1008 returning res;
1009 ghost g => {
1010 lemma_consts_properties_prev_next(prev, next);
1011 if res is Ok {
1012 g.core_token.validate_with_one_left_owner(&upread_guard_token);
1013 if g.upreader_guard_token is Some {
1014 upread_guard_token.validate_with_one_left_owner(g.upreader_guard_token.tracked_borrow());
1015 }
1016 g.core_token.join_one_left_owner(upread_guard_token);
1017 let tracked read_resource = g.read_guard_token.take_resource();
1018 let tracked (read_half_cell_perm, left_token) = read_resource;
1019 g.core_token.join_one_left_knowledge(left_token);
1020 let tracked mut pointsto = g.core_token.take_resource_left();
1021 pointsto.combine(read_half_cell_perm);
1022 let tracked (pointsto, empty) = pointsto.take_resource();
1023 write_perm = Some(pointsto);
1024 g.core_token.change_to_right(empty);
1025 write_guard_token = Some(g.core_token.split_one_right_knowledge());
1026 retract_upgrade_token = Some(g.upread_retract_token.tracked_take());
1027 } else {
1028 err_upread_guard_token = Some(upread_guard_token);
1029 }
1030 }
1031 );
1032 if res.is_ok() {
1033 let guard = self.guard.transfer_to();
1034 let inner = self.inner;
1035 atomic_with_ghost!(
1037 inner.lock => fetch_sub(UPGRADEABLE_READER);
1038 update prev -> next;
1039 ghost g => {
1040 let prev_usize = prev as usize;
1041 let next_usize = next as usize;
1042 lemma_consts_properties_value(prev_usize);
1043 lemma_consts_properties_prev_next(prev_usize, next_usize);
1044 let tracked mut token = retract_upgrade_token.tracked_unwrap();
1045 if g.upread_retract_token is Some {
1046 token.validate_with_other(g.upread_retract_token.tracked_borrow());
1047 }
1048 g.upread_retract_token = Some(token);
1049 }
1050 );
1051 Ok(
1052 RwLockWriteGuard {
1053 guard,
1054 inner,
1055 tracked_perm: Tracked(write_perm.tracked_unwrap()),
1056 tracked_token: Tracked(write_guard_token.tracked_unwrap()),
1057 },
1058 )
1059 } else {
1060 Err(
1061 RwLockUpgradeableGuard {
1062 guard: self.guard,
1063 inner: self.inner,
1064 tracked_token: Tracked(err_upread_guard_token.tracked_unwrap()),
1065 },
1066 )
1067 }
1068 }
1069}
1070
1071impl<T , G: SpinGuardian> Deref for RwLockUpgradeableGuard<'_, T, G> {
1072 type Target = T;
1073
1074 #[verus_spec(returns self.view())]
1075 fn deref(&self) -> &T {
1076 proof!{
1077 use_type_invariant(self);
1078 }
1079 self.inner.val.borrow(
1083 Tracked(self.tracked_token.borrow().tracked_borrow().tracked_borrow()),
1084 )
1085 }
1086}
1087
1088impl<T , G: SpinGuardian> RwLockUpgradeableGuard<'_, T, G> {
1096 pub fn drop(self) {
1098 proof! {
1099 use_type_invariant(&self);
1100 use_type_invariant(self.inner);
1101 lemma_consts_properties();
1102 }
1103 proof_decl!{
1104 let tracked guard_token = self.tracked_token.get();
1105 }
1106 atomic_with_ghost!(
1108 self.inner.lock => fetch_sub(UPGRADEABLE_READER);
1109 update prev -> next;
1110 ghost g => {
1111 let prev_usize = prev as usize;
1112 let next_usize = next as usize;
1113 lemma_consts_properties_value(prev_usize);
1114 lemma_consts_properties_prev_next(prev_usize, next_usize);
1115 g.core_token.validate_with_one_left_owner(&guard_token);
1116 if g.upreader_guard_token is Some {
1117 guard_token.validate_with_one_left_owner(g.upreader_guard_token.tracked_borrow());
1118 assert(false);
1119 } else {
1120 g.upreader_guard_token= Some(guard_token);
1121 }
1122 }
1123 );
1124 }
1125}
1126
1127#[verifier::bit_vector]
1136proof fn lemma_consts_properties()
1137 ensures
1138 0 & WRITER == 0,
1139 0 & UPGRADEABLE_READER == 0,
1140 0 & BEING_UPGRADED == 0,
1141 0 & READER_MASK == 0,
1142 0 & MAX_READER_MASK == 0,
1143 0 & MAX_READER == 0,
1144 0 & READER == 0,
1145 WRITER == 0x8000_0000_0000_0000,
1146 UPGRADEABLE_READER == 0x4000_0000_0000_0000,
1147 BEING_UPGRADED == 0x2000_0000_0000_0000,
1148 READER_MASK == 0x0FFF_FFFF_FFFF_FFFF,
1149 MAX_READER_MASK == 0x1FFF_FFFF_FFFF_FFFF,
1150 MAX_READER == 0x1000_0000_0000_0000,
1151 WRITER & WRITER == WRITER,
1152 WRITER & !WRITER == 0,
1153 WRITER & BEING_UPGRADED == 0,
1154 WRITER & READER_MASK == 0,
1155 WRITER & MAX_READER_MASK == 0,
1156 WRITER & MAX_READER == 0,
1157 WRITER & UPGRADEABLE_READER == 0,
1158 BEING_UPGRADED & WRITER == 0,
1159 BEING_UPGRADED & UPGRADEABLE_READER == 0,
1160 UPGRADEABLE_READER & BEING_UPGRADED == 0,
1161 UPGRADEABLE_READER & READER_MASK == 0,
1162 UPGRADEABLE_READER & MAX_READER_MASK == 0,
1163 UPGRADEABLE_READER & MAX_READER == 0,
1164 BEING_UPGRADED & READER_MASK == 0,
1165 BEING_UPGRADED & MAX_READER_MASK == 0,
1166 BEING_UPGRADED & MAX_READER == 0,
1167 (UPGRADEABLE_READER | BEING_UPGRADED) & WRITER == 0,
1168 (UPGRADEABLE_READER | BEING_UPGRADED) & UPGRADEABLE_READER == UPGRADEABLE_READER,
1169 (UPGRADEABLE_READER | BEING_UPGRADED) & BEING_UPGRADED == BEING_UPGRADED,
1170 (UPGRADEABLE_READER | BEING_UPGRADED) & READER_MASK == 0,
1171 (UPGRADEABLE_READER | BEING_UPGRADED) & MAX_READER_MASK == 0,
1172 (UPGRADEABLE_READER | BEING_UPGRADED) & MAX_READER == 0,
1173 (WRITER | UPGRADEABLE_READER) & WRITER == WRITER,
1174 (WRITER | UPGRADEABLE_READER) & UPGRADEABLE_READER == UPGRADEABLE_READER,
1175 (WRITER | UPGRADEABLE_READER) & BEING_UPGRADED == 0,
1176 (WRITER | UPGRADEABLE_READER) & READER_MASK == 0,
1177 (WRITER | UPGRADEABLE_READER) & MAX_READER_MASK == 0,
1178 (WRITER | UPGRADEABLE_READER) & MAX_READER == 0,
1179{
1180}
1181
1182#[verifier::bit_vector]
1183proof fn lemma_consts_properties_value(prev: usize)
1184 ensures
1185 no_max_reader_overflow(prev) ==> prev + READER <= usize::MAX,
1186 prev & (WRITER | MAX_READER | BEING_UPGRADED) == 0 ==> {
1187 &&& prev & WRITER == 0
1188 &&& prev & BEING_UPGRADED == 0
1189 &&& prev & MAX_READER == 0
1190 },
1191 prev & (WRITER | UPGRADEABLE_READER) == 0 ==> {
1192 &&& prev & WRITER == 0
1193 &&& prev & UPGRADEABLE_READER == 0
1194 },
1195 prev & MAX_READER == 0 ==> prev & READER_MASK == prev & MAX_READER_MASK,
1196 prev & MAX_READER != 0 ==> prev & MAX_READER_MASK >= MAX_READER,
1197 prev & (WRITER | UPGRADEABLE_READER) == WRITER ==> {
1198 &&& prev & UPGRADEABLE_READER == 0
1199 &&& prev & WRITER == WRITER
1200 },
1201 prev & UPGRADEABLE_READER != 0 ==> prev >= UPGRADEABLE_READER,
1202 prev & UPGRADEABLE_READER == 0 ==> {
1203 ||| prev & (WRITER | UPGRADEABLE_READER) == 0
1204 ||| prev & (WRITER | UPGRADEABLE_READER) == WRITER
1205 },
1206{
1207}
1208
1209#[verifier::bit_vector]
1210proof fn lemma_consts_properties_prev_next(prev: usize, next: usize)
1211 ensures
1212 prev & READER_MASK < MAX_READER,
1213 next == prev | UPGRADEABLE_READER ==> {
1214 &&& next & UPGRADEABLE_READER != 0
1215 &&& next & WRITER == prev & WRITER
1216 &&& next & READER_MASK == prev & READER_MASK
1217 &&& next & MAX_READER_MASK == prev & MAX_READER_MASK
1218 &&& next & MAX_READER == prev & MAX_READER
1219 &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1220 },
1221 next == prev | BEING_UPGRADED ==> {
1222 &&& next & BEING_UPGRADED != 0
1223 &&& next & WRITER == prev & WRITER
1224 &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1225 &&& next & READER_MASK == prev & READER_MASK
1226 &&& next & MAX_READER_MASK == prev & MAX_READER_MASK
1227 &&& next & MAX_READER == prev & MAX_READER
1228 },
1229 next == prev - UPGRADEABLE_READER && prev & UPGRADEABLE_READER != 0 ==> {
1230 &&& next & UPGRADEABLE_READER == 0
1231 &&& next & WRITER == prev & WRITER
1232 &&& next & READER_MASK == prev & READER_MASK
1233 &&& next & MAX_READER_MASK == prev & MAX_READER_MASK
1234 &&& next & MAX_READER == prev & MAX_READER
1235 &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1236 },
1237 next == prev - READER && prev & READER_MASK != 0 ==> {
1238 &&& next & READER_MASK == (prev & READER_MASK) - READER
1239 &&& next & MAX_READER_MASK == (prev & MAX_READER_MASK) - READER
1240 &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1241 &&& next & WRITER == prev & WRITER
1242 &&& next & MAX_READER == prev & MAX_READER
1243 &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1244 },
1245 next == prev - READER && prev & MAX_READER_MASK != 0 ==> {
1246 &&& next & MAX_READER_MASK == (prev & MAX_READER_MASK) - READER
1247 &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1248 &&& next & WRITER == prev & WRITER
1249 &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1250 },
1251 next == prev + READER && no_max_reader_overflow(prev) ==> {
1252 &&& next & READER_MASK == if (prev & READER_MASK) + READER == MAX_READER {
1253 0
1254 } else {
1255 (prev & READER_MASK) + READER
1256 }
1257 &&& next & MAX_READER_MASK == (prev & MAX_READER_MASK) + READER
1258 &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1259 &&& next & WRITER == prev & WRITER
1260 &&& next & MAX_READER == if (prev & READER_MASK) + READER == MAX_READER {
1261 MAX_READER
1262 } else {
1263 prev & MAX_READER
1264 }
1265 &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1266 },
1267 next == prev & !WRITER ==> {
1268 &&& next & WRITER == 0
1269 &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1270 &&& next & READER_MASK == prev & READER_MASK
1271 &&& next & MAX_READER_MASK == prev & MAX_READER_MASK
1272 &&& next & MAX_READER == prev & MAX_READER
1273 &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1274 },
1275{
1276}
1277
1278}