1use vstd::prelude::*;
7
8use vstd::atomic::PermissionU64;
9use vstd::seq_lib::*;
10use vstd::simple_pptr::*;
11
12use vstd_extra::cast_ptr::*;
13use vstd_extra::drop_tracking::{Drop, DropObligation, TrackDrop};
14use vstd_extra::ownership::*;
15use vstd_extra::trans_macros::*;
16
17use crate::mm::frame::UniqueFrame;
18use crate::mm::frame::meta::REF_COUNT_UNUSED;
19use crate::mm::frame::meta::mapping::frame_to_meta;
20use crate::mm::{Paddr, PagingLevel, Vaddr};
21use crate::specs::arch::mm::{MAX_NR_PAGES, MAX_PADDR, PAGE_SIZE};
22use crate::specs::mm::frame::linked_list::linked_list_owners::*;
23use crate::specs::mm::frame::meta_owners::{MetaSlotOwner, Metadata};
24use crate::specs::mm::frame::meta_region_owners::MetaRegionOwners;
25use crate::specs::mm::frame::unique::UniqueFrameOwner;
26
27use core::borrow::BorrowMut;
28use core::{
29 ops::{Deref, DerefMut},
30 ptr::NonNull,
31 sync::atomic::{AtomicU64, Ordering},
32};
33
34use crate::specs::*;
35
36use crate::mm::frame::meta::mapping::{
37 META_SLOT_SIZE, frame_to_index, max_meta_slots, meta_addr, meta_to_frame, meta_to_frame_spec,
38};
39use crate::mm::frame::meta::{AnyFrameMeta, MetaSlot, get_slot, has_safe_slot};
40use crate::specs::arch::kspace::FRAME_METADATA_RANGE;
41
42verus! {
43
44pub struct Link<M: AnyFrameMeta + Repr<MetaSlotSmall>> {
46 pub next: Option<ReprPtr<MetaSlot, MetadataAsLink<M>>>,
47 pub prev: Option<ReprPtr<MetaSlot, MetadataAsLink<M>>>,
48 pub meta: M,
49}
50
51pub struct LinkedList<M: AnyFrameMeta + Repr<MetaSlotSmall>> {
90 pub front: Option<ReprPtr<MetaSlot, MetadataAsLink<M>>>,
91 pub back: Option<ReprPtr<MetaSlot, MetadataAsLink<M>>>,
92 pub size: usize,
94 pub list_id: u64,
97}
98
99pub struct CursorMut<'a, M: AnyFrameMeta + Repr<MetaSlotSmall>> {
104 pub list: &'a mut LinkedList<M>,
105 pub current: Option<ReprPtr<MetaSlot, MetadataAsLink<M>>>,
106}
107
108impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> LinkedList<M> {
109 pub const fn new() -> Self {
111 Self { front: None, back: None, size: 0, list_id: 0 }
112 }
113}
114
115impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Default for LinkedList<M> {
116 fn default() -> Self {
117 Self::new()
118 }
119}
120
121#[verus_verify]
126impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> LinkedList<M> {
127 #[verus_spec(s =>
129 with
130 Tracked(owner): Tracked<LinkedListOwner<M>>,
131 requires
132 self.wf(owner),
133 owner.inv(),
134 ensures
135 s == self.model(owner).list.len(),
136 )]
137 pub fn size(&self) -> usize {
138 proof {
139 LinkedListOwner::<M>::view_preserves_len(owner.list);
140 }
141 self.size
142 }
143
144 #[verus_spec(b =>
146 with
147 Tracked(owner): Tracked<LinkedListOwner<M>>,
148 requires
149 self.wf(owner),
150 owner.inv(),
151 ensures
152 b ==> self.size == 0 && self.front is None && self.back is None,
153 !b ==> self.size > 0 && self.front is Some && self.back is Some,
154 )]
155 pub fn is_empty(&self) -> bool {
156 let is_empty = self.size == 0;
157 is_empty
158 }
159
160 #[verus_spec(
172 with
173 Tracked(regions): Tracked<&mut MetaRegionOwners>,
174 Tracked(owner): Tracked<&mut LinkedListOwner<M>>,
175 Tracked(frame_own): Tracked<&mut UniqueFrameOwner<Link<M>>>,
176 requires
177 old(self).wf_region(*old(owner), *old(regions)),
178 old(owner).relate_region(*old(regions)),
179 old(frame_own).inv(),
180 old(frame_own).global_inv(*old(regions)),
181 frame.wf(*old(frame_own)),
182 old(frame_own).frame_link_inv(*old(regions)),
183 old(regions).inv(),
184 ensures
185 final(owner).relate_region(*final(regions)),
186 final(regions).inv(),
187 final(owner).list == old(owner).list.insert(0, final(frame_own).meta_own),
188 old(owner).list_id != 0 ==> final(owner).list_id == old(owner).list_id,
189 final(owner).list_id != 0,
190 final(frame_own).meta_own.paddr == old(frame_own).meta_own.paddr,
191 final(frame_own).meta_own.in_list == final(owner).list_id,
192 )]
193 pub fn push_front(&mut self, frame: UniqueFrame<Link<M>>) {
194 let current = self.front;
195 let tracked mut cursor_own = CursorOwner::tracked_front_owner(*owner);
196 let mut cursor = CursorMut { list: self, current };
197
198 #[verus_spec(with Tracked(regions), Tracked(&mut cursor_own), Tracked(frame_own))]
199 cursor.insert_before(frame);
200
201 proof {
202 *owner = cursor_own.list_own;
203 }
204 }
205
206 #[verus_spec(r =>
218 with
219 Tracked(regions): Tracked<&mut MetaRegionOwners>,
220 Tracked(owner): Tracked<LinkedListOwner<M>>,
221 Tracked(frame_own): Tracked<UniqueFrameOwner<Link<M>>>,
222 requires
223 old(regions).inv(),
224 old(self).wf_region(owner, *old(regions)),
225 owner.relate_region(*old(regions)),
226 ensures
227 owner.list.len() == 0 ==> r.is_none(),
228 r.is_some() ==> r.unwrap().0.model(r.unwrap().1@).meta == owner.list[0]@,
229 r.is_some() ==> r.unwrap().1@.frame_link_inv(*final(regions)),
230 )]
231 pub fn pop_front(&mut self) -> Option<
232 (UniqueFrame<Link<M>>, Tracked<UniqueFrameOwner<Link<M>>>),
233 > {
234 let tracked mut cursor_own = CursorOwner::tracked_front_owner(owner);
235 let current = self.front;
236 let mut cursor = CursorMut { list: self, current };
237
238 proof {
239 if owner.list.len() > 0 {
240 let _ = owner.list[0];
241 owner.relate_region_at_facts(*regions, 0);
242 }
243 }
244
245 #[verus_spec(with Tracked(regions), Tracked(&mut cursor_own))]
246 cursor.take_current()
247 }
248
249 #[verus_spec(
261 with
262 Tracked(regions): Tracked<&mut MetaRegionOwners>,
263 Tracked(owner): Tracked<&mut LinkedListOwner<M>>,
264 Tracked(frame_own): Tracked<&mut UniqueFrameOwner<Link<M>>>,
265 requires
266 old(self).wf_region(*old(owner), *old(regions)),
267 old(owner).relate_region(*old(regions)),
268 old(frame_own).inv(),
269 old(frame_own).global_inv(*old(regions)),
270 frame.wf(*old(frame_own)),
271 old(frame_own).frame_link_inv(*old(regions)),
272 old(regions).inv(),
273 ensures
274 final(owner).relate_region(*final(regions)),
275 final(regions).inv(),
276 old(owner).list.len() > 0 ==> final(owner).list == old(owner).list.insert(
277 old(owner).list.len() as int - 1, final(frame_own).meta_own),
278 old(owner).list.len() == 0 ==> final(owner).list == old(owner).list.insert(
279 0, final(frame_own).meta_own),
280 old(owner).list_id != 0 ==> final(owner).list_id == old(owner).list_id,
283 final(owner).list_id != 0,
284 final(frame_own).meta_own.paddr == old(frame_own).meta_own.paddr,
285 final(frame_own).meta_own.in_list == final(owner).list_id,
286 )]
287 pub fn push_back(&mut self, frame: UniqueFrame<Link<M>>) {
288 let current = self.back;
289 let tracked mut cursor_own = CursorOwner::tracked_back_owner(*owner);
290 let mut cursor = CursorMut { list: self, current };
291
292 #[verus_spec(with Tracked(regions), Tracked(&mut cursor_own), Tracked(frame_own))]
293 cursor.insert_before(frame);
294
295 proof {
296 *owner = cursor_own.list_own;
297 }
298 }
299
300 #[verus_spec(r =>
313 with
314 Tracked(regions): Tracked<&mut MetaRegionOwners>,
315 Tracked(owner): Tracked<LinkedListOwner<M>>,
316 Tracked(frame_own): Tracked<UniqueFrameOwner<Link<M>>>,
317 requires
318 old(regions).inv(),
319 old(self).wf_region(owner, *old(regions)),
320 owner.relate_region(*old(regions)),
321 ensures
322 owner.list.len() == 0 ==> r.is_none(),
323 r.is_some() ==> r.unwrap().0.model(r.unwrap().1@).meta == owner.list[owner.list.len() - 1]@,
324 r.is_some() ==> r.unwrap().1@.frame_link_inv(*final(regions)),
325 )]
326 pub fn pop_back(&mut self) -> Option<
327 (UniqueFrame<Link<M>>, Tracked<UniqueFrameOwner<Link<M>>>),
328 > {
329 let current = self.back;
330 let tracked mut cursor_own = CursorOwner::tracked_back_owner(owner);
331 let mut cursor = CursorMut { list: self, current };
332
333 proof {
334 if owner.list.len() > 0 {
335 let _ = owner.list[owner.list.len() - 1];
336 owner.relate_region_at_facts(*regions, owner.list.len() - 1);
337 }
338 }
339
340 #[verus_spec(with Tracked(regions), Tracked(&mut cursor_own))]
341 cursor.take_current()
342 }
343
344 #[verus_spec(r =>
358 with
359 Tracked(regions): Tracked<&mut MetaRegionOwners>,
360 Tracked(slot_own): Tracked<&MetaSlotOwner>,
361 Tracked(owner): Tracked<&mut LinkedListOwner<M>>,
362 requires
363 slot_own.inv(),
364 old(regions).inv(),
365 ensures
366 old(owner).list_id != 0 ==> *final(owner) == *old(owner),
367 )]
368 pub fn contains(&mut self, frame: Paddr) -> bool {
369 let Ok(slot_ptr) = get_slot(frame) else {
370 return false;
371 };
372
373 proof {
374 broadcast use crate::mm::frame::meta::mapping::group_page_meta;
379
380 let idx = frame_to_index(frame);
381 assert(idx < max_meta_slots());
382 assert(regions.slot_owners.contains_key(idx));
383 assert(regions.slots.contains_key(idx));
384 assert(regions.slots[idx].is_init());
385 assert(regions.slot_owners[idx].inner_perms.in_list.is_for(
386 regions.slots[idx].value().in_list,
387 ));
388 }
389
390 let tracked mut slot_perm = regions.slots.tracked_remove(frame_to_index(frame));
391 let tracked mut slot_own = regions.slot_owners.tracked_remove(frame_to_index(frame));
392
393 let slot = slot_ptr.take(Tracked(&mut slot_perm));
394
395 let tracked mut inner_perms = slot_own.take_inner_perms();
396
397 let in_list = slot.in_list.load(Tracked(&mut inner_perms.in_list));
398 slot_ptr.put(Tracked(&mut slot_perm), slot);
399
400 proof {
401 slot_own.sync_inner(&inner_perms);
402 regions.slot_owners.tracked_insert(frame_to_index(frame), slot_own);
403 regions.slots.tracked_insert(frame_to_index(frame), slot_perm);
404 }
405
406 in_list == #[verus_spec(with Tracked(owner))]
407 self.lazy_get_id()
408 }
409
410 #[verus_spec(r =>
428 with
429 Tracked(regions): Tracked<&mut MetaRegionOwners>,
430 Tracked(owner): Tracked<LinkedListOwner<M>>,
431 -> cursor_owner: Tracked<Option<CursorOwner<M>>>,
432 requires
433 old(regions).inv(),
434 ensures
435 !has_safe_slot(frame) ==> r is None,
436 final(regions).inv(),
437 final(regions).slots == old(regions).slots,
438 final(regions).slot_owners.dom() == old(regions).slot_owners.dom(),
439 )]
440 pub fn cursor_mut_at(&mut self, frame: Paddr) -> Option<CursorMut<'_, M>> {
441 if let Ok(slot_ptr) = get_slot(frame) {
442 let ghost idx = frame_to_index(frame);
443 proof {
444 broadcast use crate::mm::frame::meta::mapping::group_page_meta;
445
446 assert(idx < max_meta_slots());
447 assert(regions.slot_owners.contains_key(idx));
448 assert(regions.slots.contains_key(idx));
449 }
450 let tracked slot_perm = regions.slots.tracked_borrow(idx);
451 let tracked mut slot_own = regions.slot_owners.tracked_remove(idx);
452 let tracked mut inner_perms = slot_own.take_inner_perms();
453
454 let slot = slot_ptr.borrow(Tracked(slot_perm));
455
456 let in_list = slot.in_list.load(Tracked(&mut inner_perms.in_list));
457
458 let contains = in_list == #[verus_spec(with Tracked(&owner))]
459 self.lazy_get_id();
460
461 #[verus_spec(with Tracked(slot_perm))]
462 let meta_ptr = slot.as_meta_ptr::<Link<M>>();
463
464 proof {
465 slot_own.sync_inner(&inner_perms);
466 regions.slot_owners.tracked_insert(idx, slot_own);
467 }
468
469 if contains {
470 let ghost link = owner.list.filter(|link: LinkOwner| link.paddr == frame).first();
471 let ghost index = owner.list.index_of(link);
472 let tracked cursor_owner = CursorOwner::tracked_cursor_mut_at_owner(owner, index);
473
474 proof_with!(|= Tracked(Some(cursor_owner)));
475 Some(
476 CursorMut {
477 list: self,
478 current: Some(MetadataAsLink::cast_from_metadata(meta_ptr)),
479 },
480 )
481 } else {
482 proof_with!(|= Tracked(None));
483 None
484 }
485 } else {
486 assert(!has_safe_slot(frame));
487 proof_with!(|= Tracked(None));
488 None
489 }
490 }
491
492 #[verus_spec(r =>
507 with
508 Tracked(owner): Tracked<LinkedListOwner<M>>,
509 requires
510 old(self).wf(owner),
511 owner.inv(),
512 ensures
513 r.0.wf(r.1@),
514 r.1@.inv(),
515 r.1@ == CursorOwner::front_owner(owner),
516 )]
517 pub fn cursor_front_mut(&mut self) -> (CursorMut<'_, M>, Tracked<CursorOwner<M>>) {
518 let current = self.front;
519
520 (CursorMut { list: self, current }, Tracked(CursorOwner::tracked_front_owner(owner)))
521 }
522
523 #[verus_spec(
538 with
539 Tracked(owner): Tracked<LinkedListOwner<M>>,
540 )]
541 pub fn cursor_back_mut(&mut self) -> (res: (CursorMut<'_, M>, Tracked<CursorOwner<M>>))
542 requires
543 old(self).wf(owner),
544 owner.inv(),
545 ensures
546 res.0.wf(res.1@),
547 res.1@.inv(),
548 res.1@ == CursorOwner::back_owner(owner),
549 {
550 let current = self.back;
551
552 (CursorMut { list: self, current }, Tracked(CursorOwner::tracked_back_owner(owner)))
553 }
554
555 #[verus_spec(
557 with Tracked(owner): Tracked<&mut LinkedListOwner<M>>
558 )]
559 fn cursor_at_ghost_mut(&mut self) -> CursorMut<'_, M> {
560 CursorMut { list: self, current: None }
561 }
562
563 #[verifier::external_body]
567 #[verus_spec(
568 with Tracked(owner): Tracked<& LinkedListOwner<M>>
569 )]
570 fn lazy_get_id(&mut self) -> (id: u64)
571 ensures
572 owner.list_id != 0 ==> id == owner.list_id,
573 final(self).size == old(self).size,
574 final(self).front == old(self).front,
575 final(self).back == old(self).back,
576 old(self).list_id != 0 ==> final(self).list_id == old(self).list_id,
577 id != 0,
578 final(self).list_id == id,
579 {
580 unimplemented!()}
599}
600
601impl<'a, M: AnyFrameMeta + Repr<MetaSlotSmall>> CursorMut<'a, M> {
602 #[verus_spec(
609 with Tracked(owner): Tracked<CursorOwner<M>>,
610 Tracked(regions): Tracked<&MetaRegionOwners>,
611 )]
612 pub fn move_next(&mut self)
613 requires
614 owner.inv_region(*regions),
615 old(self).wf_region(owner, *regions),
616 ensures
617 final(self).model(owner.move_next_owner_spec()) == old(self).model(
618 owner,
619 ).move_next_spec(),
620 owner.move_next_owner_spec().inv_region(*regions),
621 final(self).wf_region(owner.move_next_owner_spec(), *regions),
622 {
623 let ghost old_self = *self;
624
625 proof {
626 if self.current is Some {
627 let _ = owner.list_own.list[owner.index];
628 owner.list_own.relate_region_at_facts(*regions, owner.index);
629 }
630 if owner.index < owner.length() - 1 {
631 let _ = owner.list_own.list[owner.index + 1];
632 owner.list_own.relate_region_at_facts(*regions, owner.index + 1);
633 }
634 }
635
636 self.current = match self.current {
637 Some(current) => {
639 let current_md = MetadataAsLink::cast_to_metadata(current);
640 let ghost idx = frame_to_index(meta_to_frame(current.addr()));
641
642 proof {
643 assert(idx == owner.list_own.slot_index_at(owner.index));
644 assert(regions.slots.contains_key(idx));
645 assert(regions.slot_owners.contains_key(idx));
646 }
647
648 let tracked meta_perm = regions.borrow_typed_perm::<Link<M>>(idx);
649
650 borrow_field!(current_md => next, Meta(meta_perm))
651 },
652 None => self.list.front,
653 };
654
655 proof {
656 LinkedListOwner::<M>::view_preserves_len(owner.list_own.list);
657 assert(self.model(owner.move_next_owner_spec()).fore == old_self.model(
658 owner,
659 ).move_next_spec().fore);
660 assert(self.model(owner.move_next_owner_spec()).rear == old_self.model(
661 owner,
662 ).move_next_spec().rear);
663 }
664 }
665
666 #[verus_spec(
673 with Tracked(owner): Tracked<CursorOwner<M>>,
674 Tracked(regions): Tracked<&MetaRegionOwners>,
675 )]
676 pub fn move_prev(&mut self)
677 requires
678 owner.inv_region(*regions),
679 old(self).wf_region(owner, *regions),
680 ensures
681 final(self).model(owner.move_prev_owner_spec()) == old(self).model(
682 owner,
683 ).move_prev_spec(),
684 owner.move_prev_owner_spec().inv_region(*regions),
685 final(self).wf_region(owner.move_prev_owner_spec(), *regions),
686 {
687 let ghost old_self = *self;
688
689 proof {
690 if self.current is Some {
691 let _ = owner.list_own.list[owner.index];
692 owner.list_own.relate_region_at_facts(*regions, owner.index);
693 }
694 if 0 < owner.index {
695 let _ = owner.list_own.list[owner.index - 1];
696 owner.list_own.relate_region_at_facts(*regions, owner.index - 1);
697 }
698 }
699
700 self.current = match self.current {
701 Some(current) => {
703 let current_md = MetadataAsLink::cast_to_metadata(current);
704 let ghost idx = frame_to_index(meta_to_frame(current.addr()));
705
706 proof {
707 assert(idx == owner.list_own.slot_index_at(owner.index));
708 assert(regions.slots.contains_key(idx));
709 assert(regions.slot_owners.contains_key(idx));
710 }
711
712 let tracked meta_perm = regions.borrow_typed_perm::<Link<M>>(idx);
713
714 borrow_field!(current_md => prev, Meta(meta_perm))
715 },
716 None => self.list.back,
717 };
718
719 proof {
720 LinkedListOwner::<M>::view_preserves_len(owner.list_own.list);
721
722 if owner@.list_model.list.len() > 0 {
723 if owner@.fore.len() > 0 {
724 assert(self.model(owner.move_prev_owner_spec()).fore == old_self.model(
725 owner,
726 ).move_prev_spec().fore);
727 assert(self.model(owner.move_prev_owner_spec()).rear == old_self.model(
728 owner,
729 ).move_prev_spec().rear);
730 if owner@.rear.len() > 0 {
731 let _ = owner.list_own.list[owner.index];
732 owner.list_own.relate_region_at_facts(*regions, owner.index);
733 }
734 } else {
735 let _ = owner.list_own.list[owner.index];
736 owner.list_own.relate_region_at_facts(*regions, owner.index);
737 assert(self.model(owner.move_prev_owner_spec()).rear == old_self.model(
738 owner,
739 ).move_prev_spec().rear);
740 assert(owner@.rear == owner@.list_model.list);
741 }
742 }
743 }
744 }
745
746 #[verus_spec(
760 with Tracked(owner): Tracked<&'b mut CursorOwner<M>>,
761 Tracked(regions): Tracked<&'b mut MetaRegionOwners>,
762 )]
763 pub fn current_meta<'b>(&'b mut self) -> (res: Option<&'b mut M>)
764 requires
765 old(self).wf_region(*old(owner), *old(regions)),
766 old(owner).inv_region(*old(regions)),
767 old(regions).inv(),
768 ensures
769 final(owner).index == old(owner).index,
770 final(owner).list_own.list == old(owner).list_own.list,
771 final(owner).list_own.list_id == old(owner).list_own.list_id,
772 *final(self) == *old(self),
773 res.is_some() == (0 <= final(owner).index < final(owner).length()),
774 final(regions).slots.dom() == old(regions).slots.dom(),
775 final(regions).slot_owners.dom() == old(regions).slot_owners.dom(),
776 {
777 match self.current {
783 Some(current) => {
784 proof {
785 assert(self.wf_region(*owner, *regions));
786 assert(owner.inv_region(*regions));
787 assert(0 <= owner.index <= owner.length());
788 if !(0 <= owner.index < owner.length()) {
789 assert(owner.index == owner.length());
790 assert(self.current.is_none());
791 assert(false);
792 }
793 let _ = owner.list_own.list[owner.index];
794 owner.list_own.relate_region_at_facts(*regions, owner.index);
795 assert(current == self.current.unwrap());
796 }
797 let current_md = MetadataAsLink::cast_to_metadata(current);
798 let ghost idx = frame_to_index(meta_to_frame(current.addr()));
799 proof {
800 assert(idx == owner.list_own.slot_index_at(owner.index));
801 assert(regions.slots.contains_key(idx));
802 assert(regions.slot_owners.contains_key(idx));
803 }
804 let tracked current_perm = regions.borrow_mut_typed_perm::<Link<M>>(idx);
805 let link_md = current_md.borrow_mut(Tracked(current_perm));
806 let meta = &mut link_md.metadata.meta;
807 Some(meta)
808 },
809 None => {
810 proof {
811 assert(self.wf_region(*owner, *regions));
812 assert(owner.inv_region(*regions));
813 if 0 <= owner.index < owner.length() {
814 assert(self.current.is_some());
815 assert(false);
816 }
817 }
818 None
819 },
820 }
821 }
822
823 #[verus_spec(
841 with Tracked(regions) : Tracked<&mut MetaRegionOwners>,
842 Tracked(owner) : Tracked<&mut CursorOwner<M>>
843 )]
844 #[verifier::rlimit(8000)]
845 #[verifier::spinoff_prover]
846 pub fn take_current(&mut self) -> (res: Option<
847 (UniqueFrame<Link<M>>, Tracked<UniqueFrameOwner<Link<M>>>),
848 >)
849 requires
850 old(self).wf_region(*old(owner), *old(regions)),
851 old(owner).inv_region(*old(regions)),
852 old(regions).inv(),
853 ensures
854 old(owner).length() == 0 ==> res.is_none(),
855 old(self).current.is_some() ==> res.is_some(),
856 res.is_some() ==> res.unwrap().0.model(res.unwrap().1@).meta == old(
857 owner,
858 ).list_own.list[old(owner).index]@,
859 res.is_some() ==> final(self).model(*final(owner)) == old(self).model(
860 *old(owner),
861 ).remove(),
862 res.is_some() ==> res.unwrap().1@.frame_link_inv(*final(regions)),
863 res.is_some() ==> final(owner).inv_region(*final(regions)),
865 res.is_some() ==> final(self).wf_region(*final(owner), *final(regions)),
866 res.is_none() ==> *final(owner) =~= *old(owner),
867 final(regions).inv(),
868 res.is_some() ==> final(owner).index == old(owner).index,
870 res.is_some() ==> final(owner).list_own.list == old(owner).list_own.list.remove(
871 old(owner).index,
872 ),
873 final(owner).list_own.list_id == old(owner).list_own.list_id,
874 res.is_some() ==> {
875 let paddr = old(self).current.unwrap().addr();
876 let idx = frame_to_index(meta_to_frame(paddr));
877 &&& final(regions).slots.dom() =~= old(regions).slots.dom()
878 &&& final(regions).slot_owners[idx].inner_perms.ref_count.value()
879 == crate::specs::mm::frame::meta_owners::REF_COUNT_UNIQUE
880 &&& final(regions).slot_owners[idx].inner_perms.in_list.value() == 0
881 &&& final(regions).slot_owners[idx].inner_perms.storage.is_init()
882 &&& final(regions).slot_owners[idx].inner_perms.vtable_ptr.is_init()
883 &&& final(regions).slot_owners[idx].self_addr == meta_addr(idx)
884 &&& final(regions).slot_owners[idx].paths_in_pt == old(
885 regions,
886 ).slot_owners[idx].paths_in_pt
887 },
888 res.is_some() ==> forall|j: usize|
889 #![trigger final(regions).slot_owners[j]]
890 j != frame_to_index(meta_to_frame(old(self).current.unwrap().addr())) ==> {
891 &&& final(regions).slot_owners[j].usage == old(regions).slot_owners[j].usage
892 &&& final(regions).slot_owners[j].self_addr == old(
893 regions,
894 ).slot_owners[j].self_addr
895 &&& final(regions).slot_owners[j].paths_in_pt == old(
896 regions,
897 ).slot_owners[j].paths_in_pt
898 },
899 res.is_none() ==> *final(regions) =~= *old(regions),
900 res.is_some() ==> res.unwrap().0.wf(res.unwrap().1@),
902 res.is_some() ==> res.unwrap().1@.inv(),
903 res.is_some() ==> res.unwrap().1@.slot_index == frame_to_index(
904 meta_to_frame(old(self).current.unwrap().addr()),
905 ),
906 res.is_some() ==> res.unwrap().0.ptr.addr() == old(self).current.unwrap().addr(),
907 res.is_some() ==> final(regions).frame_obligations =~= old(
908 regions,
909 ).frame_obligations.insert(
910 frame_to_index(meta_to_frame(old(self).current.unwrap().addr())),
911 ),
912 {
913 let ghost owner0 = *owner;
914 let ghost regions0 = *regions;
915
916 let current = self.current?;
917 let current_md = MetadataAsLink::cast_to_metadata(current);
918
919 proof {
920 assert(0 <= owner.index < owner.list_own.list.len());
921 let _ = owner.list_own.list[owner.index];
922 owner.list_own.relate_region_at_facts(*regions, owner.index);
923 if owner.index > 0 {
924 let _ = owner.list_own.list[owner.index - 1];
925 owner.list_own.relate_region_at_facts(*regions, owner.index - 1);
926 }
927 if owner.index < owner.list_own.list.len() - 1 {
928 let _ = owner.list_own.list[owner.index + 1];
929 owner.list_own.relate_region_at_facts(*regions, owner.index + 1);
930 }
931 }
932
933 let meta_ptr = current.addr();
934 let paddr = meta_to_frame(meta_ptr);
935 let ghost idx = frame_to_index(paddr);
936
937 assert(current.addr() == owner.list_own.list[owner.index].paddr);
938 assert(idx == owner.list_own.slot_index_at(owner.index));
939
940 let tracked mut cur_own = owner.list_own.list.tracked_remove(owner.index);
941
942 let (frame, frame_own) = unsafe {
943 #[verus_spec(with Tracked(regions), Tracked(cur_own))]
944 UniqueFrame::<Link<M>>::from_raw(paddr)
945 };
946 let frame = frame;
947 let tracked frame_own = frame_own.get();
948
949 proof {
950 assert(regions.slots.dom() =~= regions0.slots.dom());
951 assert forall|j: usize| j != idx implies {
952 &&& regions.slot_owners[j].usage == regions0.slot_owners[j].usage
953 &&& regions.slot_owners[j].self_addr == regions0.slot_owners[j].self_addr
954 &&& regions.slot_owners[j].paths_in_pt == regions0.slot_owners[j].paths_in_pt
955 } by {}
956 }
957
958 let tracked tp = regions.borrow_typed_perm::<Link<M>>(idx);
959 proof {
960 assert(*tp =~= owner0.list_own.meta_perm_of(regions0, owner0.index));
961 }
962 let next_ptr = borrow_field!(current_md => next, Meta(tp));
963 let prev_ptr = borrow_field!(current_md => prev, Meta(tp));
964
965 if let Some(prev_link) = prev_ptr {
966 let prev = MetadataAsLink::cast_to_metadata(prev_link);
967 proof {
968 assert(owner0.index > 0);
969 assert(prev.addr() == owner0.list_own.list[owner0.index - 1].paddr);
970 assert(frame_to_index(meta_to_frame(prev.addr())) == owner0.list_own.slot_index_at(
971 owner0.index - 1,
972 ));
973 assert(frame_to_index(meta_to_frame(prev.addr())) != idx); assert(regions.slots[frame_to_index(meta_to_frame(prev.addr()))].pptr()
975 == prev.ptr);
976 }
977
978 let tracked prev_perm = regions.borrow_mut_typed_perm::<Link<M>>(
979 frame_to_index(meta_to_frame(prev.addr())),
980 );
981 update_field!(prev => next <- next_ptr, Meta(prev_perm));
982
983 proof {
984 assert(regions.inv());
985 assert(regions.slots.dom() =~= regions0.slots.dom());
986 assert forall|j: usize| j != idx implies {
987 &&& regions.slot_owners[j].usage == regions0.slot_owners[j].usage
988 &&& regions.slot_owners[j].self_addr == regions0.slot_owners[j].self_addr
989 &&& regions.slot_owners[j].paths_in_pt == regions0.slot_owners[j].paths_in_pt
990 } by {
991 if j == frame_to_index(meta_to_frame(prev.addr())) {
992 }
993 }
994 }
995
996 assert(owner0.index > 0);
997 } else {
998 self.list.front = next_ptr;
999 proof {
1000 assert(regions.slots.dom() =~= regions0.slots.dom());
1001 assert forall|j: usize| j != idx implies {
1002 &&& regions.slot_owners[j].usage == regions0.slot_owners[j].usage
1003 &&& regions.slot_owners[j].self_addr == regions0.slot_owners[j].self_addr
1004 &&& regions.slot_owners[j].paths_in_pt == regions0.slot_owners[j].paths_in_pt
1005 } by {}
1006 }
1007 }
1008
1009 if let Some(next_link) = next_ptr {
1010 let next = MetadataAsLink::cast_to_metadata(next_link);
1011 proof {
1012 assert(owner0.index < owner0.list_own.list.len() - 1);
1013 assert(next.addr() == owner0.list_own.list[owner0.index + 1].paddr);
1014 assert(frame_to_index(meta_to_frame(next.addr())) == owner0.list_own.slot_index_at(
1015 owner0.index + 1,
1016 ));
1017 assert(frame_to_index(meta_to_frame(next.addr())) != idx); assert(regions.slots[frame_to_index(meta_to_frame(next.addr()))].pptr()
1019 == next.ptr);
1020 }
1021
1022 let tracked next_perm = regions.borrow_mut_typed_perm::<Link<M>>(
1023 frame_to_index(meta_to_frame(next.addr())),
1024 );
1025 update_field!(next => prev <- prev_ptr, Meta(next_perm));
1026
1027 proof {
1028 assert(regions.inv());
1029 assert(regions.slots.dom() =~= regions0.slots.dom());
1030 assert forall|j: usize| j != idx implies {
1031 &&& regions.slot_owners[j].usage == regions0.slot_owners[j].usage
1032 &&& regions.slot_owners[j].self_addr == regions0.slot_owners[j].self_addr
1033 &&& regions.slot_owners[j].paths_in_pt == regions0.slot_owners[j].paths_in_pt
1034 } by {
1035 if j == frame_to_index(meta_to_frame(next.addr())) {
1036 }
1037 }
1038 }
1039
1040 self.current = Some(next_link);
1041 } else {
1042 self.list.back = prev_ptr;
1043
1044 self.current = None;
1045 proof {
1046 assert(regions.slots.dom() =~= regions0.slots.dom());
1047 assert forall|j: usize| j != idx implies {
1048 &&& regions.slot_owners[j].usage == regions0.slot_owners[j].usage
1049 &&& regions.slot_owners[j].self_addr == regions0.slot_owners[j].self_addr
1050 &&& regions.slot_owners[j].paths_in_pt == regions0.slot_owners[j].paths_in_pt
1051 } by {}
1052 }
1053 }
1054
1055 let tracked frame_perm = regions.borrow_mut_typed_perm::<Link<M>>(idx);
1056 update_field!(current_md => next <- None, Meta(frame_perm));
1057
1058 let tracked frame_perm = regions.borrow_mut_typed_perm::<Link<M>>(idx);
1059 update_field!(current_md => prev <- None, Meta(frame_perm));
1060
1061 let tracked frame_outer = regions.slots.tracked_remove(idx);
1062 let tracked mut frame_so = regions.slot_owners.tracked_remove(idx);
1063 let tracked mut fip = frame_so.take_inner_perms();
1064 #[verus_spec(with Tracked(&frame_outer))]
1065 let slot = frame.slot();
1066 slot.in_list.store(Tracked(&mut fip.in_list), 0);
1067 proof {
1068 frame_so.sync_inner(&fip);
1069 regions.slots.tracked_insert(idx, frame_outer);
1070 regions.slot_owners.tracked_insert(idx, frame_so);
1071 assert(regions.inv());
1072 assert(regions.slots.dom() =~= regions0.slots.dom());
1073 assert(regions.slot_owners[idx].paths_in_pt == regions0.slot_owners[idx].paths_in_pt);
1074 assert forall|j: usize| j != idx implies {
1075 &&& regions.slot_owners[j].usage == regions0.slot_owners[j].usage
1076 &&& regions.slot_owners[j].self_addr == regions0.slot_owners[j].self_addr
1077 &&& regions.slot_owners[j].paths_in_pt == regions0.slot_owners[j].paths_in_pt
1078 } by {}
1079 }
1080
1081 self.list.size = self.list.size - 1;
1082
1083 proof {
1084 owner0.remove_owner_spec_implies_model_spec(*owner);
1085 let ghost oldl = owner0.list_own;
1086 let ghost nn = owner0.index as int;
1087 assert forall|p: int|
1088 #![trigger oldl.slot_index_at(p)]
1089 (0 <= p < oldl.list.len() && p != nn) implies ({
1090 let i = oldl.slot_index_at(p);
1091 let fp = vstd_extra::cast_ptr::PointsTo::<MetaSlot, Metadata<Link<M>>>::new_spec(
1092 regions.slots[i],
1093 regions.slot_owners[i].inner_perms,
1094 );
1095 &&& regions.slots.contains_key(i)
1096 &&& regions.slot_owners.contains_key(i)
1097 &&& fp.addr() == oldl.list[p].paddr
1098 &&& fp.points_to.addr() == oldl.list[p].paddr
1099 &&& fp.points_to.pptr() == regions0.slots[i].pptr()
1100 &&& fp.inner_perms.ref_count.value()
1101 == crate::specs::mm::frame::meta_owners::REF_COUNT_UNIQUE
1102 &&& fp.wf(&fp.inner_perms)
1103 &&& fp.addr() % META_SLOT_SIZE == 0
1104 &&& FRAME_METADATA_RANGE.start <= fp.addr() < FRAME_METADATA_RANGE.start
1105 + MAX_NR_PAGES * META_SLOT_SIZE
1106 &&& fp.is_init()
1107 &&& (p == nn - 1 ==> fp.value().metadata.next == oldl.meta_perm_of(
1108 regions0,
1109 nn,
1110 ).value().metadata.next)
1111 &&& (p != nn - 1 ==> fp.value().metadata.next == oldl.meta_perm_of(
1112 regions0,
1113 p,
1114 ).value().metadata.next)
1115 &&& (p == nn + 1 ==> fp.value().metadata.prev == oldl.meta_perm_of(
1116 regions0,
1117 nn,
1118 ).value().metadata.prev)
1119 &&& (p != nn + 1 ==> fp.value().metadata.prev == oldl.meta_perm_of(
1120 regions0,
1121 p,
1122 ).value().metadata.prev)
1123 }) by {
1124 let i = oldl.slot_index_at(p);
1125 let _ = oldl.list[p];
1126 oldl.relate_region_at_facts(regions0, p);
1127 let _ = oldl.list[nn];
1128 oldl.relate_region_at_facts(regions0, nn);
1129 let _ = oldl.slot_index_at(nn - 1);
1130 let _ = oldl.slot_index_at(nn + 1);
1131 let _ = oldl.slot_index_at(nn);
1132 }
1133 LinkedListOwner::pop_preserves_relate_region(
1134 oldl,
1135 regions0,
1136 owner.list_own,
1137 *regions,
1138 nn,
1139 );
1140 }
1141 Some((frame, Tracked(frame_own)))
1142 }
1143
1144 #[verus_spec(
1161 with Tracked(regions): Tracked<&mut MetaRegionOwners>,
1162 Tracked(owner): Tracked<&mut CursorOwner<M>>,
1163 Tracked(frame_own): Tracked<&mut UniqueFrameOwner<Link<M>>>
1164 )]
1165 #[verifier::rlimit(8000)]
1166 #[verifier::spinoff_prover]
1167 pub fn insert_before(&mut self, mut frame: UniqueFrame<Link<M>>)
1168 requires
1169 old(self).wf_region(*old(owner), *old(regions)),
1170 old(owner).inv_region(*old(regions)),
1171 old(regions).inv(),
1172 old(frame_own).inv(),
1173 old(frame_own).global_inv(*old(regions)),
1174 frame.wf(*old(frame_own)),
1175 old(frame_own).frame_link_inv(*old(regions)),
1176 ensures
1177 final(owner).inv_region(*final(regions)),
1178 final(self).wf_region(*final(owner), *final(regions)),
1179 final(regions).inv(),
1180 final(owner).list_own.list == old(owner).list_own.list.insert(
1181 old(owner).index,
1182 final(frame_own).meta_own,
1183 ),
1184 old(owner).list_own.list_id != 0 ==> final(owner).list_own.list_id == old(
1187 owner,
1188 ).list_own.list_id,
1189 final(owner).list_own.list_id != 0,
1190 final(owner).index == old(owner).index + 1,
1191 final(frame_own).meta_own.paddr == old(frame_own).meta_own.paddr,
1192 final(frame_own).meta_own.in_list == final(owner).list_own.list_id,
1193 final(self).model(*final(owner)) == old(self).model(*old(owner)).insert(
1194 final(frame_own).meta_own@,
1195 ),
1196 {
1197 let ghost owner0 = *owner;
1198 let ghost regions0 = *regions;
1199 let ghost nn = owner.index as int;
1200
1201 proof {
1202 owner0.list_own.length_lt_usize_max(regions0);
1203 if nn > 0 {
1204 let _ = owner.list_own.list[nn - 1];
1205 owner.list_own.relate_region_at_facts(*regions, nn - 1);
1206 }
1207 if nn < owner.list_own.list.len() {
1208 let _ = owner.list_own.list[nn];
1209 owner.list_own.relate_region_at_facts(*regions, nn);
1210 }
1211 }
1212
1213 #[verus_spec(with Tracked(&*frame_own), Tracked(&*regions))]
1214 let frame_ptr = frame.meta_mut();
1215 let frame_ptr_as_link = MetadataAsLink::cast_from_metadata(frame_ptr);
1216
1217 let ghost frame_idx_g: usize = frame_own.slot_index;
1218
1219 if let Some(current) = self.current {
1220 let current_md = MetadataAsLink::cast_to_metadata(current);
1221
1222 let opt_prev_link: Option<ReprPtr<MetaSlot, MetadataAsLink<M>>>;
1224
1225 let tracked tp = regions.borrow_typed_perm::<Link<M>>(
1226 frame_to_index(meta_to_frame(current.addr())),
1227 );
1228 opt_prev_link = borrow_field!(current_md => prev, Meta(tp));
1229
1230 if let Some(prev_link) = opt_prev_link {
1231 let prev = MetadataAsLink::cast_to_metadata(prev_link);
1232
1233 let tracked perm = regions.borrow_mut_typed_perm::<Link<M>>(
1234 frame_to_index(meta_to_frame(prev.addr())),
1235 );
1236 update_field!(prev => next <- Some(frame_ptr_as_link), Meta(perm));
1237
1238 let tracked perm = regions.borrow_mut_typed_perm::<Link<M>>(frame_idx_g);
1239 update_field!(frame_ptr => prev <- Some(prev_link), Meta(perm));
1240
1241 let tracked perm = regions.borrow_mut_typed_perm::<Link<M>>(frame_idx_g);
1242 update_field!(frame_ptr => next <- Some(current), Meta(perm));
1243
1244 let tracked perm = regions.borrow_mut_typed_perm::<Link<M>>(
1245 frame_to_index(meta_to_frame(current.addr())),
1246 );
1247 update_field!(current_md => prev <- Some(frame_ptr_as_link), Meta(perm));
1248
1249 proof {
1250 let fpn_local = vstd_extra::cast_ptr::PointsTo::<
1251 MetaSlot,
1252 Metadata<Link<M>>,
1253 >::new_spec(
1254 regions.slots[frame_idx_g],
1255 regions.slot_owners[frame_idx_g].inner_perms,
1256 );
1257 assert(fpn_local.value().metadata.prev is Some);
1258 assert(fpn_local.value().metadata.prev.unwrap().addr()
1259 == owner0.list_own.list[nn - 1].paddr);
1260 assert(fpn_local.value().metadata.prev.unwrap().ptr
1261 == regions0.slots[owner0.list_own.slot_index_at(nn - 1)].pptr());
1262 assert(fpn_local.value().metadata.next is Some);
1263 assert(fpn_local.value().metadata.next.unwrap().addr()
1264 == owner0.list_own.list[nn].paddr);
1265 assert(fpn_local.value().metadata.next.unwrap().ptr
1266 == regions0.slots[owner0.list_own.slot_index_at(nn)].pptr());
1267 assert(fpn_local.inner_perms.ref_count.value()
1268 == crate::specs::mm::frame::meta_owners::REF_COUNT_UNIQUE);
1269 }
1270 } else {
1271 let tracked perm = regions.borrow_mut_typed_perm::<Link<M>>(frame_idx_g);
1272 update_field!(frame_ptr => next <- Some(current), Meta(perm));
1273
1274 let tracked perm = regions.borrow_mut_typed_perm::<Link<M>>(
1275 frame_to_index(meta_to_frame(current.addr())),
1276 );
1277 update_field!(current_md => prev <- Some(frame_ptr_as_link), Meta(perm));
1278
1279 self.list.front = Some(frame_ptr_as_link);
1280 proof {
1281 let fpn_local = vstd_extra::cast_ptr::PointsTo::<
1282 MetaSlot,
1283 Metadata<Link<M>>,
1284 >::new_spec(
1285 regions.slots[frame_idx_g],
1286 regions.slot_owners[frame_idx_g].inner_perms,
1287 );
1288 assert(fpn_local.value().metadata.prev is None);
1289 assert(fpn_local.value().metadata.next is Some);
1290 assert(fpn_local.value().metadata.next.unwrap().addr()
1291 == owner0.list_own.list[nn].paddr);
1292 assert(fpn_local.value().metadata.next.unwrap().ptr
1293 == regions0.slots[owner0.list_own.slot_index_at(nn)].pptr());
1294 assert(fpn_local.inner_perms.ref_count.value()
1295 == crate::specs::mm::frame::meta_owners::REF_COUNT_UNIQUE);
1296 }
1297 }
1298 } else {
1299 if let Some(back) = self.list.back {
1300 let back_md = MetadataAsLink::cast_to_metadata(back);
1301
1302 let tracked perm = regions.borrow_mut_typed_perm::<Link<M>>(
1303 frame_to_index(meta_to_frame(back.addr())),
1304 );
1305 update_field!(back_md => next <- Some(frame_ptr_as_link), Meta(perm));
1306
1307 let tracked perm = regions.borrow_mut_typed_perm::<Link<M>>(frame_idx_g);
1308 update_field!(frame_ptr => prev <- Some(back), Meta(perm));
1309
1310 self.list.back = Some(frame_ptr_as_link);
1311 proof {
1312 let fpn_local = vstd_extra::cast_ptr::PointsTo::<
1313 MetaSlot,
1314 Metadata<Link<M>>,
1315 >::new_spec(
1316 regions.slots[frame_idx_g],
1317 regions.slot_owners[frame_idx_g].inner_perms,
1318 );
1319 assert(fpn_local.value().metadata.prev is Some);
1320 assert(fpn_local.value().metadata.prev.unwrap().addr()
1321 == owner0.list_own.list[nn - 1].paddr);
1322 assert(fpn_local.value().metadata.prev.unwrap().ptr
1323 == regions0.slots[owner0.list_own.slot_index_at(nn - 1)].pptr());
1324 assert(fpn_local.value().metadata.next is None);
1325 assert(fpn_local.inner_perms.ref_count.value()
1326 == crate::specs::mm::frame::meta_owners::REF_COUNT_UNIQUE);
1327 }
1328 } else {
1329 self.list.front = Some(frame_ptr_as_link);
1331 self.list.back = Some(frame_ptr_as_link);
1332 proof {
1333 let fpn_local = vstd_extra::cast_ptr::PointsTo::<
1334 MetaSlot,
1335 Metadata<Link<M>>,
1336 >::new_spec(
1337 regions.slots[frame_idx_g],
1338 regions.slot_owners[frame_idx_g].inner_perms,
1339 );
1340 assert(fpn_local.value().metadata.prev is None);
1341 assert(fpn_local.value().metadata.next is None);
1342 assert(fpn_local.inner_perms.ref_count.value()
1343 == crate::specs::mm::frame::meta_owners::REF_COUNT_UNIQUE);
1344 }
1345 }
1346 }
1347
1348 #[verus_spec(with Tracked(&owner.list_own))]
1349 let list_id = self.list.lazy_get_id();
1350
1351 proof {
1352 assert(regions.slots.contains_key(frame_idx_g));
1353 assert(regions.slot_owners[frame_idx_g].inner_perms.in_list.is_for(
1354 regions.slots[frame_idx_g].value().in_list,
1355 ));
1356 }
1357 let tracked frame_outer = regions.slots.tracked_remove(frame_idx_g);
1358 let tracked mut frame_so = regions.slot_owners.tracked_remove(frame_idx_g);
1359 let tracked mut fip = frame_so.take_inner_perms();
1360 #[verus_spec(with Tracked(&frame_outer))]
1361 let slot = frame.slot();
1362 slot.in_list.store(Tracked(&mut fip.in_list), list_id);
1363 proof {
1364 frame_so.sync_inner(&fip);
1365 regions.slots.tracked_insert(frame_idx_g, frame_outer);
1366 regions.slot_owners.tracked_insert(frame_idx_g, frame_so);
1367 assert(regions.inv()); }
1369
1370 #[verus_spec(with Tracked(&*frame_own), Tracked(regions))]
1371 let _ = frame.into_raw();
1372
1373 proof {
1374 assert(self.list.size == owner.list_own.list.len());
1375 assert(owner.list_own.list.len() == owner0.list_own.list.len());
1376 assert(owner0.list_own.list.len() < usize::MAX);
1377 }
1378 self.list.size = self.list.size + 1;
1379
1380 proof {
1381 CursorOwner::<M>::list_insert(owner, &mut frame_own.meta_own, list_id);
1382
1383 let oldl = owner0.list_own;
1384 let nn = owner0.index as int;
1385 let flink = frame_own.meta_own;
1386 let ins = frame_own.slot_index;
1387
1388 assert forall|p: int|
1389 #![trigger oldl.slot_index_at(p)]
1390 (0 <= p < oldl.list.len()) implies ({
1391 let i = oldl.slot_index_at(p);
1392 let fp = vstd_extra::cast_ptr::PointsTo::<MetaSlot, Metadata<Link<M>>>::new_spec(
1393 regions.slots[i],
1394 regions.slot_owners[i].inner_perms,
1395 );
1396 &&& regions.slots.contains_key(i)
1397 &&& regions.slot_owners.contains_key(i)
1398 &&& fp.addr() == oldl.list[p].paddr
1399 &&& fp.points_to.addr() == oldl.list[p].paddr
1400 &&& fp.points_to.pptr() == regions0.slots[i].pptr()
1401 &&& fp.inner_perms.ref_count.value()
1402 == crate::specs::mm::frame::meta_owners::REF_COUNT_UNIQUE
1403 &&& fp.wf(&fp.inner_perms)
1404 &&& fp.addr() % META_SLOT_SIZE == 0
1405 &&& FRAME_METADATA_RANGE.start <= fp.addr() < FRAME_METADATA_RANGE.start
1406 + MAX_NR_PAGES * META_SLOT_SIZE
1407 &&& fp.is_init()
1408 &&& (p == nn - 1 ==> {
1409 &&& fp.value().metadata.next is Some
1410 &&& fp.value().metadata.next.unwrap().addr() == flink.paddr
1411 &&& fp.value().metadata.next.unwrap().ptr == regions.slots[ins].pptr()
1412 })
1413 &&& (p != nn - 1 ==> fp.value().metadata.next == oldl.meta_perm_of(
1414 regions0,
1415 p,
1416 ).value().metadata.next)
1417 &&& (p == nn ==> {
1418 &&& fp.value().metadata.prev is Some
1419 &&& fp.value().metadata.prev.unwrap().addr() == flink.paddr
1420 &&& fp.value().metadata.prev.unwrap().ptr == regions.slots[ins].pptr()
1421 })
1422 &&& (p != nn ==> fp.value().metadata.prev == oldl.meta_perm_of(
1423 regions0,
1424 p,
1425 ).value().metadata.prev)
1426 }) by {
1427 let i = oldl.slot_index_at(p);
1428 let _ = oldl.list[p];
1429 oldl.relate_region_at_facts(regions0, p);
1430 if nn - 1 >= 0 && nn - 1 < oldl.list.len() {
1431 let _ = oldl.list[nn - 1];
1432 oldl.relate_region_at_facts(regions0, nn - 1);
1433 }
1434 if nn >= 0 && nn < oldl.list.len() {
1435 let _ = oldl.list[nn];
1436 oldl.relate_region_at_facts(regions0, nn);
1437 }
1438 let _ = oldl.slot_index_at(nn - 1);
1439 let _ = oldl.slot_index_at(nn);
1440 let _ = oldl.slot_index_at(nn + 1);
1441 }
1442
1443 let fpn = vstd_extra::cast_ptr::PointsTo::<MetaSlot, Metadata<Link<M>>>::new_spec(
1444 regions.slots[ins],
1445 regions.slot_owners[ins].inner_perms,
1446 );
1447 assert(regions.slots.contains_key(ins));
1448 assert(regions.slot_owners.contains_key(ins));
1449 assert(fpn.addr() == flink.paddr);
1450 assert(fpn.points_to.addr() == flink.paddr);
1451 assert(fpn.inner_perms.ref_count.value()
1452 == crate::specs::mm::frame::meta_owners::REF_COUNT_UNIQUE);
1453 assert(fpn.wf(&fpn.inner_perms));
1454 assert(fpn.addr() % META_SLOT_SIZE == 0);
1455 assert(FRAME_METADATA_RANGE.start <= fpn.addr() < FRAME_METADATA_RANGE.start
1456 + MAX_NR_PAGES * META_SLOT_SIZE);
1457 assert(fpn.is_init());
1458 assert(nn == 0 <==> fpn.value().metadata.prev is None);
1459 assert(nn == oldl.list.len() <==> fpn.value().metadata.next is None);
1460 assert(nn > 0 ==> {
1461 &&& fpn.value().metadata.prev is Some
1462 &&& fpn.value().metadata.prev.unwrap().addr() == oldl.list[nn - 1].paddr
1463 &&& fpn.value().metadata.prev.unwrap().ptr == regions0.slots[oldl.slot_index_at(
1464 nn - 1,
1465 )].pptr()
1466 });
1467 assert(nn < oldl.list.len() ==> {
1468 &&& fpn.value().metadata.next is Some
1469 &&& fpn.value().metadata.next.unwrap().addr() == oldl.list[nn].paddr
1470 &&& fpn.value().metadata.next.unwrap().ptr == regions0.slots[oldl.slot_index_at(
1471 nn,
1472 )].pptr()
1473 });
1474
1475 LinkedListOwner::insert_preserves_relate_region(
1476 oldl,
1477 regions0,
1478 owner.list_own,
1479 *regions,
1480 nn,
1481 flink,
1482 );
1483
1484 owner0.insert_owner_spec_implies_model_spec(flink, *owner);
1485 }
1486 }
1487
1488 pub fn as_list(&self) -> &LinkedList<M> {
1490 self.list
1491 }
1492}
1493
1494impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> TrackDrop for LinkedList<M> {
1495 type State = (LinkedListOwner<M>, MetaRegionOwners);
1496
1497 type Key = u64;
1505
1506 open spec fn key(self) -> Self::Key {
1507 self.list_id
1508 }
1509
1510 open spec fn constructor_requires(self, s: Self::State) -> bool {
1511 true
1512 }
1513
1514 open spec fn constructor_ensures(
1515 self,
1516 s0: Self::State,
1517 s1: Self::State,
1518 obl_key: Self::Key,
1519 ) -> bool {
1520 &&& s0 =~= s1
1521 &&& obl_key == self.list_id
1522 }
1523
1524 proof fn constructor_spec(self, tracked s: &mut Self::State) -> (tracked obl: DropObligation<
1525 Self::Key,
1526 >) {
1527 DropObligation::tracked_mint(self.list_id)
1528 }
1529
1530 open spec fn drop_requires(self, s: Self::State) -> bool {
1531 &&& self.wf(s.0)
1532 &&& s.0.inv()
1533 &&& s.1.inv()
1534 &&& forall|i: int|
1535 #![trigger s.0.list[i]]
1536 0 <= i < s.0.list.len() ==> s.1.slot_owners.contains_key(
1537 frame_to_index(meta_to_frame(s.0.list[i].paddr)),
1538 )
1539 &&& forall|i: int|
1540 #![trigger s.0.list[i]]
1541 0 <= i < s.0.list.len() ==> {
1542 let idx = frame_to_index(meta_to_frame(s.0.list[i].paddr));
1543 s.1.slots.contains_key(idx)
1544 }
1545 &&& forall|i: int|
1546 #![trigger s.0.list[i]]
1547 0 <= i < s.0.list.len() ==> {
1548 let idx = frame_to_index(meta_to_frame(s.0.list[i].paddr));
1549 s.1.slot_owners[idx].inner_perms.ref_count.value()
1550 == crate::specs::mm::frame::meta_owners::REF_COUNT_UNIQUE
1551 }
1552 &&& forall|i: int|
1553 #![trigger s.0.list[i]]
1554 0 <= i < s.0.list.len() ==> {
1555 let idx = frame_to_index(meta_to_frame(s.0.list[i].paddr));
1556 s.1.frame_obligations.count(idx) == 0
1557 }
1558 &&& forall|i: int|
1559 #![trigger s.0.list[i]]
1560 0 <= i < s.0.list.len() ==> {
1561 let idx = frame_to_index(meta_to_frame(s.0.list[i].paddr));
1562 s.1.slot_owners[idx].paths_in_pt.is_empty()
1563 }
1564 &&& forall|i: int, j: int|
1565 #![trigger s.0.list[i], s.0.list[j]]
1566 0 <= i < j < s.0.list.len() ==> frame_to_index(meta_to_frame(s.0.list[i].paddr))
1567 != frame_to_index(meta_to_frame(s.0.list[j].paddr))
1568 &&& s.0.relate_region(s.1)
1569 }
1570
1571 open spec fn drop_ensures(self, s0: Self::State, s1: Self::State, obl_key: Self::Key) -> bool {
1572 &&& s1.0.list.len() == 0
1573 &&& forall|i: int|
1574 #![trigger s0.0.list[i]]
1575 0 <= i < s0.0.list.len() ==> {
1576 let idx = frame_to_index(meta_to_frame(s0.0.list[i].paddr));
1577 s1.1.frame_obligations.count(idx) == s0.1.frame_obligations.count(idx)
1578 }
1579 &&& forall|idx: usize|
1580 #![trigger s1.1.slot_owners[idx]]
1581 (forall|i: int|
1582 #![trigger s0.0.list[i]]
1583 0 <= i < s0.0.list.len() ==> idx != frame_to_index(
1584 meta_to_frame(s0.0.list[i].paddr),
1585 )) ==> {
1586 &&& s1.1.frame_obligations.count(idx) == s0.1.frame_obligations.count(idx)
1587 &&& s1.1.slot_owners[idx].usage == s0.1.slot_owners[idx].usage
1588 &&& s1.1.slot_owners[idx].self_addr == s0.1.slot_owners[idx].self_addr
1589 &&& s1.1.slot_owners[idx].paths_in_pt == s0.1.slot_owners[idx].paths_in_pt
1590 }
1591 &&& s1.1.slots.dom() =~= s0.1.slots.dom()
1592 &&& s1.1.inv()
1593 }
1594
1595 open spec fn consume_requires(self, s: Self::State, obl_key: Self::Key) -> bool {
1596 obl_key == self.list_id
1599 }
1600
1601 open spec fn consume_ensures(
1602 self,
1603 s0: Self::State,
1604 s1: Self::State,
1605 obl_key: Self::Key,
1606 ) -> bool {
1607 s0 =~= s1
1608 }
1609
1610 proof fn consume_obligation(
1611 self,
1612 tracked s: &mut Self::State,
1613 tracked obl: DropObligation<Self::Key>,
1614 ) {
1615 }
1618}
1619
1620impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Drop for LinkedList<M> {
1621 #[verifier::rlimit(8000)]
1622 #[verifier::spinoff_prover]
1623 fn drop(
1624 self,
1625 Tracked(s): Tracked<&mut Self::State>,
1626 Tracked(obl): Tracked<DropObligation<u64>>,
1627 ) {
1628 proof {
1631 self.consume_obligation(s, obl);
1632 }
1633
1634 proof_decl! {
1635 let tracked mut list_own: LinkedListOwner<M>;
1636 }
1637 let ghost original_list = s.0.list;
1638 let ghost original_list_id = s.0.list_id;
1639 let ghost n = original_list.len();
1640 let ghost original_regions = s.1;
1641 proof {
1642 assert forall|j: int| #![trigger original_list[j]] 0 <= j < n implies ({
1643 let idx = frame_to_index(meta_to_frame(original_list[j].paddr));
1644 &&& original_regions.slot_owners.contains_key(idx)
1645 &&& original_regions.slots.contains_key(idx)
1646 &&& original_regions.frame_obligations.count(idx) == 0
1647 &&& original_regions.slot_owners[idx].paths_in_pt.is_empty()
1648 &&& original_regions.slot_owners[idx].inner_perms.ref_count.value()
1649 == crate::specs::mm::frame::meta_owners::REF_COUNT_UNIQUE
1650 }) by {
1651 let _ = s.0.list[j];
1652 };
1653 list_own = LinkedListOwner::<M>::tracked_take(&mut s.0);
1654 }
1655 let tracked regions: &mut MetaRegionOwners = &mut s.1;
1656 let mut this = self;
1657
1658 #[verus_spec(with Tracked(list_own))]
1659 let cursor_pair = this.cursor_front_mut();
1660 let (mut cursor, Tracked(mut cursor_own)) = cursor_pair;
1661
1662 proof {
1663 if n > 0 {
1664 let _ = cursor_own.list_own.list[0];
1665 cursor_own.list_own.relate_region_at_facts(*regions, 0);
1666 let _ = cursor_own.list_own.list[n as int - 1];
1667 cursor_own.list_own.relate_region_at_facts(*regions, n as int - 1);
1668 }
1669 }
1670
1671 let ghost mut k: int = 0;
1672
1673 loop
1674 invariant_except_break
1675 cursor.wf_region(cursor_own, *regions),
1676 cursor.current.is_some() <==> k < n,
1677 invariant
1678 cursor_own.inv_region(*regions),
1679 cursor_own.list_own.list_id == original_list_id,
1680 cursor_own.index == 0,
1681 regions.inv(),
1682 cursor_own.list_own.list.len() == n - k,
1683 0 <= k <= n,
1684 forall|j: int|
1686 #![trigger cursor_own.list_own.list[j]]
1687 0 <= j < n - k ==> cursor_own.list_own.list[j] == original_list[j + k],
1688 forall|j: int|
1690 #![trigger original_list[j]]
1691 0 <= j < k ==> {
1692 let idx = frame_to_index(meta_to_frame(original_list[j].paddr));
1693 regions.frame_obligations.count(idx) == 0
1694 },
1695 forall|idx: usize|
1697 #![trigger regions.slot_owners[idx]]
1698 (forall|j: int|
1699 #![trigger original_list[j]]
1700 0 <= j < n ==> idx != frame_to_index(meta_to_frame(original_list[j].paddr)))
1701 ==> {
1702 &&& regions.frame_obligations.count(idx)
1703 == original_regions.frame_obligations.count(idx)
1704 &&& regions.slot_owners[idx].usage
1705 == original_regions.slot_owners[idx].usage
1706 &&& regions.slot_owners[idx].self_addr
1707 == original_regions.slot_owners[idx].self_addr
1708 &&& regions.slot_owners[idx].paths_in_pt
1709 == original_regions.slot_owners[idx].paths_in_pt
1710 },
1711 regions.slots.dom() =~= original_regions.slots.dom(),
1712 forall|j: int|
1714 #![trigger original_list[j]]
1715 k <= j < n ==> {
1716 let idx = frame_to_index(meta_to_frame(original_list[j].paddr));
1717 &&& regions.frame_obligations.count(idx)
1718 == original_regions.frame_obligations.count(idx)
1719 &&& regions.slot_owners[idx].paths_in_pt
1720 == original_regions.slot_owners[idx].paths_in_pt
1721 },
1722 forall|j: int|
1724 #![trigger original_list[j]]
1725 k <= j < n ==> regions.slot_owners.contains_key(
1726 frame_to_index(meta_to_frame(original_list[j].paddr)),
1727 ),
1728 forall|i: int, j: int|
1730 #![trigger original_list[i], original_list[j]]
1731 0 <= i < j < n ==> frame_to_index(meta_to_frame(original_list[i].paddr))
1732 != frame_to_index(meta_to_frame(original_list[j].paddr)),
1733 forall|j: int|
1734 #![trigger original_list[j]]
1735 0 <= j < n ==> {
1736 let idx = frame_to_index(meta_to_frame(original_list[j].paddr));
1737 &&& original_regions.slot_owners.contains_key(idx)
1738 &&& original_regions.slots.contains_key(idx)
1739 &&& original_regions.frame_obligations.count(idx) == 0
1740 &&& original_regions.slot_owners[idx].paths_in_pt.is_empty()
1741 &&& original_regions.slot_owners[idx].inner_perms.ref_count.value()
1742 == crate::specs::mm::frame::meta_owners::REF_COUNT_UNIQUE
1743 },
1744 ensures
1745 k == n,
1746 cursor_own.list_own.list.len() == 0,
1747 decreases n - k,
1748 {
1749 proof {
1750 if cursor.current.is_some() {
1751 assert(cursor_own.length() > 0);
1752 let _ = cursor_own.list_own.list[0];
1753 cursor_own.list_own.relate_region_at_facts(*regions, 0);
1754 let ghost _trigger = original_list[k as int];
1755 assert(cursor.current.unwrap().addr() == original_list[k].paddr);
1756 }
1757 }
1758
1759 #[verus_spec(with Tracked(regions), Tracked(&mut cursor_own))]
1760 let entry = cursor.take_current();
1761
1762 if let Some(current) = entry {
1763 let ghost cur_addr = current.0.ptr.addr();
1764 let ghost cur_idx = frame_to_index(meta_to_frame(cur_addr));
1765
1766 let (mut frame, frame_own_tracked) = current;
1767 let tracked frame_own = frame_own_tracked.get();
1768
1769 proof {
1770 let ghost _trig = original_list[k as int];
1771 assert(cur_addr == original_list[k].paddr);
1772 assert(cur_idx == frame_to_index(meta_to_frame(original_list[k].paddr)));
1773 assert(original_regions.frame_obligations.count(cur_idx) == 0);
1774 assert(original_regions.slot_owners[cur_idx].paths_in_pt.is_empty());
1775 assert(regions.slot_owners[cur_idx].paths_in_pt.is_empty());
1776 assert(frame_own.slot_index == cur_idx);
1777 assert(regions.frame_obligations.count(cur_idx) == 1);
1780 }
1781
1782 let ghost regions_pre_drop = *regions;
1783
1784 #[verus_spec(with Tracked(frame_own), Tracked(regions))]
1786 frame.drop();
1787
1788 proof {
1789 assert forall|i: int|
1790 #![trigger cursor_own.list_own.list[i]]
1791 0 <= i < cursor_own.list_own.list.len() implies ({
1792 let idx = cursor_own.list_own.slot_index_at(i);
1793 &&& regions.slot_owners.contains_key(idx)
1794 &&& regions.slot_owners[idx] == regions_pre_drop.slot_owners[idx]
1795 &&& regions.frame_obligations.count(idx)
1796 == regions_pre_drop.frame_obligations.count(idx)
1797 }) by {
1798 let idx = cursor_own.list_own.slot_index_at(i);
1799 let _ = cursor_own.list_own.list[i];
1800 let ghost _trig_k = original_list[k as int];
1801 let ghost _trig_ik = original_list[i + k + 1];
1802 assert(cursor_own.list_own.list[i] == original_list[i + k + 1]);
1803 assert(idx == frame_to_index(
1804 meta_to_frame(original_list[i + k + 1].paddr),
1805 ));
1806 assert(idx != cur_idx);
1807
1808 cursor_own.list_own.relate_region_at_facts(regions_pre_drop, i);
1809 assert(regions.frame_obligations
1810 =~= regions_pre_drop.frame_obligations.remove(cur_idx));
1811 };
1812 cursor_own.list_own.relate_region_preserved_external_change(
1813 regions_pre_drop,
1814 *regions,
1815 );
1816
1817 assert forall|j: int|
1818 #![trigger cursor_own.list_own.list[j]]
1819 0 <= j < n - k - 1 implies cursor_own.list_own.list[j] == original_list[j
1820 + k + 1] by {};
1821
1822 assert forall|j: int| #![trigger original_list[j]] 0 <= j < k implies ({
1823 let idx = frame_to_index(meta_to_frame(original_list[j].paddr));
1824 regions.frame_obligations.count(idx) == 0
1825 }) by {
1826 let idx = frame_to_index(meta_to_frame(original_list[j].paddr));
1827 let ghost _a = original_list[j as int];
1828 let ghost _b = original_list[k as int];
1829 assert(j < k);
1830 assert(idx != cur_idx);
1831 };
1832
1833 k = k + 1;
1834 }
1835 } else {
1836 break;
1837 }
1838 }
1839
1840 proof {
1843 let tracked mut final_list_own = cursor_own.list_own;
1844 vstd::modes::tracked_swap(&mut s.0, &mut final_list_own);
1845 final_list_own.tracked_destroy_empty();
1846 }
1847 }
1848}
1849
1850impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Deref for Link<M> {
1851 type Target = M;
1852
1853 fn deref(&self) -> &Self::Target {
1854 &self.meta
1855 }
1856}
1857
1858impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> DerefMut for Link<M> {
1859 fn deref_mut(&mut self) -> &mut Self::Target {
1860 &mut self.meta
1861 }
1862}
1863
1864impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> Link<M> {
1865 pub const fn new(meta: M) -> Self {
1867 Self { next: None, prev: None, meta }
1868 }
1869}
1870
1871unsafe impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> AnyFrameMeta for Link<M> {
1874 open spec fn on_drop_pre(
1875 &self,
1876 reader: crate::mm::VmReader<'_, crate::mm::Infallible>,
1877 regions: crate::specs::mm::frame::meta_region_owners::MetaRegionOwners,
1878 vm_io_owner: crate::specs::mm::io::VmIoOwner,
1879 ) -> bool {
1880 self.meta.on_drop_pre(reader, regions, vm_io_owner)
1881 }
1882
1883 fn on_drop(
1884 &mut self,
1885 reader: &mut crate::mm::VmReader<crate::mm::Infallible>,
1886 regions: Tracked<&mut crate::specs::mm::frame::meta_region_owners::MetaRegionOwners>,
1887 vm_io_owner: Tracked<&mut crate::specs::mm::io::VmIoOwner>,
1888 ) {
1889 self.meta.on_drop(reader, regions, vm_io_owner);
1890 }
1891
1892 fn is_untyped(&self) -> bool {
1893 self.meta.is_untyped()
1894 }
1895
1896 uninterp spec fn vtable_ptr(&self) -> usize;
1897}
1898
1899}