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::*;
14
15use crate::mm::frame::meta::{
16 META_SLOT_SIZE, REF_COUNT_UNIQUE,
17 mapping::{frame_to_meta, meta_to_frame},
18};
19use crate::mm::kspace::FRAME_METADATA_RANGE;
20use crate::specs::arch::*;
21use crate::specs::mm::frame::{
22 linked_list::linked_list_owners::*,
23 mapping::{frame_to_index, group_page_meta, index_to_meta, meta_to_index},
24 meta_owners::{
25 MetaSlotOwner, MetaSlotStorage, borrow_meta, borrow_meta_mut, typed_meta_value,
26 typed_meta_wf,
27 },
28 meta_region_owners::MetaRegionOwners,
29 unique::UniqueFrameOwner,
30};
31
32use super::{
33 MetaSlot, mapping,
34 meta::{AnyFrameMeta, get_slot},
35 unique::UniqueFrame,
36};
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 assert forall|p: int|
179 #![trigger regions0.slot_owners[meta_to_index(owner0.list[p].paddr)]]
180 0 <= p < owner0.list.len() as int implies frame_idx != meta_to_index(
181 owner0.list[p].paddr,
182 ) by {
183 owner0.relate_region_at_facts(regions0, p);
184 if frame_idx == meta_to_index(owner0.list[p].paddr) {
185 assert(regions0.slot_owners[meta_to_index(owner0.list[p].paddr)].in_list_perm.value()
186 == owner0.list_id);
187 }
188 }
189}
190
191impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> LinkedList<M> {
192 pub const fn new() -> Self {
194 Self { front: None, back: None, size: 0, list_id: 0 }
195 }
196}
197
198impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Default for LinkedList<M> {
199 fn default() -> Self {
200 Self::new()
201 }
202}
203
204#[verus_verify]
205impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> LinkedList<M> {
206 #[verus_spec(s =>
208 with
209 Tracked(owner): Tracked<LinkedListOwner<M>>,
210 requires
211 self.wf(owner),
212 owner.inv(),
213 ensures
214 s == owner@.list.len(),
215 )]
216 pub fn size(&self) -> usize {
217 proof {
218 LinkedListOwner::<M>::view_preserves_len(owner.list);
219 }
220 self.size
221 }
222
223 #[verus_spec(b =>
225 with
226 Tracked(owner): Tracked<LinkedListOwner<M>>,
227 requires
228 self.wf(owner),
229 owner.inv(),
230 ensures
231 b ==> self.size == 0 && self.front is None && self.back is None,
232 !b ==> self.size > 0 && self.front is Some && self.back is Some,
233 )]
234 pub fn is_empty(&self) -> bool {
235 let is_empty = self.size == 0;
236 is_empty
237 }
238
239 #[verus_spec(
251 with
252 Tracked(regions): Tracked<&mut MetaRegionOwners>,
253 Tracked(owner): Tracked<&mut LinkedListOwner<M>>,
254 Tracked(frame_own): Tracked<&mut UniqueFrameOwner<Link<M>>>,
255 requires
256 old(self).wf_region(*old(owner), *old(regions)),
257 old(owner).relate_region(*old(regions)),
258 old(frame_own).inv(),
259 old(frame_own).global_inv(*old(regions)),
260 frame.wf(*old(frame_own)),
261 old(frame_own).frame_link_inv(*old(regions)),
262 old(regions).inv(),
263 ensures
264 final(owner).relate_region(*final(regions)),
265 final(regions).inv(),
266 final(owner).list == old(owner).list.insert(0, final(frame_own).meta_own),
267 old(owner).list_id != 0 ==> final(owner).list_id == old(owner).list_id,
268 final(owner).list_id != 0,
269 final(frame_own).meta_own.paddr == old(frame_own).meta_own.paddr,
270 final(frame_own).meta_own.in_list == final(owner).list_id,
271 )]
272 pub fn push_front(&mut self, frame: UniqueFrame<Link<M>>) {
273 let current = self.front;
274 let tracked owner0 = LinkedListOwner::tracked_take(owner);
275 let tracked mut cursor_own = CursorOwner::tracked_front_owner(owner0);
276 let mut cursor = CursorMut { list: self, current };
277
278 #[verus_spec(with Tracked(regions), Tracked(&mut cursor_own), Tracked(frame_own))]
279 cursor.insert_before(frame);
280
281 proof {
282 *owner = cursor_own.list_own;
283 }
284 }
285
286 #[verus_spec(r =>
298 with
299 Tracked(regions): Tracked<&mut MetaRegionOwners>,
300 Tracked(owner): Tracked<LinkedListOwner<M>>,
301 Tracked(frame_own): Tracked<UniqueFrameOwner<Link<M>>>,
302 requires
303 old(regions).inv(),
304 old(self).wf_region(owner, *old(regions)),
305 owner.relate_region(*old(regions)),
306 ensures
307 owner.list.len() == 0 ==> r.is_none(),
308 r.is_some() ==> (r->0).1@@.meta == owner.list[0]@,
309 r.is_some() ==> (r->0).1@.frame_link_inv(*final(regions)),
310 )]
311 pub fn pop_front(&mut self) -> Option<
312 (UniqueFrame<Link<M>>, Tracked<UniqueFrameOwner<Link<M>>>),
313 > {
314 let tracked mut cursor_own = CursorOwner::tracked_front_owner(owner);
315 let current = self.front;
316 let mut cursor = CursorMut { list: self, current };
317
318 proof {
319 if owner.list.len() > 0 {
320 owner.relate_region_at_facts(*regions, 0);
321 }
322 }
323
324 #[verus_spec(with Tracked(regions), Tracked(&mut cursor_own))]
325 cursor.take_current()
326 }
327
328 #[verus_spec(
340 with
341 Tracked(regions): Tracked<&mut MetaRegionOwners>,
342 Tracked(owner): Tracked<&mut LinkedListOwner<M>>,
343 Tracked(frame_own): Tracked<&mut UniqueFrameOwner<Link<M>>>,
344 requires
345 old(self).wf_region(*old(owner), *old(regions)),
346 old(owner).relate_region(*old(regions)),
347 old(frame_own).inv(),
348 old(frame_own).global_inv(*old(regions)),
349 frame.wf(*old(frame_own)),
350 old(frame_own).frame_link_inv(*old(regions)),
351 old(regions).inv(),
352 ensures
353 final(owner).relate_region(*final(regions)),
354 final(regions).inv(),
355 old(owner).list.len() > 0 ==> final(owner).list == old(owner).list.insert(
356 old(owner).list.len() - 1, final(frame_own).meta_own),
357 old(owner).list.len() == 0 ==> final(owner).list == old(owner).list.insert(
358 0, final(frame_own).meta_own),
359 old(owner).list_id != 0 ==> final(owner).list_id == old(owner).list_id,
362 final(owner).list_id != 0,
363 final(frame_own).meta_own.paddr == old(frame_own).meta_own.paddr,
364 final(frame_own).meta_own.in_list == final(owner).list_id,
365 )]
366 pub fn push_back(&mut self, frame: UniqueFrame<Link<M>>) {
367 let current = self.back;
368 let tracked owner0 = LinkedListOwner::tracked_take(owner);
369 let tracked mut cursor_own = CursorOwner::tracked_back_owner(owner0);
370 let mut cursor = CursorMut { list: self, current };
371
372 #[verus_spec(with Tracked(regions), Tracked(&mut cursor_own), Tracked(frame_own))]
373 cursor.insert_before(frame);
374
375 proof {
376 *owner = cursor_own.list_own;
377 }
378 }
379
380 #[verus_spec(r =>
393 with
394 Tracked(regions): Tracked<&mut MetaRegionOwners>,
395 Tracked(owner): Tracked<LinkedListOwner<M>>,
396 Tracked(frame_own): Tracked<UniqueFrameOwner<Link<M>>>,
397 requires
398 old(regions).inv(),
399 old(self).wf_region(owner, *old(regions)),
400 owner.relate_region(*old(regions)),
401 ensures
402 owner.list.len() == 0 ==> r.is_none(),
403 r.is_some() ==> (r->0).1@@.meta == owner.list[owner.list.len() - 1]@,
404 r.is_some() ==> (r->0).1@.frame_link_inv(*final(regions)),
405 )]
406 pub fn pop_back(&mut self) -> Option<
407 (UniqueFrame<Link<M>>, Tracked<UniqueFrameOwner<Link<M>>>),
408 > {
409 let current = self.back;
410 let tracked mut cursor_own = CursorOwner::tracked_back_owner(owner);
411 let mut cursor = CursorMut { list: self, current };
412
413 proof {
414 if owner.list.len() > 0 {
415 owner.relate_region_at_facts(*regions, owner.list.len() - 1);
416 }
417 }
418
419 #[verus_spec(with Tracked(regions), Tracked(&mut cursor_own))]
420 cursor.take_current()
421 }
422
423 #[verus_spec(r =>
437 with
438 Tracked(regions): Tracked<&mut MetaRegionOwners>,
439 Tracked(slot_own): Tracked<&MetaSlotOwner>,
440 Tracked(owner): Tracked<&mut LinkedListOwner<M>>,
441 requires
442 slot_own.inv(),
443 old(regions).inv(),
444 ensures
445 old(owner).list_id != 0 ==> *final(owner) == *old(owner),
446 )]
447 pub fn contains(&mut self, frame: Paddr) -> bool {
448 proof_decl! {
449 let ghost idx = frame_to_index(frame);
450 if valid_frame_paddr(frame) {
451 regions.lemma_contains_valid_frame_paddr(frame);
452 }
453 let tracked slot_perm = if valid_frame_paddr(frame) {
454 Some(*regions.slots.tracked_borrow(idx))
455 } else {
456 None
457 };
458 }
459 let Ok(slot) = (#[verus_spec(with Tracked(slot_perm))]
460 crate::mm::frame::meta::get_slot(frame)) else {
461 return false;
462 };
463
464 let tracked mut slot_own = regions.slot_owners.tracked_borrow_mut(idx);
465
466 slot.in_list.load(Tracked(&mut slot_own.in_list_perm)) == #[verus_spec(with Tracked(owner))]
467 self.lazy_get_id()
468 }
469
470 #[verus_spec(r =>
488 with
489 Tracked(regions): Tracked<&mut MetaRegionOwners>,
490 Tracked(owner): Tracked<LinkedListOwner<M>>,
491 -> cursor_owner: Tracked<Option<CursorOwner<M>>>,
492 requires
493 old(regions).inv(),
494 ensures
495 !valid_frame_paddr(frame) ==> r is None,
496 final(regions).inv(),
497 final(regions).slots == old(regions).slots,
498 final(regions).slot_owners.dom() == old(regions).slot_owners.dom(),
499 )]
500 pub fn cursor_mut_at(&mut self, frame: Paddr) -> Option<CursorMut<'_, M>> {
501 proof_decl! {
502 let ghost idx = frame_to_index(frame);
503 if valid_frame_paddr(frame) {
504 regions.lemma_contains_valid_frame_paddr(frame);
505 }
506
507 let tracked slot_perm = if valid_frame_paddr(frame) {
508 Some(*regions.slots.tracked_borrow(idx))
509 } else {
510 None
511 };
512 }
513 let Ok(slot) = (#[verus_spec(with Tracked(slot_perm))]
514 crate::mm::frame::meta::get_slot(frame)) else {
515 return {
516 proof_with!(|= Tracked(None));
517 None
518 };
519 };
520
521 let tracked mut slot_own = regions.slot_owners.tracked_borrow_mut(idx);
522 let contains = slot.in_list.load(Tracked(&mut slot_own.in_list_perm))
523 == #[verus_spec(with Tracked(&owner))]
524 self.lazy_get_id();
525
526 if contains {
527 proof_decl!{
528 let ghost link = owner.list.filter(|link: LinkOwner| link.paddr == frame).first();
529 let ghost index = owner.list.index_of(link);
530 let tracked cursor_owner = CursorOwner::tracked_cursor_mut_at_owner(owner, index);
531 }
532
533 let meta_ptr = ReprPtr::<MetaSlotStorage, Link<M>>::from_pptr(
534 PPtr::<MetaSlotStorage>::from_addr(frame_to_meta(frame)),
535 );
536 proof_with!(|= Tracked(Some(cursor_owner)));
537 Some(CursorMut { list: self, current: Some(meta_ptr) })
538 } else {
539 proof_with!(|= Tracked(None));
540 None
541 }
542 }
543
544 #[verus_spec(r =>
559 with
560 Tracked(owner): Tracked<LinkedListOwner<M>>,
561 requires
562 old(self).wf(owner),
563 owner.inv(),
564 ensures
565 r.0.wf(r.1@),
566 r.1@.inv(),
567 r.1@ == CursorOwner::front_owner(owner),
568 )]
569 pub fn cursor_front_mut(&mut self) -> (CursorMut<'_, M>, Tracked<CursorOwner<M>>) {
570 let current = self.front;
571
572 (CursorMut { list: self, current }, Tracked(CursorOwner::tracked_front_owner(owner)))
573 }
574
575 #[verus_spec(
590 with
591 Tracked(owner): Tracked<LinkedListOwner<M>>,
592 )]
593 pub fn cursor_back_mut(&mut self) -> (res: (CursorMut<'_, M>, Tracked<CursorOwner<M>>))
594 requires
595 old(self).wf(owner),
596 owner.inv(),
597 ensures
598 res.0.wf(res.1@),
599 res.1@.inv(),
600 res.1@ == CursorOwner::back_owner(owner),
601 {
602 let current = self.back;
603
604 (CursorMut { list: self, current }, Tracked(CursorOwner::tracked_back_owner(owner)))
605 }
606
607 #[verus_spec(
609 with Tracked(owner): Tracked<&mut LinkedListOwner<M>>
610 )]
611 fn cursor_at_ghost_mut(&mut self) -> CursorMut<'_, M> {
612 CursorMut { list: self, current: None }
613 }
614
615 #[verifier::external_body]
619 #[verus_spec(
620 with Tracked(owner): Tracked<& LinkedListOwner<M>>
621 )]
622 fn lazy_get_id(&mut self) -> (id: u64)
623 ensures
624 owner.list_id != 0 ==> id == owner.list_id,
625 final(self).size == old(self).size,
626 final(self).front == old(self).front,
627 final(self).back == old(self).back,
628 old(self).list_id != 0 ==> final(self).list_id == old(self).list_id,
629 id != 0,
630 final(self).list_id == id,
631 {
632 unimplemented!()}
651}
652
653impl<'a, M: AnyFrameMeta + Repr<MetaSlotSmall>> CursorMut<'a, M> {
654 #[verus_spec(
661 with Tracked(owner): Tracked<CursorOwner<M>>,
662 Tracked(regions): Tracked<&MetaRegionOwners>,
663 )]
664 pub fn move_next(&mut self)
665 requires
666 owner.wf_with_region(*regions),
667 old(self).wf_region(owner, *regions),
668 ensures
669 owner.move_next_owner_spec()@ == owner@.move_next_spec(),
670 owner.move_next_owner_spec().wf_with_region(*regions),
671 final(self).wf_region(owner.move_next_owner_spec(), *regions),
672 {
673 proof {
674 if self.current is Some {
675 owner.list_own.relate_region_at_facts(*regions, owner.index);
676 }
677 if owner.index < owner.length() - 1 {
678 owner.list_own.relate_region_at_facts(*regions, owner.index + 1);
679 }
680 }
681
682 self.current = match self.current {
683 Some(current) => {
685 proof_decl!{
686 let ghost idx = meta_to_index(current.addr());
687 let tracked points_to = regions.slots.tracked_borrow(idx);
688 let tracked slot_owner = regions.slot_owners.tracked_borrow(idx);
689 let tracked repr_perm = owner.list_own.repr_perms.tracked_borrow(owner.index);
690 }
691 proof {
692 assert(regions.contains(idx));
693 }
694 let link = borrow_meta(
695 current,
696 Tracked(points_to),
697 Tracked(&slot_owner.metadata_perm),
698 Tracked(repr_perm),
699 );
700 link.next
701 },
702 None => self.list.front,
703 };
704
705 proof {
706 LinkedListOwner::<M>::view_preserves_len(owner.list_own.list);
707 assert(owner.move_next_owner_spec()@.fore == owner@.move_next_spec().fore);
708 assert(owner.move_next_owner_spec()@.rear == owner@.move_next_spec().rear);
709 }
710 }
711
712 #[verus_spec(
719 with Tracked(owner): Tracked<CursorOwner<M>>,
720 Tracked(regions): Tracked<&MetaRegionOwners>,
721 )]
722 pub fn move_prev(&mut self)
723 requires
724 owner.wf_with_region(*regions),
725 old(self).wf_region(owner, *regions),
726 ensures
727 owner.move_prev_owner_spec()@ == owner@.move_prev_spec(),
728 owner.move_prev_owner_spec().wf_with_region(*regions),
729 final(self).wf_region(owner.move_prev_owner_spec(), *regions),
730 {
731 proof {
732 if self.current is Some {
733 owner.list_own.relate_region_at_facts(*regions, owner.index);
734 }
735 if 0 < owner.index {
736 owner.list_own.relate_region_at_facts(*regions, owner.index - 1);
737 }
738 }
739
740 self.current = match self.current {
741 Some(current) => {
743 proof_decl!{
744 let ghost idx = meta_to_index(current.addr());
745 let tracked points_to = regions.slots.tracked_borrow(idx);
746 let tracked slot_owner = regions.slot_owners.tracked_borrow(idx);
747 let tracked repr_perm = owner.list_own.repr_perms.tracked_borrow(owner.index);
748 }
749 proof {
750 assert(regions.contains(idx));
751 }
752
753 let link = borrow_meta(
754 current,
755 Tracked(points_to),
756 Tracked(&slot_owner.metadata_perm),
757 Tracked(repr_perm),
758 );
759 link.prev
760 },
761 None => self.list.back,
762 };
763
764 proof {
765 LinkedListOwner::<M>::view_preserves_len(owner.list_own.list);
766
767 if owner@.list_model.list.len() > 0 {
768 if owner@.fore.len() > 0 {
769 assert(owner.move_prev_owner_spec()@.fore == owner@.move_prev_spec().fore);
770 assert(owner.move_prev_owner_spec()@.rear == owner@.move_prev_spec().rear);
771 if owner@.rear.len() > 0 {
772 owner.list_own.relate_region_at_facts(*regions, owner.index);
773 }
774 } else {
775 owner.list_own.relate_region_at_facts(*regions, owner.index);
776 assert(owner.move_prev_owner_spec()@.rear == owner@.move_prev_spec().rear);
777 assert(owner@.rear == owner@.list_model.list);
778 }
779 }
780 }
781 }
782
783 #[verus_spec(
797 with Tracked(owner): Tracked<&'b mut CursorOwner<M>>,
798 Tracked(regions): Tracked<&'b mut MetaRegionOwners>,
799 )]
800 pub fn current_meta<'b>(&'b mut self) -> (res: Option<&'b mut M>)
801 requires
802 old(self).wf_region(*old(owner), *old(regions)),
803 old(owner).wf_with_region(*old(regions)),
804 old(regions).inv(),
805 ensures
806 final(owner).index == old(owner).index,
807 final(owner).list_own.list == old(owner).list_own.list,
808 final(owner).list_own.list_id == old(owner).list_own.list_id,
809 *final(self) == *old(self),
810 res.is_some() == (0 <= final(owner).index < final(owner).length()),
811 final(regions).slots.dom() == old(regions).slots.dom(),
812 final(regions).slot_owners.dom() == old(regions).slot_owners.dom(),
813 {
814 match self.current {
820 Some(current) => {
821 proof {
822 owner.list_own.relate_region_at_facts(*regions, owner.index);
823 }
824 let ghost idx = meta_to_index(current.addr());
825 proof {
826 assert(regions.contains(idx));
827 }
828 let tracked points_to = regions.slots.tracked_borrow(idx);
829 let tracked slot_owner = regions.slot_owners.tracked_borrow_mut(idx);
830 let tracked repr_perm = owner.list_own.repr_perms.tracked_borrow_mut(owner.index);
831 Some(
832 &mut borrow_meta_mut(
833 current,
834 Tracked(points_to),
835 Tracked(slot_owner),
836 Tracked(repr_perm),
837 ).meta,
838 )
839 },
840 None => None,
841 }
842 }
843
844 #[verus_spec(
862 with Tracked(regions) : Tracked<&mut MetaRegionOwners>,
863 Tracked(owner) : Tracked<&mut CursorOwner<M>>
864 )]
865 #[verifier::spinoff_prover]
866 #[verifier::rlimit(200)]
867 pub fn take_current(&mut self) -> (res: Option<
868 (UniqueFrame<Link<M>>, Tracked<UniqueFrameOwner<Link<M>>>),
869 >)
870 requires
871 old(self).wf_region(*old(owner), *old(regions)),
872 old(owner).wf_with_region(*old(regions)),
873 old(regions).inv(),
874 ensures
875 old(owner).length() == 0 ==> res.is_none(),
876 old(self).current.is_some() ==> res.is_some(),
877 res.is_some() ==> (res->0).1@@.meta == old(owner).list_own.list[old(owner).index]@,
878 res.is_some() ==> final(owner)@ == old(owner)@.remove(),
879 res.is_some() ==> (res->0).1@.frame_link_inv(*final(regions)),
880 res.is_some() ==> final(owner).wf_with_region(*final(regions)),
882 res.is_some() ==> final(self).wf_region(*final(owner), *final(regions)),
883 res.is_none() ==> *final(owner) == *old(owner),
884 final(regions).inv(),
885 res.is_some() ==> final(owner).index == old(owner).index,
887 res.is_some() ==> final(owner).list_own.list == old(owner).list_own.list.remove(
888 old(owner).index,
889 ),
890 final(owner).list_own.list_id == old(owner).list_own.list_id,
891 res.is_some() ==> {
892 let paddr = old(self).current->0.addr();
893 let idx = meta_to_index(paddr);
894 &&& final(regions).slots.dom() == old(regions).slots.dom()
895 &&& final(regions).slot_owners[idx].ref_count() == REF_COUNT_UNIQUE
896 &&& final(regions).slot_owners[idx].in_list_perm.value() == 0
897 &&& final(regions).slot_owners[idx].storage_perm().is_init()
898 &&& final(regions).slot_owners[idx].vtable_ptr_perm().is_init()
899 &&& final(regions).slot_owners[idx].slot_vaddr == index_to_meta(idx)
900 &&& final(regions).slot_owners[idx].paths_in_pt == old(
901 regions,
902 ).slot_owners[idx].paths_in_pt
903 },
904 res.is_some() ==> forall|j: int|
905 #![trigger final(regions).slot_owners[j]]
906 j != meta_to_index(old(self).current->0.addr()) ==> {
907 &&& final(regions).slot_owners[j].usage == old(regions).slot_owners[j].usage
908 &&& final(regions).slot_owners[j].slot_vaddr == old(
909 regions,
910 ).slot_owners[j].slot_vaddr
911 &&& final(regions).slot_owners[j].paths_in_pt == old(
912 regions,
913 ).slot_owners[j].paths_in_pt
914 },
915 res.is_none() ==> *final(regions) == *old(regions),
916 res.is_some() ==> (res->0).0.wf((res->0).1@),
918 res.is_some() ==> (res->0).1@.inv(),
919 res.is_some() ==> (res->0).1@.slot_index == meta_to_index(old(self).current->0.addr()),
920 res.is_some() ==> (res->0).0.ptr.addr() == old(self).current->0.addr(),
921 res.is_some() ==> final(regions).frame_obligations == old(
922 regions,
923 ).frame_obligations.insert(meta_to_index(old(self).current->0.addr())),
924 {
925 let ghost owner0 = *owner;
926 let ghost regions0 = *regions;
927
928 let current = self.current?;
929
930 proof {
931 owner.list_own.relate_region_at_facts(*regions, owner.index);
932 if owner.index > 0 {
933 owner.list_own.relate_region_at_facts(*regions, owner.index - 1);
934 }
935 if owner.index < owner.list_own.list.len() - 1 {
936 owner.list_own.relate_region_at_facts(*regions, owner.index + 1);
937 }
938 }
939
940 let meta_ptr = current.addr();
941 let paddr = meta_to_frame(meta_ptr);
942 let ghost idx = frame_to_index(paddr);
943
944 let tracked mut cur_own = owner.list_own.list.tracked_remove(owner.index);
945 let tracked cur_repr_perm = owner.list_own.repr_perms.tracked_remove(owner.index);
946
947 let (mut frame, Tracked(mut frame_own)) = unsafe {
948 #[verus_spec(with Tracked(regions), Tracked(cur_own), Tracked(cur_repr_perm))]
950 UniqueFrame::<Link<M>>::from_raw(paddr)
951 };
952
953 proof {
954 assert(regions.slots.dom() == regions0.slots.dom());
955 assert forall|j: int| #![trigger regions0.slot_owners[j]] j != idx implies {
956 &&& regions.slot_owners[j].usage == regions0.slot_owners[j].usage
957 &&& regions.slot_owners[j].slot_vaddr == regions0.slot_owners[j].slot_vaddr
958 &&& regions.slot_owners[j].paths_in_pt == regions0.slot_owners[j].paths_in_pt
959 } by {}
960 }
961
962 let next_ptr = (#[verus_spec(with Tracked(&frame_own), Tracked(&*regions))]
963 frame.meta()).next;
964 let prev_ptr = (#[verus_spec(with Tracked(&frame_own), Tracked(&*regions))]
965 frame.meta()).prev;
966
967 if let Some(prev) = prev_ptr {
968 let ghost prev_idx = meta_to_index(owner.list_own.list[owner.index - 1].paddr);
969 let tracked prev_points_to = regions.slots.tracked_borrow(prev_idx);
970 let tracked prev_slot_owner = regions.slot_owners.tracked_borrow_mut(prev_idx);
971 let tracked prev_repr_perm = owner.list_own.repr_perms.tracked_borrow_mut(
972 owner.index - 1,
973 );
974 let prev_meta = borrow_meta_mut(
975 prev,
976 Tracked(prev_points_to),
977 Tracked(prev_slot_owner),
978 Tracked(prev_repr_perm),
979 );
980 prev_meta.next = next_ptr;
981
982 proof {
983 assert(regions.inv());
984 assert(regions.slots.dom() == regions0.slots.dom());
985 assert forall|j: int| #![trigger regions0.slot_owners[j]] j != idx implies {
986 &&& regions.slot_owners[j].usage == regions0.slot_owners[j].usage
987 &&& regions.slot_owners[j].slot_vaddr == regions0.slot_owners[j].slot_vaddr
988 &&& regions.slot_owners[j].paths_in_pt == regions0.slot_owners[j].paths_in_pt
989 } by {
990 if j == meta_to_index(prev.addr()) {
991 }
992 }
993 }
994
995 } else {
996 self.list.front = next_ptr;
997 proof {
998 assert(regions.slots.dom() == regions0.slots.dom());
999 assert forall|j: int| #![trigger regions0.slot_owners[j]] j != idx implies {
1000 &&& regions.slot_owners[j].usage == regions0.slot_owners[j].usage
1001 &&& regions.slot_owners[j].slot_vaddr == regions0.slot_owners[j].slot_vaddr
1002 &&& regions.slot_owners[j].paths_in_pt == regions0.slot_owners[j].paths_in_pt
1003 } by {}
1004 }
1005 }
1006
1007 if let Some(next) = next_ptr {
1008 let ghost next_idx = meta_to_index(owner.list_own.list[owner.index].paddr);
1009 let tracked next_points_to = regions.slots.tracked_borrow(next_idx);
1010 let tracked next_slot_owner = regions.slot_owners.tracked_borrow_mut(next_idx);
1011 let tracked next_repr_perm = owner.list_own.repr_perms.tracked_borrow_mut(owner.index);
1012 let next_meta = borrow_meta_mut(
1013 next,
1014 Tracked(next_points_to),
1015 Tracked(next_slot_owner),
1016 Tracked(next_repr_perm),
1017 );
1018 next_meta.prev = prev_ptr;
1019
1020 proof {
1021 assert(regions.inv());
1022 assert(regions.slots.dom() == regions0.slots.dom());
1023 assert forall|j: int| #![trigger regions0.slot_owners[j]] j != idx implies {
1024 &&& regions.slot_owners[j].usage == regions0.slot_owners[j].usage
1025 &&& regions.slot_owners[j].slot_vaddr == regions0.slot_owners[j].slot_vaddr
1026 &&& regions.slot_owners[j].paths_in_pt == regions0.slot_owners[j].paths_in_pt
1027 } by {
1028 if j == meta_to_index(next.addr()) {
1029 }
1030 }
1031 }
1032
1033 self.current = Some(next);
1034 } else {
1035 self.list.back = prev_ptr;
1036
1037 self.current = None;
1038 proof {
1039 assert(regions.slots.dom() == regions0.slots.dom());
1040 assert forall|j: int| #![trigger regions0.slot_owners[j]] j != idx implies {
1041 &&& regions.slot_owners[j].usage == regions0.slot_owners[j].usage
1042 &&& regions.slot_owners[j].slot_vaddr == regions0.slot_owners[j].slot_vaddr
1043 &&& regions.slot_owners[j].paths_in_pt == regions0.slot_owners[j].paths_in_pt
1044 } by {}
1045 }
1046 }
1047
1048 (#[verus_spec(with Tracked(&mut frame_own), Tracked(regions))]
1049 frame.meta_mut()).next = None;
1050 (#[verus_spec(with Tracked(&mut frame_own), Tracked(regions))]
1051 frame.meta_mut()).prev = None;
1052
1053 let tracked frame_outer = regions.slots.tracked_borrow(idx);
1054 let tracked mut frame_so = regions.slot_owners.tracked_borrow_mut(idx);
1055 #[verus_spec(with Tracked(&frame_outer))]
1056 let slot = frame.slot();
1057 slot.in_list.store(Tracked(&mut frame_so.in_list_perm), 0);
1058 proof {
1059 assert(regions.inv());
1060 assert(regions.slots.dom() == regions0.slots.dom());
1061 assert(regions.slot_owners[idx].paths_in_pt == regions0.slot_owners[idx].paths_in_pt);
1062 assert forall|j: int| #![trigger regions0.slot_owners[j]] j != idx implies {
1063 &&& regions.slot_owners[j].usage == regions0.slot_owners[j].usage
1064 &&& regions.slot_owners[j].slot_vaddr == regions0.slot_owners[j].slot_vaddr
1065 &&& regions.slot_owners[j].paths_in_pt == regions0.slot_owners[j].paths_in_pt
1066 } by {}
1067 }
1068
1069 self.list.size = self.list.size - 1;
1070
1071 proof {
1072 owner0.remove_owner_spec_implies_model_spec(*owner);
1073 let ghost oldl = owner0.list_own;
1074 let ghost nn = owner0.index as int;
1075 assert forall|p: int|
1076 #![trigger meta_to_index(oldl.list[p].paddr)]
1077 (0 <= p < oldl.list.len() && p != nn) implies ({
1078 let i = meta_to_index(oldl.list[p].paddr);
1079 let np = if p < nn {
1080 p
1081 } else {
1082 p - 1
1083 };
1084 let fp = owner.list_own.meta_value_at(*regions, np);
1085 &&& regions.contains(i)
1086 &&& regions.slots[i].addr() == oldl.list[p].paddr
1087 &&& regions.slots[i].pptr() == regions0.slots[i].pptr()
1088 &&& regions.slot_owners[i].ref_count() == REF_COUNT_UNIQUE
1089 &&& regions.slot_owners[i].usage is Frame
1090 &&& regions.slot_owners[i].in_list_perm.value() == owner.list_own.list_id
1091 &&& owner.list_own.meta_wf_at(*regions, np)
1092 &&& regions.slots[i].addr() % META_SLOT_SIZE == 0
1093 &&& FRAME_METADATA_RANGE.start <= regions.slots[i].addr()
1094 < FRAME_METADATA_RANGE.start + MAX_NR_PAGES * META_SLOT_SIZE
1095 &&& (p == nn - 1 ==> fp.next == oldl.meta_value_at(regions0, nn).next)
1096 &&& (p != nn - 1 ==> fp.next == oldl.meta_value_at(regions0, p).next)
1097 &&& (p == nn + 1 ==> fp.prev == oldl.meta_value_at(regions0, nn).prev)
1098 &&& (p != nn + 1 ==> fp.prev == oldl.meta_value_at(regions0, p).prev)
1099 }) by {
1100 let i = meta_to_index(oldl.list[p].paddr);
1101 let np = if p < nn {
1102 p
1103 } else {
1104 p - 1
1105 };
1106 let fp = owner.list_own.meta_value_at(*regions, np);
1107 oldl.relate_region_at_facts(regions0, p);
1108 oldl.relate_region_at_facts(regions0, nn);
1109 assert(regions.contains(i));
1110 }
1111 LinkedListOwner::pop_preserves_relate_region(
1112 oldl,
1113 regions0,
1114 owner.list_own,
1115 *regions,
1116 nn,
1117 );
1118 }
1119 Some((frame, Tracked(frame_own)))
1120 }
1121
1122 #[verus_spec(
1139 with Tracked(regions): Tracked<&mut MetaRegionOwners>,
1140 Tracked(owner): Tracked<&mut CursorOwner<M>>,
1141 Tracked(frame_own): Tracked<&mut UniqueFrameOwner<Link<M>>>
1142 )]
1143 #[verifier::spinoff_prover]
1144 #[verifier::rlimit(200)]
1145 pub fn insert_before(&mut self, mut frame: UniqueFrame<Link<M>>)
1146 requires
1147 old(self).wf_region(*old(owner), *old(regions)),
1148 old(owner).wf_with_region(*old(regions)),
1149 old(regions).inv(),
1150 old(frame_own).inv(),
1151 old(frame_own).global_inv(*old(regions)),
1152 frame.wf(*old(frame_own)),
1153 old(frame_own).frame_link_inv(*old(regions)),
1154 ensures
1155 final(owner).wf_with_region(*final(regions)),
1156 final(self).wf_region(*final(owner), *final(regions)),
1157 final(regions).inv(),
1158 final(owner).list_own.list == old(owner).list_own.list.insert(
1159 old(owner).index,
1160 final(frame_own).meta_own,
1161 ),
1162 old(owner).list_own.list_id != 0 ==> final(owner).list_own.list_id == old(
1165 owner,
1166 ).list_own.list_id,
1167 final(owner).list_own.list_id != 0,
1168 final(owner).index == old(owner).index + 1,
1169 final(frame_own).meta_own.paddr == old(frame_own).meta_own.paddr,
1170 final(frame_own).meta_own.in_list == final(owner).list_own.list_id,
1171 final(owner)@ == old(owner)@.insert(final(frame_own).meta_own@),
1172 {
1173 hide(LinkedListOwner::relate_region);
1174 hide(<MetaRegionOwners as Inv>::inv);
1175 let ghost owner0 = *owner;
1176 let ghost regions0 = *regions;
1177 let ghost nn = owner.index as int;
1178
1179 proof {
1180 assert(owner0.list_own.repr_perms.len() == owner0.list_own.list.len()) by {
1181 reveal(LinkedListOwner::relate_region);
1182 };
1183 assert(owner0.list_own.list.len() > 0 ==> owner0.list_own.list_id != 0) by {
1184 reveal(LinkedListOwner::relate_region);
1185 };
1186 assert(regions0.contains(frame_own.slot_index));
1187 lemma_meta_region_inv_at(regions0, frame_own.slot_index);
1188 owner0.list_own.length_lt_usize_max(regions0);
1189 if nn > 0 {
1190 assert(owner0.list_own.relate_region_at(regions0, nn - 1)) by {
1191 reveal(LinkedListOwner::relate_region);
1192 };
1193 owner.list_own.relate_region_at_facts(*regions, nn - 1);
1194 lemma_meta_region_inv_at(
1195 regions0,
1196 meta_to_index(owner0.list_own.list[nn - 1].paddr),
1197 );
1198 }
1199 if nn < owner.list_own.list.len() {
1200 assert(owner0.list_own.relate_region_at(regions0, nn)) by {
1201 reveal(LinkedListOwner::relate_region);
1202 };
1203 owner.list_own.relate_region_at_facts(*regions, nn);
1204 lemma_meta_region_inv_at(regions0, meta_to_index(owner0.list_own.list[nn].paddr));
1205 }
1206 assert forall|p: int|
1207 #![trigger
1208 regions0.slot_owners[meta_to_index(owner0.list_own.list[p].paddr)]]
1209 0 <= p < owner0.list_own.list.len() implies frame_own.slot_index != meta_to_index(
1210 owner0.list_own.list[p].paddr,
1211 ) by {
1212 lemma_insert_before_slot_distinct(
1213 owner0.list_own,
1214 regions0,
1215 frame_own.slot_index,
1216 nn,
1217 );
1218 }
1219 }
1220
1221 let frame_ptr = ReprPtr::<MetaSlotStorage, Link<M>>::from_pptr(
1222 PPtr::<MetaSlotStorage>::from_addr(frame.ptr.addr()),
1223 );
1224
1225 if let Some(current) = self.current {
1226 proof_decl!{
1227 let ghost idx = meta_to_index(current.addr());
1228 let tracked points_to = regions.slots.tracked_borrow(idx);
1229 let tracked slot_owner = regions.slot_owners.tracked_borrow(idx);
1230 let tracked repr_perm = owner.list_own.repr_perms.tracked_borrow(owner.index);
1231 }
1232
1233 let opt_prev_link: Option<ReprPtr<MetaSlotStorage, Link<M>>> = borrow_meta(
1235 current,
1236 Tracked(points_to),
1237 Tracked(&slot_owner.metadata_perm),
1238 Tracked(repr_perm),
1239 ).prev;
1240
1241 if let Some(prev_link) = opt_prev_link {
1242 let prev = prev_link;
1243
1244 (#[verus_spec(with Tracked(frame_own), Tracked(regions))]
1245 frame.meta_mut()).prev = Some(prev_link);
1246 (#[verus_spec(with Tracked(frame_own), Tracked(regions))]
1247 frame.meta_mut()).next = Some(current);
1248
1249 let ghost prev_idx = meta_to_index(owner.list_own.list[nn - 1].paddr);
1250 proof {
1251 assert(prev_idx != idx) by {
1252 reveal(LinkedListOwner::relate_region);
1253 };
1254 }
1255 let tracked prev_points_to = regions.slots.tracked_borrow(prev_idx);
1256 let tracked prev_slot_owner = regions.slot_owners.tracked_borrow_mut(prev_idx);
1257 let tracked prev_repr_perm = owner.list_own.repr_perms.tracked_borrow_mut(nn - 1);
1258 let prev_meta = borrow_meta_mut(
1259 prev,
1260 Tracked(prev_points_to),
1261 Tracked(prev_slot_owner),
1262 Tracked(prev_repr_perm),
1263 );
1264 prev_meta.next = Some(frame_ptr);
1265
1266 let ghost current_idx = meta_to_index(owner.list_own.list[nn].paddr);
1267 let tracked current_points_to = regions.slots.tracked_borrow(current_idx);
1268 let tracked current_slot_owner = regions.slot_owners.tracked_borrow_mut(
1269 current_idx,
1270 );
1271 let tracked current_repr_perm = owner.list_own.repr_perms.tracked_borrow_mut(nn);
1272 let current_meta = borrow_meta_mut(
1273 current,
1274 Tracked(current_points_to),
1275 Tracked(current_slot_owner),
1276 Tracked(current_repr_perm),
1277 );
1278 current_meta.prev = Some(frame_ptr);
1279 } else {
1280 (#[verus_spec(with Tracked(frame_own), Tracked(regions))]
1281 frame.meta_mut()).next = Some(current);
1282
1283 let ghost current_idx = meta_to_index(owner.list_own.list[nn].paddr);
1284 let tracked current_points_to = regions.slots.tracked_borrow(current_idx);
1285 let tracked current_slot_owner = regions.slot_owners.tracked_borrow_mut(
1286 current_idx,
1287 );
1288 let tracked current_repr_perm = owner.list_own.repr_perms.tracked_borrow_mut(nn);
1289 let current_meta = borrow_meta_mut(
1290 current,
1291 Tracked(current_points_to),
1292 Tracked(current_slot_owner),
1293 Tracked(current_repr_perm),
1294 );
1295 current_meta.prev = Some(frame_ptr);
1296 self.list.front = Some(frame_ptr);
1297 }
1298 } else {
1299 if let Some(back) = self.list.back {
1300 (#[verus_spec(with Tracked(frame_own), Tracked(regions))]
1301 frame.meta_mut()).prev = Some(back);
1302
1303 let ghost back_idx = meta_to_index(owner.list_own.list[nn - 1].paddr);
1304 proof {
1305 assert(0 <= nn - 1 < owner.list_own.repr_perms.len());
1306 }
1307 let tracked back_points_to = regions.slots.tracked_borrow(back_idx);
1308 let tracked back_slot_owner = regions.slot_owners.tracked_borrow_mut(back_idx);
1309 let tracked back_repr_perm = owner.list_own.repr_perms.tracked_borrow_mut(nn - 1);
1310 let back_meta = borrow_meta_mut(
1311 back,
1312 Tracked(back_points_to),
1313 Tracked(back_slot_owner),
1314 Tracked(back_repr_perm),
1315 );
1316 back_meta.next = Some(frame_ptr);
1317 self.list.back = Some(frame_ptr);
1318 } else {
1319 self.list.front = Some(frame_ptr);
1321 self.list.back = Some(frame_ptr);
1322 }
1323 }
1324
1325 #[verus_spec(with Tracked(&owner.list_own))]
1326 let list_id = self.list.lazy_get_id();
1327
1328 proof {
1329 assert(owner0.list_own.list.len() > 0 ==> list_id == owner0.list_own.list_id);
1330 }
1331 let tracked frame_outer = regions.slots.tracked_borrow_mut(frame_own.slot_index);
1332 let tracked mut frame_so = regions.slot_owners.tracked_borrow_mut(frame_own.slot_index);
1333 #[verus_spec(with Tracked(frame_outer))]
1334 let slot = frame.slot();
1335 slot.in_list.store(Tracked(&mut frame_so.in_list_perm), list_id);
1336 proof {
1337 assert(regions.inv()) by {
1338 reveal(<MetaRegionOwners as Inv>::inv);
1339 };
1340 }
1341
1342 #[verus_spec(with Tracked(&*frame_own), Tracked(regions))]
1343 let _ = frame.into_raw();
1344
1345 self.list.size = self.list.size + 1;
1346
1347 proof {
1348 let tracked frame_repr_perm = frame_own.repr_perm.tracked_take();
1349 CursorOwner::<M>::tracked_list_insert(
1350 owner,
1351 &mut frame_own.meta_own,
1352 frame_repr_perm,
1353 list_id,
1354 );
1355
1356 let oldl = owner0.list_own;
1357 let nn = owner0.index as int;
1358 let flink = frame_own.meta_own;
1359 let ins = frame_own.slot_index;
1360
1361 assert(owner.list_own.relate_region(*regions)) by {
1362 assert forall|p: int|
1363 #![trigger
1364 owner.list_own.insert_old_slot_post_at(
1365 *regions,
1366 oldl,
1367 regions0,
1368 nn,
1369 flink,
1370 p,
1371 )]
1372 (0 <= p < oldl.list.len()) implies owner.list_own.insert_old_slot_post_at(
1373 *regions,
1374 oldl,
1375 regions0,
1376 nn,
1377 flink,
1378 p,
1379 ) by {
1380 reveal(LinkedListOwner::insert_old_slot_post_at);
1381 assert(oldl.relate_region_at(regions0, p)) by {
1382 reveal(LinkedListOwner::relate_region);
1383 };
1384 oldl.relate_region_at_facts(regions0, p);
1385 if nn - 1 >= 0 && nn - 1 < oldl.list.len() && p != nn - 1 {
1386 assert(meta_to_index(oldl.list[p].paddr) != meta_to_index(
1387 oldl.list[nn - 1].paddr,
1388 )) by {
1389 reveal(LinkedListOwner::relate_region);
1390 };
1391 }
1392 if nn >= 0 && nn < oldl.list.len() && p != nn {
1393 assert(meta_to_index(oldl.list[p].paddr) != meta_to_index(
1394 oldl.list[nn].paddr,
1395 )) by {
1396 reveal(LinkedListOwner::relate_region);
1397 };
1398 }
1399 }
1400
1401 LinkedListOwner::insert_preserves_relate_region(
1402 oldl,
1403 regions0,
1404 owner.list_own,
1405 *regions,
1406 nn,
1407 flink,
1408 );
1409 };
1410
1411 owner0.insert_owner_spec_implies_model_spec(flink, *owner);
1412 }
1413 }
1414
1415 pub fn as_list(&self) -> &LinkedList<M> {
1417 self.list
1418 }
1419}
1420
1421impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> TrackDrop for LinkedList<M> {
1422 type State = (LinkedListOwner<M>, MetaRegionOwners);
1423
1424 type Obligation = DropObligation<u64>;
1432
1433 open spec fn tracked_redeem_requires(self, s: Self::State) -> bool {
1434 true
1435 }
1436
1437 open spec fn tracked_redeem_ensures(
1438 self,
1439 s0: Self::State,
1440 s1: Self::State,
1441 obl: Self::Obligation,
1442 ) -> bool {
1443 &&& s0 =~= s1
1444 &&& obl.value() == self.list_id
1445 }
1446
1447 proof fn tracked_redeem(self, tracked s: &mut Self::State) -> (tracked obl: Self::Obligation) {
1448 DropObligation::tracked_mint(self.list_id)
1449 }
1450
1451 open spec fn drop_requires(self, s: Self::State, obl: Self::Obligation) -> bool {
1452 &&& self.wf(s.0)
1453 &&& s.0.inv()
1454 &&& s.1.inv()
1455 &&& forall|i: int|
1456 #![trigger s.0.list[i]]
1457 0 <= i < s.0.list.len() ==> s.1.contains(meta_to_index(s.0.list[i].paddr))
1458 &&& forall|i: int|
1459 #![trigger s.0.list[i]]
1460 0 <= i < s.0.list.len() ==> {
1461 let idx = meta_to_index(s.0.list[i].paddr);
1462 s.1.contains(idx)
1463 }
1464 &&& forall|i: int|
1465 #![trigger s.0.list[i]]
1466 0 <= i < s.0.list.len() ==> {
1467 let idx = meta_to_index(s.0.list[i].paddr);
1468 s.1.slot_owners[idx].ref_count() == REF_COUNT_UNIQUE
1469 }
1470 &&& forall|i: int|
1471 #![trigger s.0.list[i]]
1472 0 <= i < s.0.list.len() ==> {
1473 let idx = meta_to_index(s.0.list[i].paddr);
1474 s.1.frame_obligations.count(idx) == 0
1475 }
1476 &&& forall|i: int|
1477 #![trigger s.0.list[i]]
1478 0 <= i < s.0.list.len() ==> {
1479 let idx = meta_to_index(s.0.list[i].paddr);
1480 s.1.slot_owners[idx].paths_in_pt.is_empty()
1481 }
1482 &&& forall|i: int, j: int|
1483 #![trigger s.0.list[i], s.0.list[j]]
1484 0 <= i < j < s.0.list.len() ==> meta_to_index(s.0.list[i].paddr) != meta_to_index(
1485 s.0.list[j].paddr,
1486 )
1487 &&& s.0.relate_region(s.1)
1488 &&& obl.value() == self.list_id
1489 }
1490
1491 open spec fn drop_ensures(
1492 self,
1493 s0: Self::State,
1494 s1: Self::State,
1495 obl: Self::Obligation,
1496 ) -> bool {
1497 &&& s1.0.list.len() == 0
1498 &&& forall|i: int|
1499 #![trigger s0.0.list[i]]
1500 0 <= i < s0.0.list.len() ==> {
1501 let idx = meta_to_index(s0.0.list[i].paddr);
1502 s1.1.frame_obligations.count(idx) == s0.1.frame_obligations.count(idx)
1503 }
1504 &&& forall|idx: int|
1505 #![trigger s1.1.slot_owners[idx]]
1506 (forall|i: int|
1507 #![trigger s0.0.list[i]]
1508 0 <= i < s0.0.list.len() ==> idx != meta_to_index(s0.0.list[i].paddr)) ==> {
1509 &&& s1.1.frame_obligations.count(idx) == s0.1.frame_obligations.count(idx)
1510 &&& s1.1.slot_owners[idx].usage == s0.1.slot_owners[idx].usage
1511 &&& s1.1.slot_owners[idx].slot_vaddr == s0.1.slot_owners[idx].slot_vaddr
1512 &&& s1.1.slot_owners[idx].paths_in_pt == s0.1.slot_owners[idx].paths_in_pt
1513 }
1514 &&& s1.1.slots.dom() =~= s0.1.slots.dom()
1515 &&& s1.1.inv()
1516 }
1517}
1518
1519impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Drop for LinkedList<M> {
1520 #[verifier::spinoff_prover]
1521 fn drop(
1522 self,
1523 Tracked(s): Tracked<&mut Self::State>,
1524 Tracked(obl): Tracked<DropObligation<u64>>,
1525 ) {
1526 proof_decl! {
1527 let tracked mut list_own: LinkedListOwner<M>;
1528 }
1529 let ghost original_list = s.0.list;
1530 let ghost original_list_id = s.0.list_id;
1531 let ghost n = original_list.len();
1532 let ghost original_regions = s.1;
1533 proof {
1534 list_own = LinkedListOwner::<M>::tracked_take(&mut s.0);
1535 }
1536 let tracked regions: &mut MetaRegionOwners = &mut s.1;
1537 let mut this = self;
1538
1539 #[verus_spec(with Tracked(list_own))]
1540 let cursor_pair = this.cursor_front_mut();
1541 let (mut cursor, Tracked(mut cursor_own)) = cursor_pair;
1542
1543 proof {
1544 if n > 0 {
1545 cursor_own.list_own.relate_region_at_facts(*regions, 0);
1546 cursor_own.list_own.relate_region_at_facts(*regions, n - 1);
1547 }
1548 }
1549
1550 let ghost mut k: int = 0;
1551
1552 loop
1553 invariant_except_break
1554 cursor.wf_region(cursor_own, *regions),
1555 cursor.current.is_some() <==> k < n,
1556 invariant
1557 cursor_own.wf_with_region(*regions),
1558 cursor_own.list_own.list_id == original_list_id,
1559 cursor_own.index == 0,
1560 regions.inv(),
1561 cursor_own.list_own.list.len() == n - k,
1562 0 <= k <= n,
1563 forall|j: int|
1565 #![trigger cursor_own.list_own.list[j]]
1566 0 <= j < n - k ==> cursor_own.list_own.list[j] == original_list[j + k],
1567 forall|j: int|
1569 #![trigger original_list[j]]
1570 0 <= j < k ==> {
1571 let idx = meta_to_index(original_list[j].paddr);
1572 regions.frame_obligations.count(idx) == 0
1573 },
1574 forall|idx: int|
1576 #![trigger regions.slot_owners[idx]]
1577 (forall|j: int|
1578 #![trigger original_list[j]]
1579 0 <= j < n ==> idx != meta_to_index(original_list[j].paddr)) ==> {
1580 &&& regions.frame_obligations.count(idx)
1581 == original_regions.frame_obligations.count(idx)
1582 &&& regions.slot_owners[idx].usage
1583 == original_regions.slot_owners[idx].usage
1584 &&& regions.slot_owners[idx].slot_vaddr
1585 == original_regions.slot_owners[idx].slot_vaddr
1586 &&& regions.slot_owners[idx].paths_in_pt
1587 == original_regions.slot_owners[idx].paths_in_pt
1588 },
1589 regions.slots.dom() == original_regions.slots.dom(),
1590 forall|j: int|
1592 #![trigger original_list[j]]
1593 k <= j < n ==> {
1594 let idx = meta_to_index(original_list[j].paddr);
1595 &&& regions.frame_obligations.count(idx)
1596 == original_regions.frame_obligations.count(idx)
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.frame_obligations.count(idx) == 0
1616 &&& original_regions.slot_owners[idx].paths_in_pt.is_empty()
1617 &&& original_regions.slot_owners[idx].ref_count() == REF_COUNT_UNIQUE
1618 },
1619 ensures
1620 k == n,
1621 cursor_own.list_own.list.len() == 0,
1622 decreases n - k,
1623 {
1624 #[verus_spec(with Tracked(regions), Tracked(&mut cursor_own))]
1625 let entry = cursor.take_current();
1626
1627 if let Some(current) = entry {
1628 let (mut frame, frame_own_tracked) = current;
1629 let tracked frame_own = frame_own_tracked.get();
1630 let ghost regions_pre_drop = *regions;
1631
1632 #[verus_spec(with Tracked(frame_own), Tracked(regions))]
1634 frame.drop();
1635
1636 proof {
1637 assert forall|i: int|
1638 #![trigger cursor_own.list_own.list[i]]
1639 0 <= i < cursor_own.list_own.list.len() implies ({
1640 let idx = meta_to_index(cursor_own.list_own.list[i].paddr);
1641 &&& regions.contains(idx)
1642 &&& regions.slot_owners[idx] == regions_pre_drop.slot_owners[idx]
1643 &&& regions.frame_obligations.count(idx)
1644 == regions_pre_drop.frame_obligations.count(idx)
1645 }) by {
1646 let idx = meta_to_index(cursor_own.list_own.list[i].paddr);
1647 let ghost _trig_k = original_list[k as int];
1648 let ghost _trig_ik = original_list[i + k + 1];
1649 assert(cursor_own.list_own.list[i] == original_list[i + k + 1]);
1650
1651 cursor_own.list_own.relate_region_at_facts(regions_pre_drop, i);
1652 };
1653 cursor_own.list_own.relate_region_preserved_external_change(
1654 regions_pre_drop,
1655 *regions,
1656 );
1657
1658 assert forall|j: int|
1659 #![trigger cursor_own.list_own.list[j]]
1660 0 <= j < n - k - 1 implies cursor_own.list_own.list[j] == original_list[j
1661 + k + 1] by {};
1662
1663 assert forall|j: int| #![trigger original_list[j]] 0 <= j < k implies ({
1664 let idx = meta_to_index(original_list[j].paddr);
1665 regions.frame_obligations.count(idx) == 0
1666 }) by {
1667 let ghost _a = original_list[j as int];
1668 let ghost _b = original_list[k as int];
1669 };
1670
1671 k = k + 1;
1672 }
1673 } else {
1674 break;
1675 }
1676 }
1677
1678 proof {
1681 let tracked mut final_list_own = cursor_own.list_own;
1682 vstd::modes::tracked_swap(&mut s.0, &mut final_list_own);
1683 final_list_own.tracked_destroy_empty();
1684 }
1685 }
1686}
1687
1688pub struct Link<M: AnyFrameMeta + Repr<MetaSlotSmall>> {
1697 pub next: Option<ReprPtr<MetaSlotStorage, Link<M>>>,
1698 pub prev: Option<ReprPtr<MetaSlotStorage, Link<M>>>,
1699 pub meta: M,
1700}
1701
1702impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Deref for Link<M> {
1703 type Target = M;
1704
1705 fn deref(&self) -> &Self::Target {
1706 &self.meta
1707 }
1708}
1709
1710impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> DerefMut for Link<M> {
1711 fn deref_mut(&mut self) -> &mut Self::Target {
1712 &mut self.meta
1713 }
1714}
1715
1716impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Link<M> {
1717 pub const fn new(meta: M) -> Self {
1719 Self { next: None, prev: None, meta }
1720 }
1721}
1722
1723unsafe impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> AnyFrameMeta for Link<M> {
1726 open spec fn on_drop_pre(
1727 &self,
1728 reader: crate::mm::VmReader<'_, crate::mm::Infallible>,
1729 regions: crate::specs::mm::frame::meta_region_owners::MetaRegionOwners,
1730 vm_io_owner: crate::specs::mm::io::VmIoOwner,
1731 ) -> bool {
1732 self.meta.on_drop_pre(reader, regions, vm_io_owner)
1733 }
1734
1735 fn on_drop(
1736 &mut self,
1737 reader: &mut crate::mm::VmReader<crate::mm::Infallible>,
1738 regions: Tracked<&mut crate::specs::mm::frame::meta_region_owners::MetaRegionOwners>,
1739 vm_io_owner: Tracked<&mut crate::specs::mm::io::VmIoOwner>,
1740 ) {
1741 self.meta.on_drop(reader, regions, vm_io_owner);
1742 }
1743
1744 fn is_untyped(&self) -> bool {
1745 self.meta.is_untyped()
1746 }
1747
1748 uninterp spec fn vtable_ptr(&self) -> usize;
1749}
1750
1751}