1use vstd::{prelude::*, seq_lib::*, simple_pptr::*};
7use vstd_extra::{
8 cast_ptr::*,
9 drop_tracking::{Drop, DropObligation, TrackDrop},
10 ownership::*,
11};
12
13use crate::specs::{
14 arch::*,
15 mm::frame::{
16 linked_list::linked_list_owners::*,
17 mapping::{frame_to_index, group_page_meta, index_to_meta, meta_to_index},
18 meta_owners::{
19 MetaSlotOwner, MetaSlotStorage, borrow_meta, borrow_meta_mut, typed_meta_value,
20 typed_meta_wf,
21 },
22 meta_region_owners::MetaRegionOwners,
23 unique::UniqueFrameOwner,
24 },
25};
26
27use super::{
28 MetaSlot, mapping,
29 meta::{AnyFrameMeta, get_slot},
30 unique::UniqueFrame,
31};
32use crate::mm::frame::meta::{
33 META_SLOT_SIZE, REF_COUNT_UNIQUE,
34 mapping::{frame_to_meta, meta_to_frame},
35};
36use crate::mm::kspace::FRAME_METADATA_RANGE;
37use crate::{
38 arch::mm::PagingConsts,
39 mm::{Paddr, Vaddr},
40 };
42use core::{
43 ops::{Deref, DerefMut},
44 ptr::NonNull,
45 sync::atomic::{AtomicU64, Ordering},
46};
47
48verus! {
49
50pub struct LinkedList<M: AnyFrameMeta + Repr<MetaSlotSmall>> {
123 pub front: Option<ReprPtr<MetaSlotStorage, Link<M>>>,
124 pub back: Option<ReprPtr<MetaSlotStorage, Link<M>>>,
125 pub size: usize,
127 pub list_id: u64,
130}
131
132pub struct CursorMut<'a, M: AnyFrameMeta + Repr<MetaSlotSmall>> {
137 pub list: &'a mut LinkedList<M>,
138 pub current: Option<ReprPtr<MetaSlotStorage, Link<M>>>,
139}
140
141#[verifier::spinoff_prover]
142proof fn lemma_meta_region_inv_at(regions: MetaRegionOwners, i: int)
143 requires
144 regions.inv(),
145 regions.contains(i),
146 ensures
147 regions.slot_owners[i].inv(),
148 regions.slots[i].is_init(),
149 regions.slots[i].addr() == index_to_meta(i),
150 regions.slots[i].value().wf(regions.slot_owners[i]),
151 regions.slot_owners[i].slot_vaddr == regions.slots[i].addr(),
152{
153}
154
155#[verifier::spinoff_prover]
159proof fn lemma_insert_before_slot_distinct<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
160 owner0: LinkedListOwner<M>,
161 regions0: MetaRegionOwners,
162 frame_idx: int,
163 nn: int,
164)
165 requires
166 owner0.relate_region(regions0),
167 regions0.inv(),
168 regions0.contains(frame_idx),
169 regions0.slot_owners[frame_idx].in_list_perm.value() == 0,
170 0 <= nn <= owner0.list.len() as int,
171 ensures
172 forall|p: int|
173 #![trigger regions0.slot_owners[meta_to_index(owner0.list[p].paddr)]]
174 (0 <= p < owner0.list.len() as int) ==> frame_idx != meta_to_index(
175 owner0.list[p].paddr,
176 ),
177{
178 owner0.lemma_relate_region_shape(regions0);
179 assert forall|p: int|
180 #![trigger regions0.slot_owners[meta_to_index(owner0.list[p].paddr)]]
181 0 <= p < owner0.list.len() as int implies frame_idx != meta_to_index(
182 owner0.list[p].paddr,
183 ) by {
184 owner0.lemma_relate_region_at_index(regions0, p);
185 owner0.lemma_relate_region_at_facts(regions0, p);
186 if frame_idx == meta_to_index(owner0.list[p].paddr) {
187 assert(regions0.slot_owners[meta_to_index(owner0.list[p].paddr)].in_list_perm.value()
188 == owner0.list_id);
189 }
190 }
191}
192
193impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> LinkedList<M> {
194 pub const fn new() -> Self {
196 Self { front: None, back: None, size: 0, list_id: 0 }
197 }
198}
199
200impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Default for LinkedList<M> {
201 fn default() -> Self {
202 Self::new()
203 }
204}
205
206#[verus_verify]
207impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> LinkedList<M> {
208 #[verus_spec(s =>
210 with
211 Tracked(owner): Tracked<LinkedListOwner<M>>,
212 requires
213 self.wf(owner),
214 owner.inv(),
215 ensures
216 s == owner@.list.len(),
217 )]
218 pub fn size(&self) -> usize {
219 proof {
220 LinkedListOwner::<M>::lemma_view_preserves_len(owner.list);
221 }
222 self.size
223 }
224
225 #[verus_spec(b =>
227 with
228 Tracked(owner): Tracked<LinkedListOwner<M>>,
229 requires
230 self.wf(owner),
231 owner.inv(),
232 ensures
233 b ==> self.size == 0 && self.front is None && self.back is None,
234 !b ==> self.size > 0 && self.front is Some && self.back is Some,
235 )]
236 pub fn is_empty(&self) -> bool {
237 let is_empty = self.size == 0;
238 is_empty
239 }
240
241 #[verus_spec(
253 with
254 Tracked(regions): Tracked<&mut MetaRegionOwners>,
255 Tracked(owner): Tracked<&mut LinkedListOwner<M>>,
256 Tracked(frame_own): Tracked<&mut UniqueFrameOwner<Link<M>>>,
257 requires
258 old(self).wf_region(*old(owner), *old(regions)),
259 old(owner).relate_region(*old(regions)),
260 frame.inv(),
261 old(frame_own).inv(),
262 frame.wf_with_region(*old(frame_own), *old(regions)),
263 frame.frame_link_inv(*old(frame_own), *old(regions)),
264 old(regions).inv(),
265 ensures
266 final(owner).relate_region(*final(regions)),
267 final(regions).inv(),
268 final(owner).list == old(owner).list.insert(0, final(frame_own).meta_own),
269 old(owner).list_id != 0 ==> final(owner).list_id == old(owner).list_id,
270 final(owner).list_id != 0,
271 final(frame_own).meta_own.paddr == old(frame_own).meta_own.paddr,
272 final(frame_own).meta_own.in_list == final(owner).list_id,
273 )]
274 pub fn push_front(&mut self, frame: UniqueFrame<Link<M>>) {
275 let current = self.front;
276 let tracked owner0 = LinkedListOwner::tracked_take(owner);
277 let tracked mut cursor_own = CursorOwner::tracked_front_owner(owner0);
278 let mut cursor = CursorMut { list: self, current };
279
280 #[verus_spec(with Tracked(regions), Tracked(&mut cursor_own), Tracked(frame_own))]
281 cursor.insert_before(frame);
282
283 proof {
284 *owner = cursor_own.list_own;
285 }
286 }
287
288 #[verus_spec(r =>
300 with
301 Tracked(regions): Tracked<&mut MetaRegionOwners>,
302 Tracked(owner): Tracked<LinkedListOwner<M>>,
303 Tracked(frame_own): Tracked<UniqueFrameOwner<Link<M>>>,
304 requires
305 old(regions).inv(),
306 old(self).wf_region(owner, *old(regions)),
307 owner.relate_region(*old(regions)),
308 ensures
309 owner.list.len() == 0 ==> r.is_none(),
310 r.is_some() ==> (r->0).1@.meta_own@ == owner.list[0]@,
311 r.is_some() ==> (r->0).0.frame_link_inv((r->0).1@, *final(regions)),
312 )]
313 pub fn pop_front(&mut self) -> Option<
314 (UniqueFrame<Link<M>>, Tracked<UniqueFrameOwner<Link<M>>>),
315 > {
316 let tracked mut cursor_own = CursorOwner::tracked_front_owner(owner);
317 let current = self.front;
318 let mut cursor = CursorMut { list: self, current };
319
320 proof {
321 if owner.list.len() > 0 {
322 owner.lemma_relate_region_at_index(*regions, 0);
323 owner.lemma_relate_region_at_facts(*regions, 0);
324 }
325 }
326
327 #[verus_spec(with Tracked(regions), Tracked(&mut cursor_own))]
328 cursor.take_current()
329 }
330
331 #[verus_spec(
343 with
344 Tracked(regions): Tracked<&mut MetaRegionOwners>,
345 Tracked(owner): Tracked<&mut LinkedListOwner<M>>,
346 Tracked(frame_own): Tracked<&mut UniqueFrameOwner<Link<M>>>,
347 requires
348 old(self).wf_region(*old(owner), *old(regions)),
349 old(owner).relate_region(*old(regions)),
350 frame.inv(),
351 old(frame_own).inv(),
352 frame.wf_with_region(*old(frame_own), *old(regions)),
353 frame.frame_link_inv(*old(frame_own), *old(regions)),
354 old(regions).inv(),
355 ensures
356 final(owner).relate_region(*final(regions)),
357 final(regions).inv(),
358 old(owner).list.len() > 0 ==> final(owner).list == old(owner).list.insert(
359 old(owner).list.len() - 1, final(frame_own).meta_own),
360 old(owner).list.len() == 0 ==> final(owner).list == old(owner).list.insert(
361 0, final(frame_own).meta_own),
362 old(owner).list_id != 0 ==> final(owner).list_id == old(owner).list_id,
365 final(owner).list_id != 0,
366 final(frame_own).meta_own.paddr == old(frame_own).meta_own.paddr,
367 final(frame_own).meta_own.in_list == final(owner).list_id,
368 )]
369 pub fn push_back(&mut self, frame: UniqueFrame<Link<M>>) {
370 let current = self.back;
371 let tracked owner0 = LinkedListOwner::tracked_take(owner);
372 let tracked mut cursor_own = CursorOwner::tracked_back_owner(owner0);
373 let mut cursor = CursorMut { list: self, current };
374
375 #[verus_spec(with Tracked(regions), Tracked(&mut cursor_own), Tracked(frame_own))]
376 cursor.insert_before(frame);
377
378 proof {
379 *owner = cursor_own.list_own;
380 }
381 }
382
383 #[verus_spec(r =>
396 with
397 Tracked(regions): Tracked<&mut MetaRegionOwners>,
398 Tracked(owner): Tracked<LinkedListOwner<M>>,
399 Tracked(frame_own): Tracked<UniqueFrameOwner<Link<M>>>,
400 requires
401 old(regions).inv(),
402 old(self).wf_region(owner, *old(regions)),
403 owner.relate_region(*old(regions)),
404 ensures
405 owner.list.len() == 0 ==> r.is_none(),
406 r.is_some() ==> (r->0).1@.meta_own@ == owner.list[owner.list.len() - 1]@,
407 r.is_some() ==> (r->0).0.frame_link_inv((r->0).1@, *final(regions)),
408 )]
409 pub fn pop_back(&mut self) -> Option<
410 (UniqueFrame<Link<M>>, Tracked<UniqueFrameOwner<Link<M>>>),
411 > {
412 let current = self.back;
413 let tracked mut cursor_own = CursorOwner::tracked_back_owner(owner);
414 let mut cursor = CursorMut { list: self, current };
415
416 proof {
417 if owner.list.len() > 0 {
418 owner.lemma_relate_region_at_index(*regions, owner.list.len() - 1);
419 owner.lemma_relate_region_at_facts(*regions, owner.list.len() - 1);
420 }
421 }
422
423 #[verus_spec(with Tracked(regions), Tracked(&mut cursor_own))]
424 cursor.take_current()
425 }
426
427 #[verus_spec(r =>
441 with
442 Tracked(regions): Tracked<&mut MetaRegionOwners>,
443 Tracked(slot_own): Tracked<&MetaSlotOwner>,
444 Tracked(owner): Tracked<&mut LinkedListOwner<M>>,
445 requires
446 slot_own.inv(),
447 old(regions).inv(),
448 ensures
449 old(owner).list_id != 0 ==> *final(owner) == *old(owner),
450 )]
451 pub fn contains(&mut self, frame: Paddr) -> bool {
452 proof_decl! {
453 let ghost idx = frame_to_index(frame);
454 if valid_frame_paddr(frame) {
455 regions.lemma_contains_valid_frame_paddr(frame);
456 }
457 let tracked slot_perm = if valid_frame_paddr(frame) {
458 Some(*regions.slots.tracked_borrow(idx))
459 } else {
460 None
461 };
462 }
463 let Ok(slot) = (#[verus_spec(with Tracked(slot_perm))]
464 crate::mm::frame::meta::get_slot(frame)) else {
465 return false;
466 };
467
468 let tracked mut slot_own = regions.slot_owners.tracked_borrow_mut(idx);
469
470 let tracked mut inner_perms = &mut slot_own;
471
472 slot.in_list.load(Tracked(&mut inner_perms.in_list_perm))
473 == #[verus_spec(with Tracked(owner))]
474 self.lazy_get_id()
475 }
476
477 #[verus_spec(r =>
495 with
496 Tracked(regions): Tracked<&mut MetaRegionOwners>,
497 Tracked(owner): Tracked<LinkedListOwner<M>>,
498 -> cursor_owner: Tracked<Option<CursorOwner<M>>>,
499 requires
500 old(regions).inv(),
501 ensures
502 !valid_frame_paddr(frame) ==> r is None,
503 final(regions).inv(),
504 final(regions).slots == old(regions).slots,
505 final(regions).slot_owners.dom() == old(regions).slot_owners.dom(),
506 )]
507 pub fn cursor_mut_at(&mut self, frame: Paddr) -> Option<CursorMut<'_, M>> {
508 proof_decl! {
509 let ghost idx = frame_to_index(frame);
510 if valid_frame_paddr(frame) {
511 regions.lemma_contains_valid_frame_paddr(frame);
512 }
513
514 let tracked slot_perm = if valid_frame_paddr(frame) {
515 Some(*regions.slots.tracked_borrow(idx))
516 } else {
517 None
518 };
519 }
520 let Ok(slot) = (#[verus_spec(with Tracked(slot_perm))]
521 crate::mm::frame::meta::get_slot(frame)) else {
522 return {
523 proof_with!(|= Tracked(None));
524 None
525 };
526 };
527
528 let tracked mut slot_own = regions.slot_owners.tracked_borrow_mut(idx);
529 let tracked mut inner_perms = &mut slot_own;
530
531 let contains = slot.in_list.load(Tracked(&mut inner_perms.in_list_perm))
532 == #[verus_spec(with Tracked(&owner))]
533 self.lazy_get_id();
534
535 if contains {
536 proof_decl!{
537 let ghost link = owner.list.filter(|link: LinkOwner| link.paddr == frame).first();
538 let ghost index = owner.list.index_of(link);
539 let tracked cursor_owner = CursorOwner::tracked_cursor_mut_at_owner(owner, index);
540 }
541
542 let meta_ptr = ReprPtr::<MetaSlotStorage, Link<M>>::from_pptr(
543 PPtr::<MetaSlotStorage>::from_addr(frame_to_meta(frame)),
544 );
545 proof_with!(|= Tracked(Some(cursor_owner)));
546 Some(CursorMut { list: self, current: Some(meta_ptr) })
547 } else {
548 proof_with!(|= Tracked(None));
549 None
550 }
551 }
552
553 #[verus_spec(r =>
568 with
569 Tracked(owner): Tracked<LinkedListOwner<M>>,
570 requires
571 old(self).wf(owner),
572 owner.inv(),
573 ensures
574 r.0.wf(r.1@),
575 r.1@.inv(),
576 r.1@ == CursorOwner::front_owner(owner),
577 )]
578 pub fn cursor_front_mut(&mut self) -> (CursorMut<'_, M>, Tracked<CursorOwner<M>>) {
579 let current = self.front;
580
581 (CursorMut { list: self, current }, Tracked(CursorOwner::tracked_front_owner(owner)))
582 }
583
584 #[verus_spec(
599 with
600 Tracked(owner): Tracked<LinkedListOwner<M>>,
601 )]
602 pub fn cursor_back_mut(&mut self) -> (res: (CursorMut<'_, M>, Tracked<CursorOwner<M>>))
603 requires
604 old(self).wf(owner),
605 owner.inv(),
606 ensures
607 res.0.wf(res.1@),
608 res.1@.inv(),
609 res.1@ == CursorOwner::back_owner(owner),
610 {
611 let current = self.back;
612
613 (CursorMut { list: self, current }, Tracked(CursorOwner::tracked_back_owner(owner)))
614 }
615
616 #[verus_spec(
618 with Tracked(owner): Tracked<&mut LinkedListOwner<M>>
619 )]
620 fn cursor_at_ghost_mut(&mut self) -> CursorMut<'_, M> {
621 CursorMut { list: self, current: None }
622 }
623
624 #[verifier::external_body]
628 #[verus_spec(
629 with Tracked(owner): Tracked<& LinkedListOwner<M>>
630 )]
631 fn lazy_get_id(&mut self) -> (id: u64)
632 ensures
633 owner.list_id != 0 ==> id == owner.list_id,
634 final(self).size == old(self).size,
635 final(self).front == old(self).front,
636 final(self).back == old(self).back,
637 old(self).list_id != 0 ==> final(self).list_id == old(self).list_id,
638 id != 0,
639 final(self).list_id == id,
640 {
641 unimplemented!()}
660}
661
662impl<'a, M: AnyFrameMeta + Repr<MetaSlotSmall>> CursorMut<'a, M> {
663 #[verus_spec(
670 with Tracked(owner): Tracked<CursorOwner<M>>,
671 Tracked(regions): Tracked<&MetaRegionOwners>,
672 )]
673 pub fn move_next(&mut self)
674 requires
675 owner.wf_with_region(*regions),
676 old(self).wf_region(owner, *regions),
677 ensures
678 owner.move_next_owner_spec()@ == owner@.move_next_spec(),
679 owner.move_next_owner_spec().wf_with_region(*regions),
680 final(self).wf_region(owner.move_next_owner_spec(), *regions),
681 {
682 proof {
683 owner.list_own.lemma_relate_region_shape(*regions);
684 if self.current is Some {
685 owner.list_own.lemma_relate_region_at_index(*regions, owner.index);
686 owner.list_own.lemma_relate_region_at_facts(*regions, owner.index);
687 }
688 if owner.index < owner.length() - 1 {
689 owner.list_own.lemma_relate_region_at_index(*regions, owner.index + 1);
690 owner.list_own.lemma_relate_region_at_facts(*regions, owner.index + 1);
691 }
692 }
693
694 self.current = match self.current {
695 Some(current) => {
697 proof_decl!{
698 let ghost idx = meta_to_index(current.addr());
699 let tracked points_to = regions.slots.tracked_borrow(idx);
700 let tracked metadata_perms =
701 owner.list_own.metadata_perms.tracked_borrow(owner.index);
702 let tracked repr_perm = owner.list_own.repr_perms.tracked_borrow(owner.index);
703 }
704 proof {
705 assert(regions.contains(idx));
706 }
707 let link = borrow_meta(
708 current,
709 Tracked(points_to),
710 Tracked(metadata_perms),
711 Tracked(repr_perm),
712 );
713 link.next
714 },
715 None => self.list.front,
716 };
717
718 proof {
719 LinkedListOwner::<M>::lemma_view_preserves_len(owner.list_own.list);
720 assert(owner.move_next_owner_spec()@.fore == owner@.move_next_spec().fore);
721 assert(owner.move_next_owner_spec()@.rear == owner@.move_next_spec().rear);
722 }
723 }
724
725 #[verus_spec(
732 with Tracked(owner): Tracked<CursorOwner<M>>,
733 Tracked(regions): Tracked<&MetaRegionOwners>,
734 )]
735 pub fn move_prev(&mut self)
736 requires
737 owner.wf_with_region(*regions),
738 old(self).wf_region(owner, *regions),
739 ensures
740 owner.move_prev_owner_spec()@ == owner@.move_prev_spec(),
741 owner.move_prev_owner_spec().wf_with_region(*regions),
742 final(self).wf_region(owner.move_prev_owner_spec(), *regions),
743 {
744 proof {
745 owner.list_own.lemma_relate_region_shape(*regions);
746 if self.current is Some {
747 owner.list_own.lemma_relate_region_at_index(*regions, owner.index);
748 owner.list_own.lemma_relate_region_at_facts(*regions, owner.index);
749 }
750 if 0 < owner.index {
751 owner.list_own.lemma_relate_region_at_index(*regions, owner.index - 1);
752 owner.list_own.lemma_relate_region_at_facts(*regions, owner.index - 1);
753 }
754 }
755
756 self.current = match self.current {
757 Some(current) => {
759 proof_decl!{
760 let ghost idx = meta_to_index(current.addr());
761 let tracked points_to = regions.slots.tracked_borrow(idx);
762 let tracked metadata_perms =
763 owner.list_own.metadata_perms.tracked_borrow(owner.index);
764 let tracked repr_perm = owner.list_own.repr_perms.tracked_borrow(owner.index);
765 }
766 proof {
767 assert(regions.contains(idx));
768 }
769
770 let link = borrow_meta(
771 current,
772 Tracked(points_to),
773 Tracked(metadata_perms),
774 Tracked(repr_perm),
775 );
776 link.prev
777 },
778 None => self.list.back,
779 };
780
781 proof {
782 LinkedListOwner::<M>::lemma_view_preserves_len(owner.list_own.list);
783
784 if owner@.list_model.list.len() > 0 {
785 if owner@.fore.len() > 0 {
786 assert(owner.move_prev_owner_spec()@.fore == owner@.move_prev_spec().fore);
787 assert(owner.move_prev_owner_spec()@.rear == owner@.move_prev_spec().rear);
788 if owner@.rear.len() > 0 {
789 owner.list_own.lemma_relate_region_at_index(*regions, owner.index);
790 owner.list_own.lemma_relate_region_at_facts(*regions, owner.index);
791 }
792 } else {
793 owner.list_own.lemma_relate_region_at_index(*regions, owner.index);
794 owner.list_own.lemma_relate_region_at_facts(*regions, owner.index);
795 assert(owner.move_prev_owner_spec()@.rear == owner@.move_prev_spec().rear);
796 assert(owner@.rear == owner@.list_model.list);
797 }
798 }
799 }
800 }
801
802 #[verus_spec(
816 with Tracked(owner): Tracked<&'b mut CursorOwner<M>>,
817 Tracked(regions): Tracked<&'b mut MetaRegionOwners>,
818 )]
819 pub fn current_meta<'b>(&'b mut self) -> (res: Option<&'b mut M>)
820 requires
821 old(self).wf_region(*old(owner), *old(regions)),
822 old(owner).wf_with_region(*old(regions)),
823 old(regions).inv(),
824 ensures
825 final(owner).index == old(owner).index,
826 final(owner).list_own.list == old(owner).list_own.list,
827 final(owner).list_own.list_id == old(owner).list_own.list_id,
828 *final(self) == *old(self),
829 res.is_some() == (0 <= final(owner).index < final(owner).length()),
830 final(regions).slots.dom() == old(regions).slots.dom(),
831 final(regions).slot_owners.dom() == old(regions).slot_owners.dom(),
832 {
833 match self.current {
839 Some(current) => {
840 proof {
841 owner.list_own.lemma_relate_region_shape(*regions);
842 owner.list_own.lemma_relate_region_at_index(*regions, owner.index);
843 owner.list_own.lemma_relate_region_at_facts(*regions, owner.index);
844 }
845 let ghost idx = meta_to_index(current.addr());
846 proof {
847 assert(regions.contains(idx));
848 }
849 let tracked points_to = regions.slots.tracked_borrow(idx);
850 let tracked repr_perm = owner.list_own.repr_perms.tracked_borrow_mut(owner.index);
851 let tracked metadata_perms = owner.list_own.metadata_perms.tracked_borrow_mut(
852 owner.index,
853 );
854 Some(
855 &mut borrow_meta_mut(
856 current,
857 Tracked(points_to),
858 Tracked(metadata_perms),
859 Tracked(repr_perm),
860 ).meta,
861 )
862 },
863 None => None,
864 }
865 }
866
867 #[verus_spec(
885 with Tracked(regions) : Tracked<&mut MetaRegionOwners>,
886 Tracked(owner) : Tracked<&mut CursorOwner<M>>
887 )]
888 #[verifier::spinoff_prover]
889 #[verifier::rlimit(250)]
890 pub fn take_current(&mut self) -> (res: Option<
891 (UniqueFrame<Link<M>>, Tracked<UniqueFrameOwner<Link<M>>>),
892 >)
893 requires
894 old(self).wf_region(*old(owner), *old(regions)),
895 old(owner).wf_with_region(*old(regions)),
896 old(regions).inv(),
897 ensures
898 old(owner).length() == 0 ==> res.is_none(),
899 old(self).current.is_some() ==> res.is_some(),
900 res.is_some() ==> (res->0).1@.meta_own@ == old(owner).list_own.list[old(owner).index]@,
901 res.is_some() ==> final(owner)@ == old(owner)@.remove(),
902 res.is_some() ==> (res->0).0.frame_link_inv((res->0).1@, *final(regions)),
903 res.is_some() ==> final(owner).wf_with_region(*final(regions)),
905 res.is_some() ==> final(self).wf_region(*final(owner), *final(regions)),
906 res.is_none() ==> *final(owner) == *old(owner),
907 final(regions).inv(),
908 res.is_some() ==> final(owner).index == old(owner).index,
910 res.is_some() ==> final(owner).list_own.list == old(owner).list_own.list.remove(
911 old(owner).index,
912 ),
913 final(owner).list_own.list_id == old(owner).list_own.list_id,
914 res.is_some() ==> {
915 let paddr = old(self).current->0.addr();
916 let idx = meta_to_index(paddr);
917 &&& final(regions).slots.dom() == old(regions).slots.dom()
918 &&& final(regions).ref_count(idx) == REF_COUNT_UNIQUE
919 &&& final(regions).slot_owners[idx].in_list_perm.value() == 0
920 &&& (res->0).0.tracked_metadata_perm@->0.storage_perm.is_init()
921 &&& (res->0).0.tracked_metadata_perm@->0.vtable_ptr_perm.is_init()
922 &&& final(regions).slot_owners[idx].slot_vaddr == index_to_meta(idx)
923 &&& final(regions).slot_owners[idx].paths_in_pt == old(
924 regions,
925 ).slot_owners[idx].paths_in_pt
926 },
927 res.is_some() ==> forall|j: int|
928 #![trigger final(regions).slot_owners[j]]
929 j != meta_to_index(old(self).current->0.addr()) ==> {
930 &&& final(regions).slot_owners[j].usage == old(regions).slot_owners[j].usage
931 &&& final(regions).slot_owners[j].slot_vaddr == old(
932 regions,
933 ).slot_owners[j].slot_vaddr
934 &&& final(regions).slot_owners[j].paths_in_pt == old(
935 regions,
936 ).slot_owners[j].paths_in_pt
937 },
938 res.is_none() ==> *final(regions) == *old(regions),
939 res.is_some() ==> (res->0).0.inv(),
941 res.is_some() ==> (res->0).0.wf((res->0).1@),
942 res.is_some() ==> (res->0).1@.inv(),
943 res.is_some() ==> (res->0).0.wf_with_region((res->0).1@, *final(regions)),
944 res.is_some() ==> (res->0).1@.slot_index == meta_to_index(old(self).current->0.addr()),
945 res.is_some() ==> (res->0).0.ptr.addr() == old(self).current->0.addr(),
946 {
947 hide(MetaSlotOwner::storage_perm);
949 hide(MetaSlotOwner::vtable_ptr_perm);
950 hide(<MetaRegionOwners as Inv>::inv);
951 let ghost owner0 = *owner;
952 let ghost regions0 = *regions;
953
954 let current = self.current?;
955
956 proof {
957 owner.list_own.lemma_relate_region_shape(*regions);
958 owner.list_own.lemma_relate_region_at_index(*regions, owner.index);
959 owner.list_own.lemma_relate_region_at_facts(*regions, owner.index);
960 if owner.index > 0 {
961 owner.list_own.lemma_relate_region_at_index(*regions, owner.index - 1);
962 owner.list_own.lemma_relate_region_at_facts(*regions, owner.index - 1);
963 }
964 if owner.index < owner.list_own.list.len() - 1 {
965 owner.list_own.lemma_relate_region_at_index(*regions, owner.index + 1);
966 owner.list_own.lemma_relate_region_at_facts(*regions, owner.index + 1);
967 }
968 }
969
970 let meta_ptr = current.addr();
971 let paddr = meta_to_frame(meta_ptr);
972 let ghost idx = frame_to_index(paddr);
973
974 proof {
975 lemma_meta_region_inv_at(regions0, idx);
976 }
977
978 let tracked mut cur_own = owner.list_own.list.tracked_remove(owner.index);
979 let tracked cur_repr_perm = owner.list_own.repr_perms.tracked_remove(owner.index);
980 let tracked cur_metadata_perm = owner.list_own.metadata_perms.tracked_remove(owner.index);
981
982 proof_decl! {
983 let tracked mut frame_own: UniqueFrameOwner<Link<M>>;
984 }
985 let mut frame = unsafe {
986 #[verus_spec(with
988 Tracked(regions.tracked_borrow_slot(paddr)),
989 Tracked(cur_own),
990 Tracked(cur_repr_perm),
991 Tracked(cur_metadata_perm) => Tracked(frame_own)
992 )]
993 UniqueFrame::<Link<M>>::from_raw(paddr)
994 };
995
996 proof {
997 assert(regions.slots.dom() == regions0.slots.dom());
998 }
999
1000 let next_ptr = (#[verus_spec(with Tracked(&frame_own))]
1001 frame.meta()).next;
1002 let prev_ptr = (#[verus_spec(with Tracked(&frame_own))]
1003 frame.meta()).prev;
1004
1005 if let Some(prev) = prev_ptr {
1006 let ghost prev_idx = meta_to_index(owner.list_own.list[owner.index - 1].paddr);
1007 proof {
1008 lemma_meta_region_inv_at(*regions, prev_idx);
1009 }
1010 let tracked prev_points_to = regions.slots.tracked_borrow(prev_idx);
1011 let tracked prev_repr_perm = owner.list_own.repr_perms.tracked_borrow_mut(
1012 owner.index - 1,
1013 );
1014 let tracked prev_metadata_perm = owner.list_own.metadata_perms.tracked_borrow_mut(
1015 owner.index - 1,
1016 );
1017 let prev_meta = borrow_meta_mut(
1018 prev,
1019 Tracked(prev_points_to),
1020 Tracked(prev_metadata_perm),
1021 Tracked(prev_repr_perm),
1022 );
1023 prev_meta.next = next_ptr;
1024
1025 } else {
1026 self.list.front = next_ptr;
1027 }
1028
1029 if let Some(next) = next_ptr {
1030 let ghost next_idx = meta_to_index(owner.list_own.list[owner.index].paddr);
1031 proof {
1032 lemma_meta_region_inv_at(*regions, next_idx);
1033 }
1034 let tracked next_points_to = regions.slots.tracked_borrow(next_idx);
1035 let tracked next_repr_perm = owner.list_own.repr_perms.tracked_borrow_mut(owner.index);
1036 let tracked next_metadata_perm = owner.list_own.metadata_perms.tracked_borrow_mut(
1037 owner.index,
1038 );
1039 let next_meta = borrow_meta_mut(
1040 next,
1041 Tracked(next_points_to),
1042 Tracked(next_metadata_perm),
1043 Tracked(next_repr_perm),
1044 );
1045 next_meta.prev = prev_ptr;
1046
1047 self.current = Some(next);
1048 } else {
1049 self.list.back = prev_ptr;
1050
1051 self.current = None;
1052 }
1053
1054 (#[verus_spec(with Tracked(&mut frame_own))]
1055 frame.meta_mut()).next = None;
1056 (#[verus_spec(with Tracked(&mut frame_own))]
1057 frame.meta_mut()).prev = None;
1058
1059 let tracked mut frame_so = regions.slot_owners.tracked_borrow_mut(idx);
1060 let tracked mut fip = &mut frame_so;
1061 let slot = frame.slot();
1062 slot.in_list.store(Tracked(&mut fip.in_list_perm), 0);
1063 proof {
1064 assert(regions.inv()) by {
1065 reveal(MetaSlotOwner::storage_perm);
1066 reveal(MetaSlotOwner::vtable_ptr_perm);
1067 reveal(<MetaRegionOwners as Inv>::inv);
1068 };
1069 assert(regions.slots.dom() == regions0.slots.dom());
1070 assert forall|j: int| #![trigger regions0.slot_owners[j]] j != idx implies {
1071 &&& regions.slot_owners[j].usage == regions0.slot_owners[j].usage
1072 &&& regions.slot_owners[j].slot_vaddr == regions0.slot_owners[j].slot_vaddr
1073 &&& regions.slot_owners[j].paths_in_pt == regions0.slot_owners[j].paths_in_pt
1074 } by {}
1075 }
1076
1077 self.list.size -= 1;
1078
1079 proof {
1080 owner0.remove_owner_spec_implies_model_spec(*owner);
1081 let ghost oldl = owner0.list_own;
1082 let ghost nn = owner0.index as int;
1083 assert forall|p: int|
1084 #![trigger meta_to_index(oldl.list[p].paddr)]
1085 (0 <= p < oldl.list.len() && p != nn) implies ({
1086 let i = meta_to_index(oldl.list[p].paddr);
1087 let np = if p < nn {
1088 p
1089 } else {
1090 p - 1
1091 };
1092 let fp = owner.list_own.meta_value_at(*regions, np);
1093 &&& regions.contains(i)
1094 &&& regions.slots[i].addr() == oldl.list[p].paddr
1095 &&& regions.slots[i].pptr() == regions0.slots[i].pptr()
1096 &&& regions.ref_count(i) == REF_COUNT_UNIQUE
1097 &&& regions.slot_owners[i].metadata_perm.is_resource_vacant()
1098 &&& owner.list_own.metadata_perms[np].storage_perm.id()
1099 == regions.slots[i].value().storage.id()
1100 &&& owner.list_own.metadata_perms[np].vtable_ptr_perm.pptr()
1101 == regions.slots[i].value().vtable_ptr
1102 &&& owner.list_own.metadata_perms[np].vtable_ptr_perm.is_init()
1103 &&& regions.slot_owners[i].usage is Frame
1104 &&& regions.slot_owners[i].in_list_perm.value() == owner.list_own.list_id
1105 &&& owner.list_own.meta_wf_at(*regions, np)
1106 &&& regions.slots[i].addr() % META_SLOT_SIZE == 0
1107 &&& FRAME_METADATA_RANGE.start <= regions.slots[i].addr()
1108 < FRAME_METADATA_RANGE.start + MAX_NR_PAGES * META_SLOT_SIZE
1109 &&& (p == nn - 1 ==> fp.next == oldl.meta_value_at(regions0, nn).next)
1110 &&& (p != nn - 1 ==> fp.next == oldl.meta_value_at(regions0, p).next)
1111 &&& (p == nn + 1 ==> fp.prev == oldl.meta_value_at(regions0, nn).prev)
1112 &&& (p != nn + 1 ==> fp.prev == oldl.meta_value_at(regions0, p).prev)
1113 }) by {
1114 let i = meta_to_index(oldl.list[p].paddr);
1115 let np = if p < nn {
1116 p
1117 } else {
1118 p - 1
1119 };
1120 let fp = owner.list_own.meta_value_at(*regions, np);
1121 oldl.lemma_relate_region_at_index(regions0, p);
1122 oldl.lemma_relate_region_at_index(regions0, nn);
1123 oldl.lemma_relate_region_indices_distinct(regions0, p, nn);
1124 oldl.lemma_relate_region_at_facts(regions0, p);
1125 oldl.lemma_relate_region_at_facts(regions0, nn);
1126 assert(regions.contains(i));
1127 }
1128 LinkedListOwner::lemma_pop_preserves_relate_region(
1129 oldl,
1130 regions0,
1131 owner.list_own,
1132 *regions,
1133 nn,
1134 );
1135 }
1136 Some((frame, Tracked(frame_own)))
1137 }
1138
1139 #[verus_spec(
1156 with Tracked(regions): Tracked<&mut MetaRegionOwners>,
1157 Tracked(owner): Tracked<&mut CursorOwner<M>>,
1158 Tracked(frame_own): Tracked<&mut UniqueFrameOwner<Link<M>>>
1159 )]
1160 #[verifier::spinoff_prover]
1161 #[verifier::rlimit(200)]
1162 pub fn insert_before(&mut self, mut frame: UniqueFrame<Link<M>>)
1163 requires
1164 old(self).wf_region(*old(owner), *old(regions)),
1165 old(owner).wf_with_region(*old(regions)),
1166 old(regions).inv(),
1167 frame.inv(),
1168 old(frame_own).inv(),
1169 frame.wf_with_region(*old(frame_own), *old(regions)),
1170 frame.frame_link_inv(*old(frame_own), *old(regions)),
1171 ensures
1172 final(owner).wf_with_region(*final(regions)),
1173 final(self).wf_region(*final(owner), *final(regions)),
1174 final(regions).inv(),
1175 final(owner).list_own.list == old(owner).list_own.list.insert(
1176 old(owner).index,
1177 final(frame_own).meta_own,
1178 ),
1179 old(owner).list_own.list_id != 0 ==> final(owner).list_own.list_id == old(
1182 owner,
1183 ).list_own.list_id,
1184 final(owner).list_own.list_id != 0,
1185 final(owner).index == old(owner).index + 1,
1186 final(frame_own).meta_own.paddr == old(frame_own).meta_own.paddr,
1187 final(frame_own).meta_own.in_list == final(owner).list_own.list_id,
1188 final(owner)@ == old(owner)@.insert(final(frame_own).meta_own@),
1189 {
1190 hide(<MetaRegionOwners as Inv>::inv);
1191 let ghost owner0 = *owner;
1192 let ghost regions0 = *regions;
1193 let ghost nn = owner.index as int;
1194
1195 proof {
1196 assert(owner0.list_own.repr_perms.len() == owner0.list_own.list.len()) by {
1197 reveal(LinkedListOwner::relate_region);
1198 };
1199 assert(owner0.list_own.metadata_perms.len() == owner0.list_own.list.len()) by {
1200 reveal(LinkedListOwner::relate_region);
1201 };
1202 assert(owner0.list_own.list.len() > 0 ==> owner0.list_own.list_id != 0) by {
1203 reveal(LinkedListOwner::relate_region);
1204 };
1205 lemma_meta_region_inv_at(regions0, frame_own.slot_index);
1206 owner0.list_own.lemma_length_lt_usize_max(regions0);
1207 if nn > 0 {
1208 assert(owner0.list_own.relate_region_at(regions0, nn - 1)) by {
1209 reveal(LinkedListOwner::relate_region);
1210 };
1211 owner.list_own.lemma_relate_region_at_facts(*regions, nn - 1);
1212 lemma_meta_region_inv_at(
1213 regions0,
1214 meta_to_index(owner0.list_own.list[nn - 1].paddr),
1215 );
1216 }
1217 if nn < owner.list_own.list.len() {
1218 assert(owner0.list_own.relate_region_at(regions0, nn)) by {
1219 reveal(LinkedListOwner::relate_region);
1220 };
1221 owner.list_own.lemma_relate_region_at_facts(*regions, nn);
1222 lemma_meta_region_inv_at(regions0, meta_to_index(owner0.list_own.list[nn].paddr));
1223 }
1224 assert forall|p: int|
1225 #![trigger
1226 regions0.slot_owners[meta_to_index(owner0.list_own.list[p].paddr)]]
1227 0 <= p < owner0.list_own.list.len() implies frame_own.slot_index != meta_to_index(
1228 owner0.list_own.list[p].paddr,
1229 ) by {
1230 lemma_insert_before_slot_distinct(
1231 owner0.list_own,
1232 regions0,
1233 frame_own.slot_index,
1234 nn,
1235 );
1236 }
1237 }
1238
1239 let frame_ptr = ReprPtr::<MetaSlotStorage, Link<M>>::from_pptr(
1240 PPtr::<MetaSlotStorage>::from_addr(frame.ptr.addr()),
1241 );
1242
1243 if let Some(current) = self.current {
1244 proof_decl!{
1245 let ghost idx = meta_to_index(current.addr());
1246 let tracked points_to = regions.slots.tracked_borrow(idx);
1247 let tracked metadata_perms =
1248 owner.list_own.metadata_perms.tracked_borrow(owner.index);
1249 let tracked repr_perm = owner.list_own.repr_perms.tracked_borrow(owner.index);
1250 }
1251
1252 let opt_prev_link: Option<ReprPtr<MetaSlotStorage, Link<M>>> = borrow_meta(
1254 current,
1255 Tracked(points_to),
1256 Tracked(metadata_perms),
1257 Tracked(repr_perm),
1258 ).prev;
1259
1260 if let Some(prev_link) = opt_prev_link {
1261 let prev = prev_link;
1262
1263 (#[verus_spec(with Tracked(frame_own))]
1264 frame.meta_mut()).prev = Some(prev_link);
1265 (#[verus_spec(with Tracked(frame_own))]
1266 frame.meta_mut()).next = Some(current);
1267
1268 let ghost prev_idx = meta_to_index(owner.list_own.list[nn - 1].paddr);
1269 proof {
1270 assert(prev_idx != idx) by {
1271 reveal(LinkedListOwner::relate_region);
1272 };
1273 }
1274 let tracked prev_points_to = regions.slots.tracked_borrow(prev_idx);
1275 let tracked prev_repr_perm = owner.list_own.repr_perms.tracked_borrow_mut(nn - 1);
1276 let tracked prev_metadata_perm = owner.list_own.metadata_perms.tracked_borrow_mut(
1277 nn - 1,
1278 );
1279 let prev_meta = borrow_meta_mut(
1280 prev,
1281 Tracked(prev_points_to),
1282 Tracked(prev_metadata_perm),
1283 Tracked(prev_repr_perm),
1284 );
1285 prev_meta.next = Some(frame_ptr);
1286
1287 let ghost current_idx = meta_to_index(owner.list_own.list[nn].paddr);
1288 let tracked current_points_to = regions.slots.tracked_borrow(current_idx);
1289 let tracked current_repr_perm = owner.list_own.repr_perms.tracked_borrow_mut(nn);
1290 let tracked current_metadata_perm =
1291 owner.list_own.metadata_perms.tracked_borrow_mut(nn);
1292 let current_meta = borrow_meta_mut(
1293 current,
1294 Tracked(current_points_to),
1295 Tracked(current_metadata_perm),
1296 Tracked(current_repr_perm),
1297 );
1298 current_meta.prev = Some(frame_ptr);
1299 } else {
1300 (#[verus_spec(with Tracked(frame_own))]
1301 frame.meta_mut()).next = Some(current);
1302
1303 let ghost current_idx = meta_to_index(owner.list_own.list[nn].paddr);
1304 let tracked current_points_to = regions.slots.tracked_borrow(current_idx);
1305 let tracked current_repr_perm = owner.list_own.repr_perms.tracked_borrow_mut(nn);
1306 let tracked current_metadata_perm =
1307 owner.list_own.metadata_perms.tracked_borrow_mut(nn);
1308 let current_meta = borrow_meta_mut(
1309 current,
1310 Tracked(current_points_to),
1311 Tracked(current_metadata_perm),
1312 Tracked(current_repr_perm),
1313 );
1314 current_meta.prev = Some(frame_ptr);
1315 self.list.front = Some(frame_ptr);
1316 }
1317 } else {
1318 if let Some(back) = self.list.back {
1319 (#[verus_spec(with Tracked(frame_own))]
1320 frame.meta_mut()).prev = Some(back);
1321
1322 let ghost back_idx = meta_to_index(owner.list_own.list[nn - 1].paddr);
1323 proof {
1324 assert(0 <= nn - 1 < owner.list_own.repr_perms.len());
1325 }
1326 let tracked back_points_to = regions.slots.tracked_borrow(back_idx);
1327 let tracked back_repr_perm = owner.list_own.repr_perms.tracked_borrow_mut(nn - 1);
1328 let tracked back_metadata_perm = owner.list_own.metadata_perms.tracked_borrow_mut(
1329 nn - 1,
1330 );
1331 let back_meta = borrow_meta_mut(
1332 back,
1333 Tracked(back_points_to),
1334 Tracked(back_metadata_perm),
1335 Tracked(back_repr_perm),
1336 );
1337 back_meta.next = Some(frame_ptr);
1338 self.list.back = Some(frame_ptr);
1339 } else {
1340 self.list.front = Some(frame_ptr);
1342 self.list.back = Some(frame_ptr);
1343 }
1344 }
1345
1346 #[verus_spec(with Tracked(&owner.list_own))]
1347 let list_id = self.list.lazy_get_id();
1348
1349 proof {
1350 assert(owner0.list_own.list.len() > 0 ==> list_id == owner0.list_own.list_id);
1351 }
1352 let tracked mut frame_so = regions.slot_owners.tracked_borrow_mut(frame_own.slot_index);
1353 let tracked mut fip = &mut frame_so;
1354 let slot = frame.slot();
1355 slot.in_list.store(Tracked(&mut fip.in_list_perm), list_id);
1356 proof {
1357 assert(regions.inv()) by {
1358 reveal(<MetaRegionOwners as Inv>::inv);
1359 };
1360 assert(frame.wf_with_region(*frame_own, *regions));
1361 }
1362
1363 #[verus_spec(with
1364 Tracked(&*frame_own) => Tracked(frame_metadata_perm)
1365 )]
1366 let _ = frame.into_raw();
1367
1368 self.list.size = self.list.size + 1;
1369
1370 proof {
1371 let tracked frame_repr_perm = frame_own.repr_perm.tracked_take();
1372 CursorOwner::<M>::tracked_list_insert(
1373 owner,
1374 &mut frame_own.meta_own,
1375 frame_repr_perm,
1376 frame_metadata_perm,
1377 list_id,
1378 );
1379 let oldl = owner0.list_own;
1380 let nn = owner0.index as int;
1381 let flink = frame_own.meta_own;
1382 let ins = frame_own.slot_index;
1383
1384 assert(owner.list_own.relate_region(*regions)) by {
1385 assert forall|p: int|
1386 #![trigger
1387 owner.list_own.insert_old_slot_post_at(
1388 *regions,
1389 oldl,
1390 regions0,
1391 nn,
1392 flink,
1393 p,
1394 )]
1395 (0 <= p < oldl.list.len()) implies owner.list_own.insert_old_slot_post_at(
1396 *regions,
1397 oldl,
1398 regions0,
1399 nn,
1400 flink,
1401 p,
1402 ) by {
1403 reveal(LinkedListOwner::insert_old_slot_post_at);
1404 assert(oldl.relate_region_at(regions0, p)) by {
1405 reveal(LinkedListOwner::relate_region);
1406 };
1407 oldl.lemma_relate_region_at_facts(regions0, p);
1408 if nn - 1 >= 0 && nn - 1 < oldl.list.len() && p != nn - 1 {
1409 assert(meta_to_index(oldl.list[p].paddr) != meta_to_index(
1410 oldl.list[nn - 1].paddr,
1411 )) by {
1412 reveal(LinkedListOwner::relate_region);
1413 };
1414 }
1415 if nn >= 0 && nn < oldl.list.len() && p != nn {
1416 assert(meta_to_index(oldl.list[p].paddr) != meta_to_index(
1417 oldl.list[nn].paddr,
1418 )) by {
1419 reveal(LinkedListOwner::relate_region);
1420 };
1421 }
1422 }
1423
1424 LinkedListOwner::lemma_insert_preserves_relate_region(
1425 oldl,
1426 regions0,
1427 owner.list_own,
1428 *regions,
1429 nn,
1430 flink,
1431 );
1432 };
1433
1434 owner0.insert_owner_spec_implies_model_spec(flink, *owner);
1435 }
1436 }
1437
1438 pub fn as_list(&self) -> &LinkedList<M> {
1440 self.list
1441 }
1442}
1443
1444impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> TrackDrop for LinkedList<M> {
1445 type State = (LinkedListOwner<M>, MetaRegionOwners);
1446
1447 type Obligation = DropObligation<u64>;
1455
1456 open spec fn tracked_redeem_requires(self, s: Self::State) -> bool {
1457 true
1458 }
1459
1460 open spec fn tracked_redeem_ensures(
1461 self,
1462 s0: Self::State,
1463 s1: Self::State,
1464 obl: Self::Obligation,
1465 ) -> bool {
1466 &&& s0 =~= s1
1467 &&& obl.value() == self.list_id
1468 }
1469
1470 proof fn tracked_redeem(self, tracked s: &mut Self::State) -> (tracked obl: Self::Obligation) {
1471 DropObligation::tracked_mint(self.list_id)
1472 }
1473
1474 open spec fn drop_requires(self, s: Self::State, obl: Self::Obligation) -> bool {
1475 &&& self.wf(s.0)
1476 &&& s.0.inv()
1477 &&& s.1.inv()
1478 &&& forall|i: int|
1479 #![trigger s.0.list[i]]
1480 0 <= i < s.0.list.len() ==> s.1.contains(meta_to_index(s.0.list[i].paddr))
1481 &&& forall|i: int|
1482 #![trigger s.0.list[i]]
1483 0 <= i < s.0.list.len() ==> {
1484 let idx = meta_to_index(s.0.list[i].paddr);
1485 s.1.contains(idx)
1486 }
1487 &&& forall|i: int|
1488 #![trigger s.0.list[i]]
1489 0 <= i < s.0.list.len() ==> {
1490 let idx = meta_to_index(s.0.list[i].paddr);
1491 s.1.ref_count(idx) == REF_COUNT_UNIQUE
1492 }
1493 &&& forall|i: int|
1494 #![trigger s.0.list[i]]
1495 0 <= i < s.0.list.len() ==> {
1496 let idx = meta_to_index(s.0.list[i].paddr);
1497 s.1.slot_owners[idx].paths_in_pt.is_empty()
1498 }
1499 &&& forall|i: int, j: int|
1500 #![trigger s.0.list[i], s.0.list[j]]
1501 0 <= i < j < s.0.list.len() ==> meta_to_index(s.0.list[i].paddr) != meta_to_index(
1502 s.0.list[j].paddr,
1503 )
1504 &&& s.0.relate_region(s.1)
1505 &&& obl.value() == self.list_id
1506 }
1507
1508 open spec fn drop_ensures(
1509 self,
1510 s0: Self::State,
1511 s1: Self::State,
1512 obl: Self::Obligation,
1513 ) -> bool {
1514 &&& s1.0.list.len() == 0
1515 &&& forall|idx: int|
1516 #![trigger s1.1.slot_owners[idx]]
1517 (forall|i: int|
1518 #![trigger s0.0.list[i]]
1519 0 <= i < s0.0.list.len() ==> idx != meta_to_index(s0.0.list[i].paddr)) ==> {
1520 &&& s1.1.slot_owners[idx].usage == s0.1.slot_owners[idx].usage
1521 &&& s1.1.slot_owners[idx].slot_vaddr == s0.1.slot_owners[idx].slot_vaddr
1522 &&& s1.1.slot_owners[idx].paths_in_pt == s0.1.slot_owners[idx].paths_in_pt
1523 }
1524 &&& s1.1.slots.dom() =~= s0.1.slots.dom()
1525 &&& s1.1.inv()
1526 }
1527}
1528
1529impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Drop for LinkedList<M> {
1530 #[verifier::spinoff_prover]
1531 fn drop(
1532 mut self,
1533 Tracked(s): Tracked<&mut Self::State>,
1534 Tracked(obl): Tracked<DropObligation<u64>>,
1535 ) {
1536 proof_decl! {
1537 let tracked mut list_own: LinkedListOwner<M>;
1538 }
1539 let ghost original_list = s.0.list;
1540 let ghost original_list_id = s.0.list_id;
1541 let ghost n = original_list.len();
1542 let ghost original_regions = s.1;
1543 proof {
1544 list_own = LinkedListOwner::<M>::tracked_take(&mut s.0);
1545 }
1546 let tracked regions: &mut MetaRegionOwners = &mut s.1;
1547
1548 #[verus_spec(with Tracked(list_own))]
1549 let cursor_pair = self.cursor_front_mut();
1550 let (mut cursor, Tracked(mut cursor_own)) = cursor_pair;
1551
1552 proof {
1553 if n > 0 {
1554 cursor_own.list_own.lemma_relate_region_at_index(*regions, 0);
1555 cursor_own.list_own.lemma_relate_region_at_index(*regions, n - 1);
1556 cursor_own.list_own.lemma_relate_region_at_facts(*regions, 0);
1557 cursor_own.list_own.lemma_relate_region_at_facts(*regions, n - 1);
1558 }
1559 }
1560
1561 let ghost mut k: int = 0;
1562
1563 loop
1564 invariant_except_break
1565 cursor.wf_region(cursor_own, *regions),
1566 cursor.current.is_some() <==> k < n,
1567 invariant
1568 cursor_own.wf_with_region(*regions),
1569 cursor_own.list_own.list_id == original_list_id,
1570 cursor_own.index == 0,
1571 regions.inv(),
1572 cursor_own.list_own.list.len() == n - k,
1573 0 <= k <= n,
1574 forall|j: int|
1576 #![trigger cursor_own.list_own.list[j]]
1577 0 <= j < n - k ==> cursor_own.list_own.list[j] == original_list[j + k],
1578 forall|idx: int|
1580 #![trigger regions.slot_owners[idx]]
1581 (forall|j: int|
1582 #![trigger original_list[j]]
1583 0 <= j < n ==> idx != meta_to_index(original_list[j].paddr)) ==> {
1584 &&& regions.slot_owners[idx].usage
1585 == original_regions.slot_owners[idx].usage
1586 &&& regions.slot_owners[idx].slot_vaddr
1587 == original_regions.slot_owners[idx].slot_vaddr
1588 &&& regions.slot_owners[idx].paths_in_pt
1589 == original_regions.slot_owners[idx].paths_in_pt
1590 },
1591 regions.slots.dom() == original_regions.slots.dom(),
1592 forall|j: int|
1594 #![trigger original_list[j]]
1595 k <= j < n ==> {
1596 let idx = meta_to_index(original_list[j].paddr);
1597 &&& regions.slot_owners[idx].paths_in_pt
1598 == original_regions.slot_owners[idx].paths_in_pt
1599 },
1600 forall|j: int|
1602 #![trigger original_list[j]]
1603 k <= j < n ==> regions.contains(meta_to_index(original_list[j].paddr)),
1604 forall|i: int, j: int|
1606 #![trigger original_list[i], original_list[j]]
1607 0 <= i < j < n ==> meta_to_index(original_list[i].paddr) != meta_to_index(
1608 original_list[j].paddr,
1609 ),
1610 forall|j: int|
1611 #![trigger original_list[j]]
1612 0 <= j < n ==> {
1613 let idx = meta_to_index(original_list[j].paddr);
1614 &&& original_regions.contains(idx)
1615 &&& original_regions.slot_owners[idx].paths_in_pt.is_empty()
1616 &&& original_regions.ref_count(idx) == REF_COUNT_UNIQUE
1617 },
1618 ensures
1619 k == n,
1620 cursor_own.list_own.list.len() == 0,
1621 decreases n - k,
1622 {
1623 #[verus_spec(with Tracked(regions), Tracked(&mut cursor_own))]
1624 let entry = cursor.take_current();
1625
1626 if let Some(current) = entry {
1627 let (mut frame, frame_own_tracked) = current;
1628 let tracked frame_own = frame_own_tracked.get();
1629 let ghost regions_pre_drop = *regions;
1630
1631 #[verus_spec(with Tracked(frame_own), Tracked(regions))]
1633 frame.drop();
1634
1635 proof {
1636 assert forall|i: int|
1637 #![trigger cursor_own.list_own.list[i]]
1638 0 <= i < cursor_own.list_own.list.len() implies ({
1639 let idx = meta_to_index(cursor_own.list_own.list[i].paddr);
1640 &&& regions.contains(idx)
1641 &&& regions.slot_owners[idx] == regions_pre_drop.slot_owners[idx]
1642 }) by {
1643 let idx = meta_to_index(cursor_own.list_own.list[i].paddr);
1644 let ghost _trig_k = original_list[k as int];
1645 let ghost _trig_ik = original_list[i + k + 1];
1646 assert(cursor_own.list_own.list[i] == original_list[i + k + 1]);
1647
1648 cursor_own.list_own.lemma_relate_region_at_index(regions_pre_drop, i);
1649 cursor_own.list_own.lemma_relate_region_at_facts(regions_pre_drop, i);
1650 };
1651 cursor_own.list_own.lemma_relate_region_preserved_external_change(
1652 regions_pre_drop,
1653 *regions,
1654 );
1655
1656 assert forall|j: int|
1657 #![trigger cursor_own.list_own.list[j]]
1658 0 <= j < n - k - 1 implies cursor_own.list_own.list[j] == original_list[j
1659 + k + 1] by {};
1660
1661 k = k + 1;
1662 }
1663 } else {
1664 break;
1665 }
1666 }
1667
1668 proof {
1671 let tracked mut final_list_own = cursor_own.list_own;
1672 vstd::modes::tracked_swap(&mut s.0, &mut final_list_own);
1673 final_list_own.tracked_destroy_empty();
1674 }
1675 }
1676}
1677
1678pub struct Link<M: AnyFrameMeta + Repr<MetaSlotSmall>> {
1687 pub next: Option<ReprPtr<MetaSlotStorage, Link<M>>>,
1688 pub prev: Option<ReprPtr<MetaSlotStorage, Link<M>>>,
1689 pub meta: M,
1690}
1691
1692impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Deref for Link<M> {
1693 type Target = M;
1694
1695 fn deref(&self) -> &Self::Target {
1696 &self.meta
1697 }
1698}
1699
1700impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> DerefMut for Link<M> {
1701 fn deref_mut(&mut self) -> &mut Self::Target {
1702 &mut self.meta
1703 }
1704}
1705
1706impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Link<M> {
1707 pub const fn new(meta: M) -> Self {
1709 Self { next: None, prev: None, meta }
1710 }
1711}
1712
1713unsafe impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> AnyFrameMeta for Link<M> {
1716 open spec fn on_drop_pre(
1717 &self,
1718 reader: crate::mm::VmReader<'_, crate::mm::Infallible>,
1719 regions: crate::specs::mm::frame::meta_region_owners::MetaRegionOwners,
1720 vm_io_owner: crate::specs::mm::io::VmIoOwner,
1721 ) -> bool {
1722 self.meta.on_drop_pre(reader, regions, vm_io_owner)
1723 }
1724
1725 fn on_drop(
1726 &mut self,
1727 reader: &mut crate::mm::VmReader<crate::mm::Infallible>,
1728 regions: Tracked<&mut crate::specs::mm::frame::meta_region_owners::MetaRegionOwners>,
1729 vm_io_owner: Tracked<&mut crate::specs::mm::io::VmIoOwner>,
1730 ) {
1731 self.meta.on_drop(reader, regions, vm_io_owner);
1732 }
1733
1734 fn is_untyped(&self) -> bool {
1735 self.meta.is_untyped()
1736 }
1737
1738 uninterp spec fn vtable_ptr(&self) -> usize;
1739}
1740
1741}