1use vstd::prelude::*;
7
8use vstd::seq_lib::*;
9use vstd::simple_pptr::*;
10
11use vstd_extra::cast_ptr::*;
12use vstd_extra::drop_tracking::{Drop, DropObligation, TrackDrop};
13use vstd_extra::ownership::*;
14use vstd_extra::trans_macros::*;
15
16use crate::mm::frame::meta::{
17 META_SLOT_SIZE, REF_COUNT_UNIQUE,
18 mapping::{frame_to_meta, meta_to_frame},
19};
20use crate::mm::kspace::FRAME_METADATA_RANGE;
21use crate::specs::arch::*;
22use crate::specs::mm::frame::{
23 linked_list::linked_list_owners::*,
24 mapping::{frame_to_index, group_page_meta, max_meta_slots, meta_addr},
25 meta_owners::{MetaSlotOwner, Metadata},
26 meta_region_owners::MetaRegionOwners,
27 unique::UniqueFrameOwner,
28};
29
30use super::{
31 MetaSlot, mapping,
32 meta::{AnyFrameMeta, get_slot},
33 unique::UniqueFrame,
34};
35use crate::{
36 arch::mm::PagingConsts,
37 mm::{Paddr, Vaddr},
38 };
40use core::{
41 ops::{Deref, DerefMut},
42 ptr::NonNull,
43 sync::atomic::{AtomicU64, Ordering},
44};
45
46verus! {
47
48pub struct LinkedList<M: AnyFrameMeta + Repr<MetaSlotSmall>> {
122 pub front: Option<ReprPtr<MetaSlot, MetadataAsLink<M>>>,
123 pub back: Option<ReprPtr<MetaSlot, MetadataAsLink<M>>>,
124 pub size: usize,
126 pub list_id: u64,
129}
130
131pub struct CursorMut<'a, M: AnyFrameMeta + Repr<MetaSlotSmall>> {
136 pub list: &'a mut LinkedList<M>,
137 pub current: Option<ReprPtr<MetaSlot, MetadataAsLink<M>>>,
138}
139
140impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> LinkedList<M> {
141 pub const fn new() -> Self {
143 Self { front: None, back: None, size: 0, list_id: 0 }
144 }
145}
146
147impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Default for LinkedList<M> {
148 fn default() -> Self {
149 Self::new()
150 }
151}
152
153#[verus_verify]
154impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> LinkedList<M> {
155 #[verus_spec(s =>
157 with
158 Tracked(owner): Tracked<LinkedListOwner<M>>,
159 requires
160 self.wf(owner),
161 owner.inv(),
162 ensures
163 s == owner@.list.len(),
164 )]
165 pub fn size(&self) -> usize {
166 proof {
167 LinkedListOwner::<M>::view_preserves_len(owner.list);
168 }
169 self.size
170 }
171
172 #[verus_spec(b =>
174 with
175 Tracked(owner): Tracked<LinkedListOwner<M>>,
176 requires
177 self.wf(owner),
178 owner.inv(),
179 ensures
180 b ==> self.size == 0 && self.front is None && self.back is None,
181 !b ==> self.size > 0 && self.front is Some && self.back is Some,
182 )]
183 pub fn is_empty(&self) -> bool {
184 let is_empty = self.size == 0;
185 is_empty
186 }
187
188 #[verus_spec(
200 with
201 Tracked(regions): Tracked<&mut MetaRegionOwners>,
202 Tracked(owner): Tracked<&mut LinkedListOwner<M>>,
203 Tracked(frame_own): Tracked<&mut UniqueFrameOwner<Link<M>>>,
204 requires
205 old(self).wf_region(*old(owner), *old(regions)),
206 old(owner).relate_region(*old(regions)),
207 old(frame_own).inv(),
208 old(frame_own).global_inv(*old(regions)),
209 frame.wf(*old(frame_own)),
210 old(frame_own).frame_link_inv(*old(regions)),
211 old(regions).inv(),
212 ensures
213 final(owner).relate_region(*final(regions)),
214 final(regions).inv(),
215 final(owner).list == old(owner).list.insert(0, final(frame_own).meta_own),
216 old(owner).list_id != 0 ==> final(owner).list_id == old(owner).list_id,
217 final(owner).list_id != 0,
218 final(frame_own).meta_own.paddr == old(frame_own).meta_own.paddr,
219 final(frame_own).meta_own.in_list == final(owner).list_id,
220 )]
221 pub fn push_front(&mut self, frame: UniqueFrame<Link<M>>) {
222 let current = self.front;
223 let tracked mut cursor_own = CursorOwner::tracked_front_owner(*owner);
224 let mut cursor = CursorMut { list: self, current };
225
226 #[verus_spec(with Tracked(regions), Tracked(&mut cursor_own), Tracked(frame_own))]
227 cursor.insert_before(frame);
228
229 proof {
230 *owner = cursor_own.list_own;
231 }
232 }
233
234 #[verus_spec(r =>
246 with
247 Tracked(regions): Tracked<&mut MetaRegionOwners>,
248 Tracked(owner): Tracked<LinkedListOwner<M>>,
249 Tracked(frame_own): Tracked<UniqueFrameOwner<Link<M>>>,
250 requires
251 old(regions).inv(),
252 old(self).wf_region(owner, *old(regions)),
253 owner.relate_region(*old(regions)),
254 ensures
255 owner.list.len() == 0 ==> r.is_none(),
256 r.is_some() ==> (r->0).1@@.meta == owner.list[0]@,
257 r.is_some() ==> (r->0).1@.frame_link_inv(*final(regions)),
258 )]
259 pub fn pop_front(&mut self) -> Option<
260 (UniqueFrame<Link<M>>, Tracked<UniqueFrameOwner<Link<M>>>),
261 > {
262 let tracked mut cursor_own = CursorOwner::tracked_front_owner(owner);
263 let current = self.front;
264 let mut cursor = CursorMut { list: self, current };
265
266 proof {
267 if owner.list.len() > 0 {
268 owner.relate_region_at_facts(*regions, 0);
269 }
270 }
271
272 #[verus_spec(with Tracked(regions), Tracked(&mut cursor_own))]
273 cursor.take_current()
274 }
275
276 #[verus_spec(
288 with
289 Tracked(regions): Tracked<&mut MetaRegionOwners>,
290 Tracked(owner): Tracked<&mut LinkedListOwner<M>>,
291 Tracked(frame_own): Tracked<&mut UniqueFrameOwner<Link<M>>>,
292 requires
293 old(self).wf_region(*old(owner), *old(regions)),
294 old(owner).relate_region(*old(regions)),
295 old(frame_own).inv(),
296 old(frame_own).global_inv(*old(regions)),
297 frame.wf(*old(frame_own)),
298 old(frame_own).frame_link_inv(*old(regions)),
299 old(regions).inv(),
300 ensures
301 final(owner).relate_region(*final(regions)),
302 final(regions).inv(),
303 old(owner).list.len() > 0 ==> final(owner).list == old(owner).list.insert(
304 old(owner).list.len() - 1, final(frame_own).meta_own),
305 old(owner).list.len() == 0 ==> final(owner).list == old(owner).list.insert(
306 0, final(frame_own).meta_own),
307 old(owner).list_id != 0 ==> final(owner).list_id == old(owner).list_id,
310 final(owner).list_id != 0,
311 final(frame_own).meta_own.paddr == old(frame_own).meta_own.paddr,
312 final(frame_own).meta_own.in_list == final(owner).list_id,
313 )]
314 pub fn push_back(&mut self, frame: UniqueFrame<Link<M>>) {
315 let current = self.back;
316 let tracked mut cursor_own = CursorOwner::tracked_back_owner(*owner);
317 let mut cursor = CursorMut { list: self, current };
318
319 #[verus_spec(with Tracked(regions), Tracked(&mut cursor_own), Tracked(frame_own))]
320 cursor.insert_before(frame);
321
322 proof {
323 *owner = cursor_own.list_own;
324 }
325 }
326
327 #[verus_spec(r =>
340 with
341 Tracked(regions): Tracked<&mut MetaRegionOwners>,
342 Tracked(owner): Tracked<LinkedListOwner<M>>,
343 Tracked(frame_own): Tracked<UniqueFrameOwner<Link<M>>>,
344 requires
345 old(regions).inv(),
346 old(self).wf_region(owner, *old(regions)),
347 owner.relate_region(*old(regions)),
348 ensures
349 owner.list.len() == 0 ==> r.is_none(),
350 r.is_some() ==> (r->0).1@@.meta == owner.list[owner.list.len() - 1]@,
351 r.is_some() ==> (r->0).1@.frame_link_inv(*final(regions)),
352 )]
353 pub fn pop_back(&mut self) -> Option<
354 (UniqueFrame<Link<M>>, Tracked<UniqueFrameOwner<Link<M>>>),
355 > {
356 let current = self.back;
357 let tracked mut cursor_own = CursorOwner::tracked_back_owner(owner);
358 let mut cursor = CursorMut { list: self, current };
359
360 proof {
361 if owner.list.len() > 0 {
362 owner.relate_region_at_facts(*regions, owner.list.len() - 1);
363 }
364 }
365
366 #[verus_spec(with Tracked(regions), Tracked(&mut cursor_own))]
367 cursor.take_current()
368 }
369
370 #[verus_spec(r =>
384 with
385 Tracked(regions): Tracked<&mut MetaRegionOwners>,
386 Tracked(slot_own): Tracked<&MetaSlotOwner>,
387 Tracked(owner): Tracked<&mut LinkedListOwner<M>>,
388 requires
389 slot_own.inv(),
390 old(regions).inv(),
391 ensures
392 old(owner).list_id != 0 ==> *final(owner) == *old(owner),
393 )]
394 pub fn contains(&mut self, frame: Paddr) -> bool {
395 let Ok(slot_ptr) = get_slot(frame) else {
396 return false;
397 };
398
399 proof {
400 broadcast use group_page_meta;
405
406 let idx = frame_to_index(frame);
407 assert(regions.slot_owners.contains_key(idx));
408 assert(regions.slots.contains_key(idx));
409 assert(regions.slots[idx].is_init());
410 assert(regions.slot_owners[idx].inner_perms.in_list.is_for(
411 regions.slots[idx].value().in_list,
412 ));
413 }
414
415 let tracked mut slot_perm = regions.slots.tracked_remove(frame_to_index(frame));
416 let tracked mut slot_own = regions.slot_owners.tracked_remove(frame_to_index(frame));
417
418 let slot = slot_ptr.take(Tracked(&mut slot_perm));
419
420 let tracked mut inner_perms = slot_own.tracked_borrow_mut_inner_perms();
421
422 let in_list = slot.in_list.load(Tracked(&mut inner_perms.in_list));
423 slot_ptr.put(Tracked(&mut slot_perm), slot);
424
425 proof {
426 regions.slot_owners.tracked_insert(frame_to_index(frame), slot_own);
427 regions.slots.tracked_insert(frame_to_index(frame), slot_perm);
428 }
429
430 in_list == #[verus_spec(with Tracked(owner))]
431 self.lazy_get_id()
432 }
433
434 #[verus_spec(r =>
452 with
453 Tracked(regions): Tracked<&mut MetaRegionOwners>,
454 Tracked(owner): Tracked<LinkedListOwner<M>>,
455 -> cursor_owner: Tracked<Option<CursorOwner<M>>>,
456 requires
457 old(regions).inv(),
458 ensures
459 !has_safe_slot(frame) ==> r is None,
460 final(regions).inv(),
461 final(regions).slots == old(regions).slots,
462 final(regions).slot_owners.dom() == old(regions).slot_owners.dom(),
463 )]
464 pub fn cursor_mut_at(&mut self, frame: Paddr) -> Option<CursorMut<'_, M>> {
465 if let Ok(slot_ptr) = get_slot(frame) {
466 let ghost idx = frame_to_index(frame);
467 proof {
468 broadcast use group_page_meta;
469
470 assert(regions.slot_owners.contains_key(idx));
471 assert(regions.slots.contains_key(idx));
472 }
473 let tracked slot_perm = regions.slots.tracked_borrow(idx);
474 let tracked mut slot_own = regions.slot_owners.tracked_remove(idx);
475 let tracked mut inner_perms = slot_own.tracked_borrow_mut_inner_perms();
476
477 let slot = slot_ptr.borrow(Tracked(slot_perm));
478
479 let in_list = slot.in_list.load(Tracked(&mut inner_perms.in_list));
480
481 let contains = in_list == #[verus_spec(with Tracked(&owner))]
482 self.lazy_get_id();
483
484 #[verus_spec(with Tracked(slot_perm))]
485 let meta_ptr = slot.as_meta_ptr::<Link<M>>();
486
487 proof {
488 regions.slot_owners.tracked_insert(idx, slot_own);
489 }
490
491 if contains {
492 let ghost link = owner.list.filter(|link: LinkOwner| link.paddr == frame).first();
493 let ghost index = owner.list.index_of(link);
494 let tracked cursor_owner = CursorOwner::tracked_cursor_mut_at_owner(owner, index);
495
496 proof_with!(|= Tracked(Some(cursor_owner)));
497 Some(
498 CursorMut {
499 list: self,
500 current: Some(MetadataAsLink::cast_from_metadata(meta_ptr)),
501 },
502 )
503 } else {
504 proof_with!(|= Tracked(None));
505 None
506 }
507 } else {
508 assert(!has_safe_slot(frame));
509 proof_with!(|= Tracked(None));
510 None
511 }
512 }
513
514 #[verus_spec(r =>
529 with
530 Tracked(owner): Tracked<LinkedListOwner<M>>,
531 requires
532 old(self).wf(owner),
533 owner.inv(),
534 ensures
535 r.0.wf(r.1@),
536 r.1@.inv(),
537 r.1@ == CursorOwner::front_owner(owner),
538 )]
539 pub fn cursor_front_mut(&mut self) -> (CursorMut<'_, M>, Tracked<CursorOwner<M>>) {
540 let current = self.front;
541
542 (CursorMut { list: self, current }, Tracked(CursorOwner::tracked_front_owner(owner)))
543 }
544
545 #[verus_spec(
560 with
561 Tracked(owner): Tracked<LinkedListOwner<M>>,
562 )]
563 pub fn cursor_back_mut(&mut self) -> (res: (CursorMut<'_, M>, Tracked<CursorOwner<M>>))
564 requires
565 old(self).wf(owner),
566 owner.inv(),
567 ensures
568 res.0.wf(res.1@),
569 res.1@.inv(),
570 res.1@ == CursorOwner::back_owner(owner),
571 {
572 let current = self.back;
573
574 (CursorMut { list: self, current }, Tracked(CursorOwner::tracked_back_owner(owner)))
575 }
576
577 #[verus_spec(
579 with Tracked(owner): Tracked<&mut LinkedListOwner<M>>
580 )]
581 fn cursor_at_ghost_mut(&mut self) -> CursorMut<'_, M> {
582 CursorMut { list: self, current: None }
583 }
584
585 #[verifier::external_body]
589 #[verus_spec(
590 with Tracked(owner): Tracked<& LinkedListOwner<M>>
591 )]
592 fn lazy_get_id(&mut self) -> (id: u64)
593 ensures
594 owner.list_id != 0 ==> id == owner.list_id,
595 final(self).size == old(self).size,
596 final(self).front == old(self).front,
597 final(self).back == old(self).back,
598 old(self).list_id != 0 ==> final(self).list_id == old(self).list_id,
599 id != 0,
600 final(self).list_id == id,
601 {
602 unimplemented!()}
621}
622
623impl<'a, M: AnyFrameMeta + Repr<MetaSlotSmall>> CursorMut<'a, M> {
624 #[verus_spec(
631 with Tracked(owner): Tracked<CursorOwner<M>>,
632 Tracked(regions): Tracked<&MetaRegionOwners>,
633 )]
634 pub fn move_next(&mut self)
635 requires
636 owner.wf_with_region(*regions),
637 old(self).wf_region(owner, *regions),
638 ensures
639 owner.move_next_owner_spec()@ == owner@.move_next_spec(),
640 owner.move_next_owner_spec().wf_with_region(*regions),
641 final(self).wf_region(owner.move_next_owner_spec(), *regions),
642 {
643 let ghost old_self = *self;
644
645 proof {
646 if self.current is Some {
647 owner.list_own.relate_region_at_facts(*regions, owner.index);
648 }
649 if owner.index < owner.length() - 1 {
650 owner.list_own.relate_region_at_facts(*regions, owner.index + 1);
651 }
652 }
653
654 self.current = match self.current {
655 Some(current) => {
657 let current_md = MetadataAsLink::cast_to_metadata(current);
658 let ghost idx = frame_to_index(meta_to_frame(current.addr()));
659
660 proof {
661 assert(idx == owner.list_own.slot_index_at(owner.index));
662 assert(regions.slots.contains_key(idx));
663 assert(regions.slot_owners.contains_key(idx));
664 }
665
666 let tracked meta_perm = regions.borrow_typed_perm::<Link<M>>(idx);
667
668 borrow_field!(current_md => next, Meta(meta_perm))
669 },
670 None => self.list.front,
671 };
672
673 proof {
674 LinkedListOwner::<M>::view_preserves_len(owner.list_own.list);
675 assert(owner.move_next_owner_spec()@.fore == owner@.move_next_spec().fore);
676 assert(owner.move_next_owner_spec()@.rear == owner@.move_next_spec().rear);
677 }
678 }
679
680 #[verus_spec(
687 with Tracked(owner): Tracked<CursorOwner<M>>,
688 Tracked(regions): Tracked<&MetaRegionOwners>,
689 )]
690 pub fn move_prev(&mut self)
691 requires
692 owner.wf_with_region(*regions),
693 old(self).wf_region(owner, *regions),
694 ensures
695 owner.move_prev_owner_spec()@ == owner@.move_prev_spec(),
696 owner.move_prev_owner_spec().wf_with_region(*regions),
697 final(self).wf_region(owner.move_prev_owner_spec(), *regions),
698 {
699 let ghost old_self = *self;
700
701 proof {
702 if self.current is Some {
703 owner.list_own.relate_region_at_facts(*regions, owner.index);
704 }
705 if 0 < owner.index {
706 owner.list_own.relate_region_at_facts(*regions, owner.index - 1);
707 }
708 }
709
710 self.current = match self.current {
711 Some(current) => {
713 let current_md = MetadataAsLink::cast_to_metadata(current);
714 let ghost idx = frame_to_index(meta_to_frame(current.addr()));
715
716 proof {
717 assert(idx == owner.list_own.slot_index_at(owner.index));
718 assert(regions.slots.contains_key(idx));
719 assert(regions.slot_owners.contains_key(idx));
720 }
721
722 let tracked meta_perm = regions.borrow_typed_perm::<Link<M>>(idx);
723
724 borrow_field!(current_md => prev, Meta(meta_perm))
725 },
726 None => self.list.back,
727 };
728
729 proof {
730 LinkedListOwner::<M>::view_preserves_len(owner.list_own.list);
731
732 if owner@.list_model.list.len() > 0 {
733 if owner@.fore.len() > 0 {
734 assert(owner.move_prev_owner_spec()@.fore == owner@.move_prev_spec().fore);
735 assert(owner.move_prev_owner_spec()@.rear == owner@.move_prev_spec().rear);
736 if owner@.rear.len() > 0 {
737 owner.list_own.relate_region_at_facts(*regions, owner.index);
738 }
739 } else {
740 owner.list_own.relate_region_at_facts(*regions, owner.index);
741 assert(owner.move_prev_owner_spec()@.rear == owner@.move_prev_spec().rear);
742 assert(owner@.rear == owner@.list_model.list);
743 }
744 }
745 }
746 }
747
748 #[verus_spec(
762 with Tracked(owner): Tracked<&'b mut CursorOwner<M>>,
763 Tracked(regions): Tracked<&'b mut MetaRegionOwners>,
764 )]
765 pub fn current_meta<'b>(&'b mut self) -> (res: Option<&'b mut M>)
766 requires
767 old(self).wf_region(*old(owner), *old(regions)),
768 old(owner).wf_with_region(*old(regions)),
769 old(regions).inv(),
770 ensures
771 final(owner).index == old(owner).index,
772 final(owner).list_own.list == old(owner).list_own.list,
773 final(owner).list_own.list_id == old(owner).list_own.list_id,
774 *final(self) == *old(self),
775 res.is_some() == (0 <= final(owner).index < final(owner).length()),
776 final(regions).slots.dom() == old(regions).slots.dom(),
777 final(regions).slot_owners.dom() == old(regions).slot_owners.dom(),
778 {
779 match self.current {
785 Some(current) => {
786 proof {
787 owner.list_own.relate_region_at_facts(*regions, owner.index);
788 }
789 let current_md = MetadataAsLink::cast_to_metadata(current);
790 let ghost idx = frame_to_index(meta_to_frame(current.addr()));
791 proof {
792 assert(idx == owner.list_own.slot_index_at(owner.index));
793 assert(regions.slots.contains_key(idx));
794 assert(regions.slot_owners.contains_key(idx));
795 }
796 let tracked current_perm = regions.borrow_mut_typed_perm::<Link<M>>(idx);
797 let link_md = current_md.borrow_mut(Tracked(current_perm));
798 let meta = &mut link_md.metadata.meta;
799 Some(meta)
800 },
801 None => None,
802 }
803 }
804
805 #[verus_spec(
823 with Tracked(regions) : Tracked<&mut MetaRegionOwners>,
824 Tracked(owner) : Tracked<&mut CursorOwner<M>>
825 )]
826 #[verifier::spinoff_prover]
827 pub fn take_current(&mut self) -> (res: Option<
828 (UniqueFrame<Link<M>>, Tracked<UniqueFrameOwner<Link<M>>>),
829 >)
830 requires
831 old(self).wf_region(*old(owner), *old(regions)),
832 old(owner).wf_with_region(*old(regions)),
833 old(regions).inv(),
834 ensures
835 old(owner).length() == 0 ==> res.is_none(),
836 old(self).current.is_some() ==> res.is_some(),
837 res.is_some() ==> (res->0).1@@.meta == old(owner).list_own.list[old(owner).index]@,
838 res.is_some() ==> final(owner)@ == old(owner)@.remove(),
839 res.is_some() ==> (res->0).1@.frame_link_inv(*final(regions)),
840 res.is_some() ==> final(owner).wf_with_region(*final(regions)),
842 res.is_some() ==> final(self).wf_region(*final(owner), *final(regions)),
843 res.is_none() ==> *final(owner) == *old(owner),
844 final(regions).inv(),
845 res.is_some() ==> final(owner).index == old(owner).index,
847 res.is_some() ==> final(owner).list_own.list == old(owner).list_own.list.remove(
848 old(owner).index,
849 ),
850 final(owner).list_own.list_id == old(owner).list_own.list_id,
851 res.is_some() ==> {
852 let paddr = old(self).current->0.addr();
853 let idx = frame_to_index(meta_to_frame(paddr));
854 &&& final(regions).slots.dom() == old(regions).slots.dom()
855 &&& final(regions).slot_owners[idx].inner_perms.ref_count.value()
856 == REF_COUNT_UNIQUE
857 &&& final(regions).slot_owners[idx].inner_perms.in_list.value() == 0
858 &&& final(regions).slot_owners[idx].inner_perms.storage.is_init()
859 &&& final(regions).slot_owners[idx].inner_perms.vtable_ptr.is_init()
860 &&& final(regions).slot_owners[idx].slot_vaddr == meta_addr(idx)
861 &&& final(regions).slot_owners[idx].paths_in_pt == old(
862 regions,
863 ).slot_owners[idx].paths_in_pt
864 },
865 res.is_some() ==> forall|j: usize|
866 #![trigger final(regions).slot_owners[j]]
867 j != frame_to_index(meta_to_frame(old(self).current->0.addr())) ==> {
868 &&& final(regions).slot_owners[j].usage == old(regions).slot_owners[j].usage
869 &&& final(regions).slot_owners[j].slot_vaddr == old(
870 regions,
871 ).slot_owners[j].slot_vaddr
872 &&& final(regions).slot_owners[j].paths_in_pt == old(
873 regions,
874 ).slot_owners[j].paths_in_pt
875 },
876 res.is_none() ==> *final(regions) == *old(regions),
877 res.is_some() ==> (res->0).0.wf((res->0).1@),
879 res.is_some() ==> (res->0).1@.inv(),
880 res.is_some() ==> (res->0).1@.slot_index == frame_to_index(
881 meta_to_frame(old(self).current->0.addr()),
882 ),
883 res.is_some() ==> (res->0).0.ptr.addr() == old(self).current->0.addr(),
884 res.is_some() ==> final(regions).frame_obligations == old(
885 regions,
886 ).frame_obligations.insert(frame_to_index(meta_to_frame(old(self).current->0.addr()))),
887 {
888 let ghost owner0 = *owner;
889 let ghost regions0 = *regions;
890
891 let current = self.current?;
892 let current_md = MetadataAsLink::cast_to_metadata(current);
893
894 proof {
895 owner.list_own.relate_region_at_facts(*regions, owner.index);
896 if owner.index > 0 {
897 owner.list_own.relate_region_at_facts(*regions, owner.index - 1);
898 }
899 if owner.index < owner.list_own.list.len() - 1 {
900 owner.list_own.relate_region_at_facts(*regions, owner.index + 1);
901 }
902 }
903
904 let meta_ptr = current.addr();
905 let paddr = meta_to_frame(meta_ptr);
906 let ghost idx = frame_to_index(paddr);
907
908 assert(current.addr() == owner.list_own.list[owner.index].paddr);
909 assert(idx == owner.list_own.slot_index_at(owner.index));
910
911 let tracked mut cur_own = owner.list_own.list.tracked_remove(owner.index);
912
913 let (frame, frame_own) = unsafe {
914 #[verus_spec(with Tracked(regions), Tracked(cur_own))]
915 UniqueFrame::<Link<M>>::from_raw(paddr)
916 };
917 let frame = frame;
918 let tracked frame_own = frame_own.get();
919
920 proof {
921 assert(regions.slots.dom() == regions0.slots.dom());
922 assert forall|j: usize| #![trigger regions0.slot_owners[j]] j != idx implies {
923 &&& regions.slot_owners[j].usage == regions0.slot_owners[j].usage
924 &&& regions.slot_owners[j].slot_vaddr == regions0.slot_owners[j].slot_vaddr
925 &&& regions.slot_owners[j].paths_in_pt == regions0.slot_owners[j].paths_in_pt
926 } by {}
927 }
928
929 let tracked tp = regions.borrow_typed_perm::<Link<M>>(idx);
930 proof {
931 assert(*tp == owner0.list_own.meta_perm_of(regions0, owner0.index));
932 }
933 let next_ptr = borrow_field!(current_md => next, Meta(tp));
934 let prev_ptr = borrow_field!(current_md => prev, Meta(tp));
935
936 if let Some(prev_link) = prev_ptr {
937 let prev = MetadataAsLink::cast_to_metadata(prev_link);
938 proof {
939 assert(prev.addr() == owner0.list_own.list[owner0.index - 1].paddr);
940 assert(frame_to_index(meta_to_frame(prev.addr())) == owner0.list_own.slot_index_at(
941 owner0.index - 1,
942 ));
943 assert(frame_to_index(meta_to_frame(prev.addr())) != idx); assert(regions.slots[frame_to_index(meta_to_frame(prev.addr()))].pptr()
945 == prev.ptr);
946 }
947
948 let tracked prev_perm = regions.borrow_mut_typed_perm::<Link<M>>(
949 frame_to_index(meta_to_frame(prev.addr())),
950 );
951 update_field!(prev => next <- next_ptr, Meta(prev_perm));
952
953 proof {
954 assert(regions.inv());
955 assert(regions.slots.dom() == regions0.slots.dom());
956 assert forall|j: usize| #![trigger regions0.slot_owners[j]] j != idx implies {
957 &&& regions.slot_owners[j].usage == regions0.slot_owners[j].usage
958 &&& regions.slot_owners[j].slot_vaddr == regions0.slot_owners[j].slot_vaddr
959 &&& regions.slot_owners[j].paths_in_pt == regions0.slot_owners[j].paths_in_pt
960 } by {
961 if j == frame_to_index(meta_to_frame(prev.addr())) {
962 }
963 }
964 }
965
966 } else {
967 self.list.front = next_ptr;
968 proof {
969 assert(regions.slots.dom() == regions0.slots.dom());
970 assert forall|j: usize| #![trigger regions0.slot_owners[j]] j != idx implies {
971 &&& regions.slot_owners[j].usage == regions0.slot_owners[j].usage
972 &&& regions.slot_owners[j].slot_vaddr == regions0.slot_owners[j].slot_vaddr
973 &&& regions.slot_owners[j].paths_in_pt == regions0.slot_owners[j].paths_in_pt
974 } by {}
975 }
976 }
977
978 if let Some(next_link) = next_ptr {
979 let next = MetadataAsLink::cast_to_metadata(next_link);
980 proof {
981 assert(next.addr() == owner0.list_own.list[owner0.index + 1].paddr);
982 assert(frame_to_index(meta_to_frame(next.addr())) == owner0.list_own.slot_index_at(
983 owner0.index + 1,
984 ));
985 assert(frame_to_index(meta_to_frame(next.addr())) != idx); assert(regions.slots[frame_to_index(meta_to_frame(next.addr()))].pptr()
987 == next.ptr);
988 }
989
990 let tracked next_perm = regions.borrow_mut_typed_perm::<Link<M>>(
991 frame_to_index(meta_to_frame(next.addr())),
992 );
993 update_field!(next => prev <- prev_ptr, Meta(next_perm));
994
995 proof {
996 assert(regions.inv());
997 assert(regions.slots.dom() == regions0.slots.dom());
998 assert forall|j: usize| #![trigger regions0.slot_owners[j]] j != idx implies {
999 &&& regions.slot_owners[j].usage == regions0.slot_owners[j].usage
1000 &&& regions.slot_owners[j].slot_vaddr == regions0.slot_owners[j].slot_vaddr
1001 &&& regions.slot_owners[j].paths_in_pt == regions0.slot_owners[j].paths_in_pt
1002 } by {
1003 if j == frame_to_index(meta_to_frame(next.addr())) {
1004 }
1005 }
1006 }
1007
1008 self.current = Some(next_link);
1009 } else {
1010 self.list.back = prev_ptr;
1011
1012 self.current = None;
1013 proof {
1014 assert(regions.slots.dom() == regions0.slots.dom());
1015 assert forall|j: usize| #![trigger regions0.slot_owners[j]] j != idx implies {
1016 &&& regions.slot_owners[j].usage == regions0.slot_owners[j].usage
1017 &&& regions.slot_owners[j].slot_vaddr == regions0.slot_owners[j].slot_vaddr
1018 &&& regions.slot_owners[j].paths_in_pt == regions0.slot_owners[j].paths_in_pt
1019 } by {}
1020 }
1021 }
1022
1023 let tracked frame_perm = regions.borrow_mut_typed_perm::<Link<M>>(idx);
1024 update_field!(current_md => next <- None, Meta(frame_perm));
1025
1026 let tracked frame_perm = regions.borrow_mut_typed_perm::<Link<M>>(idx);
1027 update_field!(current_md => prev <- None, Meta(frame_perm));
1028
1029 let tracked frame_outer = regions.slots.tracked_remove(idx);
1030 let tracked mut frame_so = regions.slot_owners.tracked_remove(idx);
1031 let tracked mut fip = frame_so.tracked_borrow_mut_inner_perms();
1032 #[verus_spec(with Tracked(&frame_outer))]
1033 let slot = frame.slot();
1034 slot.in_list.store(Tracked(&mut fip.in_list), 0);
1035 proof {
1036 regions.slots.tracked_insert(idx, frame_outer);
1037 regions.slot_owners.tracked_insert(idx, frame_so);
1038 assert(regions.inv());
1039 assert(regions.slots.dom() == regions0.slots.dom());
1040 assert(regions.slot_owners[idx].paths_in_pt == regions0.slot_owners[idx].paths_in_pt);
1041 assert forall|j: usize| #![trigger regions0.slot_owners[j]] j != idx implies {
1042 &&& regions.slot_owners[j].usage == regions0.slot_owners[j].usage
1043 &&& regions.slot_owners[j].slot_vaddr == regions0.slot_owners[j].slot_vaddr
1044 &&& regions.slot_owners[j].paths_in_pt == regions0.slot_owners[j].paths_in_pt
1045 } by {}
1046 }
1047
1048 self.list.size = self.list.size - 1;
1049
1050 proof {
1051 owner0.remove_owner_spec_implies_model_spec(*owner);
1052 let ghost oldl = owner0.list_own;
1053 let ghost nn = owner0.index as int;
1054 assert forall|p: int|
1055 #![trigger oldl.slot_index_at(p)]
1056 (0 <= p < oldl.list.len() && p != nn) implies ({
1057 let i = oldl.slot_index_at(p);
1058 let fp = vstd_extra::cast_ptr::PointsTo::<MetaSlot, Metadata<Link<M>>>::new_spec(
1059 regions.slots[i],
1060 regions.slot_owners[i].inner_perms,
1061 );
1062 &&& regions.slots.contains_key(i)
1063 &&& regions.slot_owners.contains_key(i)
1064 &&& fp.addr() == oldl.list[p].paddr
1065 &&& fp.points_to.addr() == oldl.list[p].paddr
1066 &&& fp.points_to.pptr() == regions0.slots[i].pptr()
1067 &&& fp.inner_perms.ref_count.value() == REF_COUNT_UNIQUE
1068 &&& fp.wf(&fp.inner_perms)
1069 &&& fp.addr() % META_SLOT_SIZE == 0
1070 &&& FRAME_METADATA_RANGE.start <= fp.addr() < FRAME_METADATA_RANGE.start
1071 + MAX_NR_PAGES * META_SLOT_SIZE
1072 &&& fp.is_init()
1073 &&& (p == nn - 1 ==> fp.value().metadata.next == oldl.meta_perm_of(
1074 regions0,
1075 nn,
1076 ).value().metadata.next)
1077 &&& (p != nn - 1 ==> fp.value().metadata.next == oldl.meta_perm_of(
1078 regions0,
1079 p,
1080 ).value().metadata.next)
1081 &&& (p == nn + 1 ==> fp.value().metadata.prev == oldl.meta_perm_of(
1082 regions0,
1083 nn,
1084 ).value().metadata.prev)
1085 &&& (p != nn + 1 ==> fp.value().metadata.prev == oldl.meta_perm_of(
1086 regions0,
1087 p,
1088 ).value().metadata.prev)
1089 }) by {
1090 let i = oldl.slot_index_at(p);
1091 oldl.relate_region_at_facts(regions0, p);
1092 oldl.relate_region_at_facts(regions0, nn);
1093 }
1094 LinkedListOwner::pop_preserves_relate_region(
1095 oldl,
1096 regions0,
1097 owner.list_own,
1098 *regions,
1099 nn,
1100 );
1101 }
1102 Some((frame, Tracked(frame_own)))
1103 }
1104
1105 #[verus_spec(
1122 with Tracked(regions): Tracked<&mut MetaRegionOwners>,
1123 Tracked(owner): Tracked<&mut CursorOwner<M>>,
1124 Tracked(frame_own): Tracked<&mut UniqueFrameOwner<Link<M>>>
1125 )]
1126 #[verifier::spinoff_prover]
1127 pub fn insert_before(&mut self, mut frame: UniqueFrame<Link<M>>)
1128 requires
1129 old(self).wf_region(*old(owner), *old(regions)),
1130 old(owner).wf_with_region(*old(regions)),
1131 old(regions).inv(),
1132 old(frame_own).inv(),
1133 old(frame_own).global_inv(*old(regions)),
1134 frame.wf(*old(frame_own)),
1135 old(frame_own).frame_link_inv(*old(regions)),
1136 ensures
1137 final(owner).wf_with_region(*final(regions)),
1138 final(self).wf_region(*final(owner), *final(regions)),
1139 final(regions).inv(),
1140 final(owner).list_own.list == old(owner).list_own.list.insert(
1141 old(owner).index,
1142 final(frame_own).meta_own,
1143 ),
1144 old(owner).list_own.list_id != 0 ==> final(owner).list_own.list_id == old(
1147 owner,
1148 ).list_own.list_id,
1149 final(owner).list_own.list_id != 0,
1150 final(owner).index == old(owner).index + 1,
1151 final(frame_own).meta_own.paddr == old(frame_own).meta_own.paddr,
1152 final(frame_own).meta_own.in_list == final(owner).list_own.list_id,
1153 final(owner)@ == old(owner)@.insert(final(frame_own).meta_own@),
1154 {
1155 let ghost owner0 = *owner;
1156 let ghost regions0 = *regions;
1157 let ghost nn = owner.index as int;
1158
1159 proof {
1160 owner0.list_own.length_lt_usize_max(regions0);
1161 if nn > 0 {
1162 owner.list_own.relate_region_at_facts(*regions, nn - 1);
1163 }
1164 if nn < owner.list_own.list.len() {
1165 owner.list_own.relate_region_at_facts(*regions, nn);
1166 }
1167 }
1168
1169 let frame_ptr = ReprPtr::<MetaSlot, Metadata<Link<M>>>::from_pptr(frame.ptr);
1170 let frame_ptr_as_link = MetadataAsLink::cast_from_metadata(frame_ptr);
1171
1172 let ghost frame_idx_g: usize = frame_own.slot_index;
1173
1174 if let Some(current) = self.current {
1175 let current_md = MetadataAsLink::cast_to_metadata(current);
1176
1177 let opt_prev_link: Option<ReprPtr<MetaSlot, MetadataAsLink<M>>>;
1179
1180 let tracked tp = regions.borrow_typed_perm::<Link<M>>(
1181 frame_to_index(meta_to_frame(current.addr())),
1182 );
1183 opt_prev_link = borrow_field!(current_md => prev, Meta(tp));
1184
1185 if let Some(prev_link) = opt_prev_link {
1186 let prev = MetadataAsLink::cast_to_metadata(prev_link);
1187
1188 let tracked perm = regions.borrow_mut_typed_perm::<Link<M>>(
1189 frame_to_index(meta_to_frame(prev.addr())),
1190 );
1191 update_field!(prev => next <- Some(frame_ptr_as_link), Meta(perm));
1192
1193 let tracked perm = regions.borrow_mut_typed_perm::<Link<M>>(frame_idx_g);
1194 update_field!(frame_ptr => prev <- Some(prev_link), Meta(perm));
1195
1196 let tracked perm = regions.borrow_mut_typed_perm::<Link<M>>(frame_idx_g);
1197 update_field!(frame_ptr => next <- Some(current), Meta(perm));
1198
1199 let tracked perm = regions.borrow_mut_typed_perm::<Link<M>>(
1200 frame_to_index(meta_to_frame(current.addr())),
1201 );
1202 update_field!(current_md => prev <- Some(frame_ptr_as_link), Meta(perm));
1203
1204 proof {
1205 let fpn_local = vstd_extra::cast_ptr::PointsTo::<
1206 MetaSlot,
1207 Metadata<Link<M>>,
1208 >::new_spec(
1209 regions.slots[frame_idx_g],
1210 regions.slot_owners[frame_idx_g].inner_perms,
1211 );
1212 assert(fpn_local.value().metadata.prev.unwrap().addr()
1213 == owner0.list_own.list[nn - 1].paddr);
1214 assert(fpn_local.value().metadata.prev.unwrap().ptr
1215 == regions0.slots[owner0.list_own.slot_index_at(nn - 1)].pptr());
1216 assert(fpn_local.value().metadata.next.unwrap().addr()
1217 == owner0.list_own.list[nn].paddr);
1218 assert(fpn_local.value().metadata.next.unwrap().ptr
1219 == regions0.slots[owner0.list_own.slot_index_at(nn)].pptr());
1220 }
1221 } else {
1222 let tracked perm = regions.borrow_mut_typed_perm::<Link<M>>(frame_idx_g);
1223 update_field!(frame_ptr => next <- Some(current), Meta(perm));
1224
1225 let tracked perm = regions.borrow_mut_typed_perm::<Link<M>>(
1226 frame_to_index(meta_to_frame(current.addr())),
1227 );
1228 update_field!(current_md => prev <- Some(frame_ptr_as_link), Meta(perm));
1229
1230 self.list.front = Some(frame_ptr_as_link);
1231 }
1232 } else {
1233 if let Some(back) = self.list.back {
1234 let back_md = MetadataAsLink::cast_to_metadata(back);
1235
1236 let tracked perm = regions.borrow_mut_typed_perm::<Link<M>>(
1237 frame_to_index(meta_to_frame(back.addr())),
1238 );
1239 update_field!(back_md => next <- Some(frame_ptr_as_link), Meta(perm));
1240
1241 let tracked perm = regions.borrow_mut_typed_perm::<Link<M>>(frame_idx_g);
1242 update_field!(frame_ptr => prev <- Some(back), Meta(perm));
1243
1244 self.list.back = Some(frame_ptr_as_link);
1245 } else {
1246 self.list.front = Some(frame_ptr_as_link);
1248 self.list.back = Some(frame_ptr_as_link);
1249 }
1250 }
1251
1252 #[verus_spec(with Tracked(&owner.list_own))]
1253 let list_id = self.list.lazy_get_id();
1254
1255 proof {
1256 assert(regions.slots.contains_key(frame_idx_g));
1257 }
1258 let tracked frame_outer = regions.slots.tracked_remove(frame_idx_g);
1259 let tracked mut frame_so = regions.slot_owners.tracked_remove(frame_idx_g);
1260 let tracked mut fip = frame_so.tracked_borrow_mut_inner_perms();
1261 #[verus_spec(with Tracked(&frame_outer))]
1262 let slot = frame.slot();
1263 slot.in_list.store(Tracked(&mut fip.in_list), list_id);
1264 proof {
1265 regions.slots.tracked_insert(frame_idx_g, frame_outer);
1266 regions.slot_owners.tracked_insert(frame_idx_g, frame_so);
1267 assert(regions.inv());
1268 }
1269
1270 #[verus_spec(with Tracked(&*frame_own), Tracked(regions))]
1271 let _ = frame.into_raw();
1272
1273 self.list.size = self.list.size + 1;
1274
1275 proof {
1276 CursorOwner::<M>::tracked_list_insert(owner, &mut frame_own.meta_own, list_id);
1277
1278 let oldl = owner0.list_own;
1279 let nn = owner0.index as int;
1280 let flink = frame_own.meta_own;
1281 let ins = frame_own.slot_index;
1282
1283 assert forall|p: int|
1284 #![trigger oldl.slot_index_at(p)]
1285 (0 <= p < oldl.list.len()) implies ({
1286 let i = oldl.slot_index_at(p);
1287 let fp = vstd_extra::cast_ptr::PointsTo::<MetaSlot, Metadata<Link<M>>>::new_spec(
1288 regions.slots[i],
1289 regions.slot_owners[i].inner_perms,
1290 );
1291 &&& regions.slots.contains_key(i)
1292 &&& regions.slot_owners.contains_key(i)
1293 &&& fp.addr() == oldl.list[p].paddr
1294 &&& fp.points_to.addr() == oldl.list[p].paddr
1295 &&& fp.points_to.pptr() == regions0.slots[i].pptr()
1296 &&& fp.inner_perms.ref_count.value() == REF_COUNT_UNIQUE
1297 &&& fp.wf(&fp.inner_perms)
1298 &&& fp.addr() % META_SLOT_SIZE == 0
1299 &&& FRAME_METADATA_RANGE.start <= fp.addr() < FRAME_METADATA_RANGE.start
1300 + MAX_NR_PAGES * META_SLOT_SIZE
1301 &&& fp.is_init()
1302 &&& (p == nn - 1 ==> {
1303 &&& fp.value().metadata.next is Some
1304 &&& fp.value().metadata.next.unwrap().addr() == flink.paddr
1305 &&& fp.value().metadata.next.unwrap().ptr == regions.slots[ins].pptr()
1306 })
1307 &&& (p != nn - 1 ==> fp.value().metadata.next == oldl.meta_perm_of(
1308 regions0,
1309 p,
1310 ).value().metadata.next)
1311 &&& (p == nn ==> {
1312 &&& fp.value().metadata.prev is Some
1313 &&& fp.value().metadata.prev.unwrap().addr() == flink.paddr
1314 &&& fp.value().metadata.prev.unwrap().ptr == regions.slots[ins].pptr()
1315 })
1316 &&& (p != nn ==> fp.value().metadata.prev == oldl.meta_perm_of(
1317 regions0,
1318 p,
1319 ).value().metadata.prev)
1320 }) by {
1321 let i = oldl.slot_index_at(p);
1322 oldl.relate_region_at_facts(regions0, p);
1323 if nn - 1 >= 0 && nn - 1 < oldl.list.len() {
1324 oldl.relate_region_at_facts(regions0, nn - 1);
1325 }
1326 if nn >= 0 && nn < oldl.list.len() {
1327 oldl.relate_region_at_facts(regions0, nn);
1328 }
1329 }
1330
1331 let fpn = vstd_extra::cast_ptr::PointsTo::<MetaSlot, Metadata<Link<M>>>::new_spec(
1332 regions.slots[ins],
1333 regions.slot_owners[ins].inner_perms,
1334 );
1335 assert(regions.slots.contains_key(ins));
1336 assert(regions.slot_owners.contains_key(ins));
1337
1338 LinkedListOwner::insert_preserves_relate_region(
1339 oldl,
1340 regions0,
1341 owner.list_own,
1342 *regions,
1343 nn,
1344 flink,
1345 );
1346
1347 owner0.insert_owner_spec_implies_model_spec(flink, *owner);
1348 }
1349 }
1350
1351 pub fn as_list(&self) -> &LinkedList<M> {
1353 self.list
1354 }
1355}
1356
1357impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> TrackDrop for LinkedList<M> {
1358 type State = (LinkedListOwner<M>, MetaRegionOwners);
1359
1360 type Key = u64;
1368
1369 open spec fn key(self) -> Self::Key {
1370 self.list_id
1371 }
1372
1373 open spec fn constructor_requires(self, s: Self::State) -> bool {
1374 true
1375 }
1376
1377 open spec fn constructor_ensures(
1378 self,
1379 s0: Self::State,
1380 s1: Self::State,
1381 obl_key: Self::Key,
1382 ) -> bool {
1383 &&& s0 =~= s1
1384 &&& obl_key == self.list_id
1385 }
1386
1387 proof fn constructor_spec(self, tracked s: &mut Self::State) -> (tracked obl: DropObligation<
1388 Self::Key,
1389 >) {
1390 DropObligation::tracked_mint(self.list_id)
1391 }
1392
1393 open spec fn drop_requires(self, s: Self::State) -> bool {
1394 &&& self.wf(s.0)
1395 &&& s.0.inv()
1396 &&& s.1.inv()
1397 &&& forall|i: int|
1398 #![trigger s.0.list[i]]
1399 0 <= i < s.0.list.len() ==> s.1.slot_owners.contains_key(
1400 frame_to_index(meta_to_frame(s.0.list[i].paddr)),
1401 )
1402 &&& forall|i: int|
1403 #![trigger s.0.list[i]]
1404 0 <= i < s.0.list.len() ==> {
1405 let idx = frame_to_index(meta_to_frame(s.0.list[i].paddr));
1406 s.1.slots.contains_key(idx)
1407 }
1408 &&& forall|i: int|
1409 #![trigger s.0.list[i]]
1410 0 <= i < s.0.list.len() ==> {
1411 let idx = frame_to_index(meta_to_frame(s.0.list[i].paddr));
1412 s.1.slot_owners[idx].inner_perms.ref_count.value() == REF_COUNT_UNIQUE
1413 }
1414 &&& forall|i: int|
1415 #![trigger s.0.list[i]]
1416 0 <= i < s.0.list.len() ==> {
1417 let idx = frame_to_index(meta_to_frame(s.0.list[i].paddr));
1418 s.1.frame_obligations.count(idx) == 0
1419 }
1420 &&& forall|i: int|
1421 #![trigger s.0.list[i]]
1422 0 <= i < s.0.list.len() ==> {
1423 let idx = frame_to_index(meta_to_frame(s.0.list[i].paddr));
1424 s.1.slot_owners[idx].paths_in_pt.is_empty()
1425 }
1426 &&& forall|i: int, j: int|
1427 #![trigger s.0.list[i], s.0.list[j]]
1428 0 <= i < j < s.0.list.len() ==> frame_to_index(meta_to_frame(s.0.list[i].paddr))
1429 != frame_to_index(meta_to_frame(s.0.list[j].paddr))
1430 &&& s.0.relate_region(s.1)
1431 }
1432
1433 open spec fn drop_ensures(self, s0: Self::State, s1: Self::State, obl_key: Self::Key) -> bool {
1434 &&& s1.0.list.len() == 0
1435 &&& forall|i: int|
1436 #![trigger s0.0.list[i]]
1437 0 <= i < s0.0.list.len() ==> {
1438 let idx = frame_to_index(meta_to_frame(s0.0.list[i].paddr));
1439 s1.1.frame_obligations.count(idx) == s0.1.frame_obligations.count(idx)
1440 }
1441 &&& forall|idx: usize|
1442 #![trigger s1.1.slot_owners[idx]]
1443 (forall|i: int|
1444 #![trigger s0.0.list[i]]
1445 0 <= i < s0.0.list.len() ==> idx != frame_to_index(
1446 meta_to_frame(s0.0.list[i].paddr),
1447 )) ==> {
1448 &&& s1.1.frame_obligations.count(idx) == s0.1.frame_obligations.count(idx)
1449 &&& s1.1.slot_owners[idx].usage == s0.1.slot_owners[idx].usage
1450 &&& s1.1.slot_owners[idx].slot_vaddr == s0.1.slot_owners[idx].slot_vaddr
1451 &&& s1.1.slot_owners[idx].paths_in_pt == s0.1.slot_owners[idx].paths_in_pt
1452 }
1453 &&& s1.1.slots.dom() =~= s0.1.slots.dom()
1454 &&& s1.1.inv()
1455 }
1456
1457 open spec fn consume_requires(self, s: Self::State, obl_key: Self::Key) -> bool {
1458 obl_key == self.list_id
1461 }
1462
1463 open spec fn consume_ensures(
1464 self,
1465 s0: Self::State,
1466 s1: Self::State,
1467 obl_key: Self::Key,
1468 ) -> bool {
1469 s0 =~= s1
1470 }
1471
1472 proof fn consume_obligation(
1473 self,
1474 tracked s: &mut Self::State,
1475 tracked obl: DropObligation<Self::Key>,
1476 ) {
1477 }
1480}
1481
1482impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Drop for LinkedList<M> {
1483 #[verifier::spinoff_prover]
1484 fn drop(
1485 self,
1486 Tracked(s): Tracked<&mut Self::State>,
1487 Tracked(obl): Tracked<DropObligation<u64>>,
1488 ) {
1489 proof {
1492 self.consume_obligation(s, obl);
1493 }
1494
1495 proof_decl! {
1496 let tracked mut list_own: LinkedListOwner<M>;
1497 }
1498 let ghost original_list = s.0.list;
1499 let ghost original_list_id = s.0.list_id;
1500 let ghost n = original_list.len();
1501 let ghost original_regions = s.1;
1502 proof {
1503 list_own = LinkedListOwner::<M>::tracked_take(&mut s.0);
1504 }
1505 let tracked regions: &mut MetaRegionOwners = &mut s.1;
1506 let mut this = self;
1507
1508 #[verus_spec(with Tracked(list_own))]
1509 let cursor_pair = this.cursor_front_mut();
1510 let (mut cursor, Tracked(mut cursor_own)) = cursor_pair;
1511
1512 proof {
1513 if n > 0 {
1514 cursor_own.list_own.relate_region_at_facts(*regions, 0);
1515 cursor_own.list_own.relate_region_at_facts(*regions, n - 1);
1516 }
1517 }
1518
1519 let ghost mut k: int = 0;
1520
1521 loop
1522 invariant_except_break
1523 cursor.wf_region(cursor_own, *regions),
1524 cursor.current.is_some() <==> k < n,
1525 invariant
1526 cursor_own.wf_with_region(*regions),
1527 cursor_own.list_own.list_id == original_list_id,
1528 cursor_own.index == 0,
1529 regions.inv(),
1530 cursor_own.list_own.list.len() == n - k,
1531 0 <= k <= n,
1532 forall|j: int|
1534 #![trigger cursor_own.list_own.list[j]]
1535 0 <= j < n - k ==> cursor_own.list_own.list[j] == original_list[j + k],
1536 forall|j: int|
1538 #![trigger original_list[j]]
1539 0 <= j < k ==> {
1540 let idx = frame_to_index(meta_to_frame(original_list[j].paddr));
1541 regions.frame_obligations.count(idx) == 0
1542 },
1543 forall|idx: usize|
1545 #![trigger regions.slot_owners[idx]]
1546 (forall|j: int|
1547 #![trigger original_list[j]]
1548 0 <= j < n ==> idx != frame_to_index(meta_to_frame(original_list[j].paddr)))
1549 ==> {
1550 &&& regions.frame_obligations.count(idx)
1551 == original_regions.frame_obligations.count(idx)
1552 &&& regions.slot_owners[idx].usage
1553 == original_regions.slot_owners[idx].usage
1554 &&& regions.slot_owners[idx].slot_vaddr
1555 == original_regions.slot_owners[idx].slot_vaddr
1556 &&& regions.slot_owners[idx].paths_in_pt
1557 == original_regions.slot_owners[idx].paths_in_pt
1558 },
1559 regions.slots.dom() == original_regions.slots.dom(),
1560 forall|j: int|
1562 #![trigger original_list[j]]
1563 k <= j < n ==> {
1564 let idx = frame_to_index(meta_to_frame(original_list[j].paddr));
1565 &&& regions.frame_obligations.count(idx)
1566 == original_regions.frame_obligations.count(idx)
1567 &&& regions.slot_owners[idx].paths_in_pt
1568 == original_regions.slot_owners[idx].paths_in_pt
1569 },
1570 forall|j: int|
1572 #![trigger original_list[j]]
1573 k <= j < n ==> regions.slot_owners.contains_key(
1574 frame_to_index(meta_to_frame(original_list[j].paddr)),
1575 ),
1576 forall|i: int, j: int|
1578 #![trigger original_list[i], original_list[j]]
1579 0 <= i < j < n ==> frame_to_index(meta_to_frame(original_list[i].paddr))
1580 != frame_to_index(meta_to_frame(original_list[j].paddr)),
1581 forall|j: int|
1582 #![trigger original_list[j]]
1583 0 <= j < n ==> {
1584 let idx = frame_to_index(meta_to_frame(original_list[j].paddr));
1585 &&& original_regions.slot_owners.contains_key(idx)
1586 &&& original_regions.slots.contains_key(idx)
1587 &&& original_regions.frame_obligations.count(idx) == 0
1588 &&& original_regions.slot_owners[idx].paths_in_pt.is_empty()
1589 &&& original_regions.slot_owners[idx].inner_perms.ref_count.value()
1590 == REF_COUNT_UNIQUE
1591 },
1592 ensures
1593 k == n,
1594 cursor_own.list_own.list.len() == 0,
1595 decreases n - k,
1596 {
1597 #[verus_spec(with Tracked(regions), Tracked(&mut cursor_own))]
1598 let entry = cursor.take_current();
1599
1600 if let Some(current) = entry {
1601 let (mut frame, frame_own_tracked) = current;
1602 let tracked frame_own = frame_own_tracked.get();
1603 let ghost regions_pre_drop = *regions;
1604
1605 #[verus_spec(with Tracked(frame_own), Tracked(regions))]
1607 frame.drop();
1608
1609 proof {
1610 assert forall|i: int|
1611 #![trigger cursor_own.list_own.list[i]]
1612 0 <= i < cursor_own.list_own.list.len() implies ({
1613 let idx = cursor_own.list_own.slot_index_at(i);
1614 &&& regions.slot_owners.contains_key(idx)
1615 &&& regions.slot_owners[idx] == regions_pre_drop.slot_owners[idx]
1616 &&& regions.frame_obligations.count(idx)
1617 == regions_pre_drop.frame_obligations.count(idx)
1618 }) by {
1619 let idx = cursor_own.list_own.slot_index_at(i);
1620 let ghost _trig_k = original_list[k as int];
1621 let ghost _trig_ik = original_list[i + k + 1];
1622 assert(cursor_own.list_own.list[i] == original_list[i + k + 1]);
1623
1624 cursor_own.list_own.relate_region_at_facts(regions_pre_drop, i);
1625 };
1626 cursor_own.list_own.relate_region_preserved_external_change(
1627 regions_pre_drop,
1628 *regions,
1629 );
1630
1631 assert forall|j: int|
1632 #![trigger cursor_own.list_own.list[j]]
1633 0 <= j < n - k - 1 implies cursor_own.list_own.list[j] == original_list[j
1634 + k + 1] by {};
1635
1636 assert forall|j: int| #![trigger original_list[j]] 0 <= j < k implies ({
1637 let idx = frame_to_index(meta_to_frame(original_list[j].paddr));
1638 regions.frame_obligations.count(idx) == 0
1639 }) by {
1640 let ghost _a = original_list[j as int];
1641 let ghost _b = original_list[k as int];
1642 };
1643
1644 k = k + 1;
1645 }
1646 } else {
1647 break;
1648 }
1649 }
1650
1651 proof {
1654 let tracked mut final_list_own = cursor_own.list_own;
1655 vstd::modes::tracked_swap(&mut s.0, &mut final_list_own);
1656 final_list_own.tracked_destroy_empty();
1657 }
1658 }
1659}
1660
1661pub struct Link<M: AnyFrameMeta + Repr<MetaSlotSmall>> {
1670 pub next: Option<ReprPtr<MetaSlot, MetadataAsLink<M>>>,
1671 pub prev: Option<ReprPtr<MetaSlot, MetadataAsLink<M>>>,
1672 pub meta: M,
1673}
1674
1675impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Deref for Link<M> {
1676 type Target = M;
1677
1678 fn deref(&self) -> &Self::Target {
1679 &self.meta
1680 }
1681}
1682
1683impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> DerefMut for Link<M> {
1684 fn deref_mut(&mut self) -> &mut Self::Target {
1685 &mut self.meta
1686 }
1687}
1688
1689impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Link<M> {
1690 pub const fn new(meta: M) -> Self {
1692 Self { next: None, prev: None, meta }
1693 }
1694}
1695
1696unsafe impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> AnyFrameMeta for Link<M> {
1699 open spec fn on_drop_pre(
1700 &self,
1701 reader: crate::mm::VmReader<'_, crate::mm::Infallible>,
1702 regions: crate::specs::mm::frame::meta_region_owners::MetaRegionOwners,
1703 vm_io_owner: crate::specs::mm::io::VmIoOwner,
1704 ) -> bool {
1705 self.meta.on_drop_pre(reader, regions, vm_io_owner)
1706 }
1707
1708 fn on_drop(
1709 &mut self,
1710 reader: &mut crate::mm::VmReader<crate::mm::Infallible>,
1711 regions: Tracked<&mut crate::specs::mm::frame::meta_region_owners::MetaRegionOwners>,
1712 vm_io_owner: Tracked<&mut crate::specs::mm::io::VmIoOwner>,
1713 ) {
1714 self.meta.on_drop(reader, regions, vm_io_owner);
1715 }
1716
1717 fn is_untyped(&self) -> bool {
1718 self.meta.is_untyped()
1719 }
1720
1721 uninterp spec fn vtable_ptr(&self) -> usize;
1722}
1723
1724}