1pub mod allocator;
34pub mod linked_list;
35pub mod meta;
36pub mod segment;
37pub mod unique;
38pub mod untyped;
39
40mod frame_ref;
41
42#[cfg(ktest)]
43mod test;
44
45use vstd::atomic::PermissionU64;
46use vstd::prelude::*;
47use vstd::simple_pptr::{self, PPtr};
48
49use vstd_extra::cast_ptr;
50
51use core::{
52 marker::PhantomData,
53 sync::atomic::{AtomicUsize, Ordering},
54};
55
56use meta::REF_COUNT_UNUSED;
58pub use segment::Segment;
59
60use crate::specs::arch::kspace::FRAME_METADATA_RANGE;
62pub use frame_ref::FrameRef;
63pub use linked_list::{CursorMut, Link, LinkedList};
64pub use meta::mapping::{
65 frame_to_index, frame_to_index_spec, frame_to_meta, meta_addr, meta_to_frame, META_SLOT_SIZE,
66};
67pub use meta::{has_safe_slot, AnyFrameMeta, GetFrameError, MetaSlot};
68pub use unique::UniqueFrame;
69pub use untyped::{AnyUFrameMeta, UFrame};
70
71use crate::mm::page_table::{PageTableConfig, PageTablePageMeta};
72
73use vstd_extra::cast_ptr::*;
74use vstd_extra::drop_tracking::*;
75use vstd_extra::ownership::*;
76
77use crate::mm::{
78 kspace::{LINEAR_MAPPING_BASE_VADDR, VMALLOC_BASE_VADDR},
79 Paddr, PagingLevel, Vaddr, MAX_PADDR,
80};
81use crate::specs::arch::mm::{MAX_NR_PAGES, PAGE_SIZE};
82use crate::specs::mm::frame::frame_specs::*;
83use crate::specs::mm::frame::meta_owners::*;
84use crate::specs::mm::frame::meta_region_owners::MetaRegionOwners;
85use crate::mm::page_table::RCClone;
86
87verus! {
88
89#[verifier::external_body]
90fn acquire_fence() {
91 core::sync::atomic::fence(Ordering::Acquire);
92}
93
94#[repr(transparent)]
104pub struct Frame<M: AnyFrameMeta> {
105 pub ptr: PPtr<MetaSlot>,
106 pub _marker: PhantomData<M>,
107}
108
109impl<M: AnyFrameMeta> TrackDrop for Frame<M> {
116 type State = MetaRegionOwners;
117
118 open spec fn constructor_requires(self, s: Self::State) -> bool {
119 &&& s.slot_owners.contains_key(frame_to_index(meta_to_frame(self.ptr.addr())))
120 &&& s.inv()
121 }
122
123 open spec fn constructor_ensures(self, s0: Self::State, s1: Self::State) -> bool {
124 let slot_own = s0.slot_owners[frame_to_index(meta_to_frame(self.ptr.addr()))];
125 &&& s1.slot_owners[frame_to_index(meta_to_frame(self.ptr.addr()))] == MetaSlotOwner {
126 raw_count: (slot_own.raw_count + 1) as usize,
127 ..slot_own
128 }
129 &&& forall|i: usize|
130 #![trigger s1.slot_owners[i]]
131 i != frame_to_index(meta_to_frame(self.ptr.addr())) ==> s1.slot_owners[i]
132 == s0.slot_owners[i]
133 &&& s1.slots =~= s0.slots
134 &&& s1.slot_owners.dom() =~= s0.slot_owners.dom()
135 }
136
137 proof fn constructor_spec(self, tracked s: &mut Self::State) {
138 let meta_addr = self.ptr.addr();
139 let index = frame_to_index(meta_to_frame(meta_addr));
140 let tracked mut slot_own = s.slot_owners.tracked_remove(index);
141 slot_own.raw_count = (slot_own.raw_count + 1) as usize;
142 s.slot_owners.tracked_insert(index, slot_own);
143 }
144
145 open spec fn drop_requires(self, s: Self::State) -> bool {
146 let idx = frame_to_index(meta_to_frame(self.ptr.addr()));
147 let slot_own = s.slot_owners[idx];
148 &&& self.inv()
149 &&& s.inv()
150 &&& s.slots.contains_key(idx)
151 &&& s.slots[idx].pptr() == self.ptr
152 &&& s.slot_owners.contains_key(idx)
153 &&& slot_own.raw_count > 0
154 &&& slot_own.inner_perms.ref_count.value() > 0
155 &&& slot_own.inner_perms.ref_count.value() != REF_COUNT_UNUSED
156 &&& slot_own.inner_perms.ref_count.value() == 1 ==> {
159 &&& slot_own.raw_count == 1
160 &&& slot_own.inner_perms.storage.is_init()
161 &&& slot_own.inner_perms.in_list.value() == 0
162 }
163 }
164
165 open spec fn drop_ensures(self, s0: Self::State, s1: Self::State) -> bool {
166 let slot_own = s0.slot_owners[frame_to_index(meta_to_frame(self.ptr.addr()))];
167 &&& s1.slot_owners[frame_to_index(meta_to_frame(self.ptr.addr()))].raw_count == (
168 slot_own.raw_count - 1) as usize
169 &&& forall|i: usize|
170 #![trigger s1.slot_owners[i]]
171 i != frame_to_index(meta_to_frame(self.ptr.addr())) ==> s1.slot_owners[i]
172 == s0.slot_owners[i]
173 &&& s1.slots =~= s0.slots
174 &&& s1.slot_owners.dom() =~= s0.slot_owners.dom()
175 }
176
177 proof fn drop_tracked(self, tracked s: &mut Self::State) {
178 let index = frame_to_index(meta_to_frame(self.ptr.addr()));
179 let tracked mut slot_own = s.slot_owners.tracked_remove(index);
180 slot_own.raw_count = (slot_own.raw_count - 1) as usize;
181 s.slot_owners.tracked_insert(index, slot_own);
182 }
183}
184
185impl<M: AnyFrameMeta> Inv for Frame<M> {
186 open spec fn inv(self) -> bool {
187 &&& self.ptr.addr() % META_SLOT_SIZE == 0
188 &&& FRAME_METADATA_RANGE.start <= self.ptr.addr() < FRAME_METADATA_RANGE.start
189 + MAX_NR_PAGES * META_SLOT_SIZE
190 }
191}
192
193impl<M: AnyFrameMeta> Frame<M> {
194 pub open spec fn paddr(self) -> usize {
195 meta_to_frame(self.ptr.addr())
196 }
197
198 pub open spec fn index(self) -> usize {
199 frame_to_index(self.paddr())
200 }
201}
202
203#[verus_verify]
204impl<'a, M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> Frame<M> {
205 #[verus_spec(r =>
224 with
225 Tracked(regions): Tracked<&mut MetaRegionOwners>
226 -> perm: Tracked<Option<PointsTo<MetaSlot, Metadata<M>>>>
227 requires
228 old(regions).inv(),
229 old(regions).slots.contains_key(frame_to_index(paddr)),
230 ensures
231 final(regions).inv(),
232 r matches Ok(res) ==> perm@ is Some && MetaSlot::get_from_unused_perm_spec(paddr, metadata, false, res.ptr, perm@.unwrap()),
233 r is Ok ==> MetaSlot::get_from_unused_spec(paddr, false, *old(regions), *final(regions)),
234 !has_safe_slot(paddr) ==> r is Err,
235 )]
236 pub fn from_unused(paddr: Paddr, metadata: M) -> Result<Self, GetFrameError> {
237 #[verus_spec(with Tracked(regions))]
238 let from_unused = MetaSlot::get_from_unused(paddr, metadata, false);
239 if let Err(err) = from_unused {
240 proof_with!(|= Tracked(None));
241 Err(err)
242 } else {
243 let (ptr, Tracked(perm)) = from_unused.unwrap();
244 proof_with!(|= Tracked(Some(perm)));
245 Ok(Self { ptr, _marker: PhantomData })
246 }
247 }
248
249 #[verus_spec(
260 with Tracked(perm) : Tracked<&'a PointsTo<MetaSlot, Metadata<M>>>,
261 requires
262 self.ptr.addr() == perm.addr(),
263 self.ptr == perm.points_to.pptr(),
264 perm.is_init(),
265 perm.wf(&perm.inner_perms),
266 returns
267 perm.value().metadata,
268 )]
269 pub fn meta(&self) -> &'a M {
270 #[verus_spec(with Tracked(&perm.points_to))]
272 let slot = self.slot();
273
274 #[verus_spec(with Tracked(&perm.points_to))]
275 let ptr = slot.as_meta_ptr();
276
277 &ptr.borrow(Tracked(perm)).metadata
278 }
279}
280
281#[verus_verify]
282impl<M: AnyFrameMeta> Frame<M> {
283 #[verus_spec(res =>
302 with Tracked(regions) : Tracked<&mut MetaRegionOwners>,
303 requires
304 old(regions).inv(),
305 old(regions).slots.contains_key(frame_to_index(paddr)),
306 !MetaSlot::get_from_in_use_panic_cond(paddr, *old(regions)),
307 ensures
308 final(regions).inv(),
309 res is Ok ==>
310 final(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value() ==
311 old(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value() + 1,
312 res matches Ok(res) ==>
313 res.ptr == old(regions).slots[frame_to_index(paddr)].pptr(),
314 !has_safe_slot(paddr) ==> res is Err,
315 forall|i: usize|
316 #![trigger final(regions).slot_owners[i]]
317 i != frame_to_index(paddr) ==> final(regions).slot_owners[i] == old(regions).slot_owners[i]
318 )]
319 pub fn from_in_use(paddr: Paddr) -> Result<Self, GetFrameError> {
320 Ok(Self {
321 ptr: (#[verus_spec(with Tracked(regions))] MetaSlot::get_from_in_use(paddr))?,
322 _marker: PhantomData
323 })
324 }
325}
326
327#[verus_verify]
328impl<'a, M: AnyFrameMeta> Frame<M> {
329 #[verus_spec(
331 with Tracked(perm): Tracked<&vstd::simple_pptr::PointsTo<MetaSlot>>
332 )]
333 pub fn start_paddr(&self) -> Paddr
334 requires
335 perm.addr() == self.ptr.addr(),
336 perm.is_init(),
337 FRAME_METADATA_RANGE.start <= perm.addr() < FRAME_METADATA_RANGE.end,
338 perm.addr() % META_SLOT_SIZE == 0,
339 returns
340 meta_to_frame(self.ptr.addr()),
341 {
342 #[verus_spec(with Tracked(perm))]
343 let slot = self.slot();
344
345 #[verus_spec(with Tracked(perm))]
346 slot.frame_paddr()
347 }
348
349 #[verus_spec(
356 with Tracked(regions): Tracked<&MetaRegionOwners>
357 )]
358 pub fn eq(&self, other: &Self) -> (res: bool)
359 requires
360 self.inv(),
361 other.inv(),
362 regions.inv(),
363 regions.slots.contains_key(frame_to_index(meta_to_frame(self.ptr.addr()))),
364 regions.slots.contains_key(frame_to_index(meta_to_frame(other.ptr.addr()))),
365 regions.slots[frame_to_index(meta_to_frame(self.ptr.addr()))].pptr() == self.ptr,
366 regions.slots[frame_to_index(meta_to_frame(other.ptr.addr()))].pptr() == other.ptr,
367 ensures
368 res == (meta_to_frame(self.ptr.addr()) == meta_to_frame(other.ptr.addr())),
369 {
370 let ghost self_idx = frame_to_index(meta_to_frame(self.ptr.addr()));
371 let ghost other_idx = frame_to_index(meta_to_frame(other.ptr.addr()));
372 let tracked self_perm = regions.slots.tracked_borrow(self_idx);
373 let tracked other_perm = regions.slots.tracked_borrow(other_idx);
374
375 (#[verus_spec(with Tracked(self_perm))] self.start_paddr() ==
376 #[verus_spec(with Tracked(other_perm))] other.start_paddr())
377 }
378
379 pub const fn map_level(&self) -> PagingLevel {
387 1
388 }
389
390 pub const fn size(&self) -> usize {
392 PAGE_SIZE
393 }
394
395 #[verus_spec(
419 with Tracked(slot_own): Tracked<&mut MetaSlotOwner>,
420 Tracked(perm) : Tracked<&PointsTo<MetaSlot, Metadata<M>>>
421 )]
422 pub fn reference_count(&self) -> u64
423 requires
424 perm.addr() == self.ptr.addr(),
425 perm.points_to.pptr() == self.ptr,
426 perm.is_init(),
427 perm.wf(&perm.inner_perms),
428 perm.inner_perms.ref_count.id() == perm.points_to.value().ref_count.id(),
429 returns
430 perm.value().ref_count,
431 {
432 let refcnt = (#[verus_spec(with Tracked(&perm.points_to))] self.slot()).ref_count.load(Tracked(&perm.inner_perms.ref_count));
433 refcnt
434 }
435
436 #[verus_spec(res =>
446 with Tracked(regions): Tracked<&mut MetaRegionOwners>,
447 Tracked(perm): Tracked<&MetaPerm<M>>,
448 requires
449 old(regions).inv(),
450 old(regions).slot_owners[self.index()].raw_count <= 1,
451 old(regions).slot_owners[self.index()].inner_perms.ref_count.value()
452 != crate::mm::frame::meta::REF_COUNT_UNUSED,
453 old(regions).slot_owners[self.index()].self_addr == self.ptr.addr(),
454 perm.points_to.pptr() == self.ptr,
455 perm.points_to.value().wf(old(regions).slot_owners[self.index()]),
456 perm.is_init(),
457 self.inv(),
458 ensures
459 final(regions).inv(),
460 res.inner@.ptr.addr() == self.ptr.addr(),
461 final(regions).slot_owners[self.index()].raw_count == 1,
463 final(regions).slot_owners[self.index()].inner_perms
465 == old(regions).slot_owners[self.index()].inner_perms,
466 final(regions).slot_owners[self.index()].self_addr
467 == old(regions).slot_owners[self.index()].self_addr,
468 final(regions).slot_owners[self.index()].usage
469 == old(regions).slot_owners[self.index()].usage,
470 final(regions).slot_owners[self.index()].paths_in_pt
471 == old(regions).slot_owners[self.index()].paths_in_pt,
472 forall |i: usize|
474 #![trigger final(regions).slot_owners[i]]
475 i != self.index() ==> final(regions).slot_owners[i]
476 == old(regions).slot_owners[i],
477 final(regions).slot_owners.dom() =~= old(regions).slot_owners.dom(),
478 forall |k: usize| old(regions).slots.contains_key(k) ==> #[trigger] final(regions).slots.contains_key(k),
480 forall |k: usize| old(regions).slots.contains_key(k) && k != self.index()
481 ==> old(regions).slots[k] == #[trigger] final(regions).slots[k],
482 forall |k: usize| k != self.index() ==>
484 (#[trigger] final(regions).slots.contains_key(k) ==> old(regions).slots.contains_key(k)),
485 )]
486 pub fn borrow(&self) -> FrameRef<'a, M> {
487 assert(regions.slot_owners.contains_key(self.index()));
488 broadcast use crate::mm::frame::meta::mapping::group_page_meta;
489
490 unsafe {
492 #[verus_spec(with Tracked(regions), Tracked(perm))]
493 FrameRef::borrow_paddr(#[verus_spec(with Tracked(&perm.points_to))] self.start_paddr())
494 }
495 }
496
497 #[verus_spec(r =>
518 with
519 Tracked(regions): Tracked<&mut MetaRegionOwners>,
520 -> frame_perm: Tracked<MetaPerm<M>>,
521 requires
522 old(regions).inv(),
523 old(regions).slots.contains_key(self.index()),
524 self.inv(),
525 old(regions).slot_owners[self.index()].inner_perms.ref_count.value() != REF_COUNT_UNUSED,
526 ensures
527 final(regions).inv(),
528 r == self.paddr(),
529 frame_perm@.points_to == old(regions).slots[self.index()],
530 final(regions).slot_owners[self.index()].raw_count
531 == (old(regions).slot_owners[self.index()].raw_count + 1) as usize,
532 self.into_raw_post_noninterference(*old(regions), *final(regions)),
533 )]
534 pub(in crate::mm) fn into_raw(self) -> Paddr {
535 broadcast use crate::mm::frame::meta::mapping::group_page_meta;
536
537 let tracked perm = regions.slots.tracked_borrow(self.index());
538
539 assert(perm.addr() == self.ptr.addr()) by {
540 assert(frame_to_meta(meta_to_frame(self.ptr.addr())) == self.ptr.addr());
541 };
542
543 #[verus_spec(with Tracked(perm))]
544 let paddr = self.start_paddr();
545
546 let ghost index = self.index();
547
548 assert(self.constructor_requires(*regions));
549 let _ = ManuallyDrop::new(self, Tracked(regions));
550
551 assert(regions.slots.contains_key(index));
552 let tracked meta_perm = regions.copy_perm::<M>(index);
553
554 proof_with!(|= Tracked(meta_perm));
555 paddr
556 }
557
558 #[verus_spec(r =>
588 with
589 Tracked(regions): Tracked<&mut MetaRegionOwners>,
590 Tracked(perm): Tracked<&MetaPerm<M>>,
591 -> debt: Tracked<BorrowDebt>,
592 requires
593 Self::from_raw_requires_safety(*old(regions), paddr),
594 old(regions).slot_owners[frame_to_index(paddr)].raw_count <= 1,
595 perm.points_to.is_init(),
596 perm.points_to.addr() == frame_to_meta(paddr),
597 perm.points_to.value().wf(old(regions).slot_owners[frame_to_index(paddr)]),
598 ensures
599 Self::from_raw_ensures(*old(regions), *final(regions), paddr, r),
600 final(regions).slots == old(regions).slots.insert(frame_to_index(paddr), perm.points_to),
601 debt@.frame_index == frame_to_index(paddr),
602 debt@.raw_count_at_issue == old(regions).slot_owners[frame_to_index(paddr)].raw_count,
603 )]
604 pub(in crate::mm) fn from_raw(paddr: Paddr) -> Self {
605 let vaddr = frame_to_meta(paddr);
606 let ptr = PPtr::from_addr(vaddr);
607
608 let ghost idx = frame_to_index(paddr);
609 let ghost old_raw_count = regions.slot_owners[idx].raw_count;
610
611 proof {
612 let index = frame_to_index(paddr);
613 regions.sync_perm::<M>(index, perm);
614
615 let tracked mut slot_own = regions.slot_owners.tracked_remove(index);
616 slot_own.raw_count = 0usize;
617 regions.slot_owners.tracked_insert(index, slot_own);
618 }
619
620 proof_with!(|= Tracked(BorrowDebt { frame_index: idx, raw_count_at_issue: old_raw_count }));
621 Self { ptr, _marker: PhantomData }
622 }
623
624 #[verus_spec(
635 with Tracked(slot_perm): Tracked<&'a vstd::simple_pptr::PointsTo<MetaSlot>>
636 )]
637 pub fn slot(&self) -> (slot: &'a MetaSlot)
638 requires
639 slot_perm.pptr() == self.ptr,
640 slot_perm.is_init(),
641 returns
642 slot_perm.value(),
643 {
644 self.ptr.borrow(Tracked(slot_perm))
647 }
648}
649
650#[verus_spec(
664 with Tracked(regions): Tracked<&mut MetaRegionOwners>
665)]
666pub(in crate::mm) fn inc_frame_ref_count(paddr: Paddr)
667 requires
668 old(regions).inv(),
669 old(regions).slots.contains_key(frame_to_index(paddr)),
670 has_safe_slot(paddr),
671 !MetaSlot::inc_ref_count_panic_cond(
672 old(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count,
673 ),
674 old(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value() > 0,
676 old(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value() + 1
678 < REF_COUNT_MAX,
679 ensures
680 final(regions).inv(),
681 final(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value() == old(
682 regions,
683 ).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value() + 1,
684 final(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.id()
685 == old(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.id(),
686 final(regions).slot_owners[frame_to_index(paddr)].inner_perms.storage
687 == old(regions).slot_owners[frame_to_index(paddr)].inner_perms.storage,
688 final(regions).slot_owners[frame_to_index(paddr)].inner_perms.vtable_ptr
689 == old(regions).slot_owners[frame_to_index(paddr)].inner_perms.vtable_ptr,
690 final(regions).slot_owners[frame_to_index(paddr)].inner_perms.in_list
691 == old(regions).slot_owners[frame_to_index(paddr)].inner_perms.in_list,
692 final(regions).slot_owners[frame_to_index(paddr)].paths_in_pt
693 == old(regions).slot_owners[frame_to_index(paddr)].paths_in_pt,
694 final(regions).slot_owners[frame_to_index(paddr)].self_addr
695 == old(regions).slot_owners[frame_to_index(paddr)].self_addr,
696 final(regions).slot_owners[frame_to_index(paddr)].raw_count
697 == old(regions).slot_owners[frame_to_index(paddr)].raw_count,
698 final(regions).slot_owners[frame_to_index(paddr)].usage
699 == old(regions).slot_owners[frame_to_index(paddr)].usage,
700 final(regions).slots =~= old(regions).slots,
701 forall|i: usize|
702 i != frame_to_index(paddr) ==> (#[trigger] final(regions).slot_owners[i] == old(
703 regions,
704 ).slot_owners[i]),
705 final(regions).slot_owners.dom() =~= old(regions).slot_owners.dom(),
706{
707 let tracked mut slot_own = regions.slot_owners.tracked_remove(frame_to_index(paddr));
708 let tracked perm = regions.slots.tracked_borrow(frame_to_index(paddr));
709 let tracked mut inner_perms = slot_own.take_inner_perms();
710
711 let vaddr: Vaddr = frame_to_meta(paddr);
712 let slot = PPtr::<MetaSlot>::from_addr(vaddr);
715
716 #[verus_spec(with Tracked(&mut inner_perms.ref_count))]
717 slot.borrow(Tracked(perm)).inc_ref_count();
718
719 proof {
720 let idx = frame_to_index(paddr);
721
722 assert(inner_perms.ref_count.id()
724 == old(regions).slot_owners[idx].inner_perms.ref_count.id());
725
726 slot_own.sync_inner(&inner_perms);
728
729 assert(slot_own.inv());
731
732 assert(regions.slots[idx].value().wf(slot_own));
734
735 regions.slot_owners.tracked_insert(idx, slot_own);
736 }
737}
738
739pub type DynFrame = Frame<MetaSlotStorage>;
742
743#[verus_verify]
744impl<M: AnyFrameMeta + ?Sized> RCClone for Frame<M> {
745 open spec fn clone_requires(self, perm: MetaRegionOwners) -> bool {
746 let idx = frame_to_index(meta_to_frame(self.ptr.addr()));
747 &&& self.inv()
748 &&& perm.inv()
749 &&& perm.slots.contains_key(idx)
750 &&& perm.slot_owners.contains_key(idx)
751 &&& perm.slot_owners[idx].inner_perms.ref_count.value() > 0
752 &&& perm.slot_owners[idx].inner_perms.ref_count.value() + 1 < meta::REF_COUNT_MAX
753 &&& has_safe_slot(meta_to_frame(self.ptr.addr()))
754 }
755
756 open spec fn clone_ensures(self, old_perm: MetaRegionOwners, new_perm: MetaRegionOwners, res: Self) -> bool {
757 let idx = frame_to_index(meta_to_frame(self.ptr.addr()));
758 &&& new_perm.inv()
759 &&& new_perm.slot_owners[idx].inner_perms.ref_count.value()
761 == old_perm.slot_owners[idx].inner_perms.ref_count.value() + 1
762 &&& new_perm.slot_owners[idx].inner_perms.ref_count.id()
763 == old_perm.slot_owners[idx].inner_perms.ref_count.id()
764 &&& new_perm.slot_owners[idx].inner_perms.storage == old_perm.slot_owners[idx].inner_perms.storage
766 &&& new_perm.slot_owners[idx].inner_perms.vtable_ptr == old_perm.slot_owners[idx].inner_perms.vtable_ptr
767 &&& new_perm.slot_owners[idx].inner_perms.in_list == old_perm.slot_owners[idx].inner_perms.in_list
768 &&& new_perm.slot_owners[idx].paths_in_pt == old_perm.slot_owners[idx].paths_in_pt
769 &&& new_perm.slot_owners[idx].self_addr == old_perm.slot_owners[idx].self_addr
770 &&& new_perm.slot_owners[idx].raw_count == old_perm.slot_owners[idx].raw_count
771 &&& new_perm.slot_owners[idx].usage == old_perm.slot_owners[idx].usage
772 &&& new_perm.slots =~= old_perm.slots
774 &&& forall|i: usize| i != idx ==>
775 (#[trigger] new_perm.slot_owners[i] == old_perm.slot_owners[i])
776 &&& new_perm.slot_owners.dom() =~= old_perm.slot_owners.dom()
777 }
778
779 fn clone(&self, Tracked(perm): Tracked<&mut MetaRegionOwners>) -> Self
780 {
781 let paddr = meta_to_frame(self.ptr.addr());
782
783 #[verus_spec(with Tracked(perm))]
784 inc_frame_ref_count(paddr);
785
786 Self {
787 ptr: PPtr::<MetaSlot>::from_addr(self.ptr.0),
788 _marker: PhantomData,
789 }
790 }
791}
792
793impl<M: AnyFrameMeta> Drop for Frame<M> {
794 fn drop(self, Tracked(regions): Tracked<MetaRegionOwners>) -> (res: Tracked<MetaRegionOwners>)
795 {
796 let tracked mut regions = regions;
797 let ghost idx = frame_to_index(meta_to_frame(self.ptr.addr()));
798 let ghost old_regions = regions;
799
800 let tracked mut slot_own = regions.slot_owners.tracked_remove(idx);
801 let tracked perm = regions.slots.tracked_remove(idx);
802 let slot = self.ptr.borrow(Tracked(&perm));
803
804 proof {
805 assert(slot.ref_count.id() == slot_own.inner_perms.ref_count.id());
806 }
807 let last_ref_cnt = slot.ref_count.fetch_sub(Tracked(&mut slot_own.inner_perms.ref_count), 1);
808
809 proof {
810 slot_own.raw_count = (slot_own.raw_count - 1) as usize;
811 }
812
813 if last_ref_cnt == 1 {
814 acquire_fence();
817
818 proof {
819 assert(slot_own.inner_perms.ref_count.value() == 0u64);
820 assert(slot_own.raw_count == 0);
821 assert(slot_own.inner_perms.storage.is_init());
822 assert(slot_own.inner_perms.in_list.value() == 0u64);
823 assert(slot_own.inv());
824 assert(MetaSlot::drop_last_in_place_safety_cond(slot_own));
825 assert(slot.ref_count.id() == slot_own.inner_perms.ref_count.id());
826 }
827 #[verus_spec(with Tracked(&mut slot_own))]
828 slot.drop_last_in_place();
829
830 }
833
834 proof {
835 regions.slot_owners.tracked_insert(idx, slot_own);
836 regions.slots.tracked_insert(idx, perm);
837
838 assert forall|i: usize| i != idx implies #[trigger] regions.slot_owners[i] == old_regions.slot_owners[i] by {}
839 assert(regions.slots =~= old_regions.slots);
840 assert(regions.slot_owners.dom() =~= old_regions.slot_owners.dom());
841 }
842
843 Tracked(regions)
844 }
845}
846
847} impl<M: AnyUFrameMeta> From<Frame<M>> for UFrame {
898 fn from(frame: Frame<M>) -> Self {
899 unsafe { core::mem::transmute(frame) }
901 }
902}