1use vstd::prelude::*;
46use vstd_extra::{cast_ptr::Repr, ownership::*, set_extra::lemma_finite_int_set_has_unused};
47
48use crate::specs::{
49 arch::valid_frame_paddr,
50 mm::frame::{
51 linked_list::linked_list_owners::*,
52 mapping::{frame_to_index, meta_to_index},
53 meta_owners::{MetadataPerm, PageUsage},
54 meta_region_owners::MetaRegionOwners,
55 unique::UniqueFrameOwner,
56 },
57};
58
59use crate::mm::{
60 Paddr,
61 frame::{
62 AnyFrameMeta, Link,
63 meta::{REF_COUNT_UNIQUE, REF_COUNT_UNUSED},
64 },
65};
66
67verus! {
68
69pub type ListId = int;
71
72pub type LooseId = int;
75
76pub type CursorId = ListId;
81
82pub open spec fn list_registry_ok<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
94 regions: MetaRegionOwners,
95 lo: LinkedListOwner<M>,
96) -> bool {
97 &&& forall|i: int|
98 #![trigger meta_to_index(lo.list[i].slot_vaddr)]
99 0 <= i < lo.list.len() ==> regions.slot_owners[meta_to_index(
100 lo.list[i].slot_vaddr,
101 )].in_list_perm.value() == lo.list_id
102 &&& lo.list_id != 0 ==> forall|idx: int|
103 #![trigger regions.slot_owners[idx]]
104 regions.contains(idx) && regions.slot_owners[idx].in_list_perm.value() == lo.list_id
105 ==> exists|i: int|
106 0 <= i < lo.list.len() && #[trigger] meta_to_index(lo.list[i].slot_vaddr) == idx
107}
108
109pub tracked struct ListStore<M: AnyFrameMeta + Repr<MetaSlotSmall>> {
118 pub regions: MetaRegionOwners,
119 pub lists: Map<ListId, LinkedListOwner<M>>,
120 pub loose: Map<LooseId, UniqueFrameOwner<Link<M>>>,
121 pub cursors: Map<CursorId, CursorOwner<M>>,
122}
123
124impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> ListStore<M> {
125 pub open spec fn inv(self) -> bool {
127 &&& self.regions.inv()
128 &&& forall|id: ListId| #[trigger]
131 self.lists.dom().contains(id) ==> {
132 &&& self.lists[id].inv()
133 &&& self.lists[id].relate_region(self.regions)
134 }
135 &&& forall|lid: LooseId| #[trigger]
136 self.loose.dom().contains(lid) ==> {
137 &&& self.loose[lid].inv()
138 &&& self.loose[lid].global_inv(self.regions)
139 &&& self.loose[lid].frame_link_inv(self.regions)
140 }
141 &&& forall|id1: ListId, id2: ListId|
143 #![trigger self.lists.dom().contains(id1), self.lists.dom().contains(id2)]
144 self.lists.dom().contains(id1) && self.lists.dom().contains(id2)
145 && self.lists[id1].list_id == self.lists[id2].list_id && self.lists[id1].list_id
146 != 0 ==> id1
147 == id2
148 &&& forall|lid1: LooseId, lid2: LooseId|
151 #![trigger self.loose.dom().contains(lid1), self.loose.dom().contains(lid2)]
152 self.loose.dom().contains(lid1) && self.loose.dom().contains(lid2)
153 && self.loose[lid1].slot_index == self.loose[lid2].slot_index ==> lid1
154 == lid2
155 &&& self.lists.dom().disjoint(
159 self.cursors.dom(),
160 )
161 &&& forall|cid: CursorId| #[trigger]
164 self.cursors.dom().contains(cid) ==> {
165 &&& self.cursors[cid].list_own.inv()
166 &&& self.cursors[cid].wf_with_region(self.regions)
167 }
168 &&& forall|id: ListId, cid: CursorId|
171 #![trigger self.lists.dom().contains(id), self.cursors.dom().contains(cid)]
172 self.lists.dom().contains(id) && self.cursors.dom().contains(cid)
173 && self.lists[id].list_id == self.cursors[cid].list_own.list_id
174 && self.lists[id].list_id != 0
175 ==> false
176 &&& forall|cid1: CursorId, cid2: CursorId|
178 #![trigger self.cursors.dom().contains(cid1), self.cursors.dom().contains(cid2)]
179 self.cursors.dom().contains(cid1) && self.cursors.dom().contains(cid2)
180 && self.cursors[cid1].list_own.list_id == self.cursors[cid2].list_own.list_id
181 && self.cursors[cid1].list_own.list_id != 0 ==> cid1
182 == cid2
183 &&& forall|id: ListId| #[trigger]
186 self.lists.dom().contains(id) ==> list_registry_ok(
187 self.regions,
188 self.lists[id],
189 )
190 &&& forall|cid: CursorId| #[trigger]
192 self.cursors.dom().contains(cid) ==> list_registry_ok(
193 self.regions,
194 self.cursors[cid].list_own,
195 )
196 }
197}
198
199pub proof fn tracked_empty_list_owner<M: AnyFrameMeta + Repr<MetaSlotSmall>>() -> (tracked res:
204 LinkedListOwner<M>)
205 ensures
206 res.list =~= Seq::<LinkOwner>::empty(),
207 res.repr_perms =~= Seq::<LinkInnerPerms<M>>::empty(),
208 res.metadata_perms =~= Seq::<MetadataPerm>::empty(),
209 res.list_id == 0,
210{
211 let tracked list = Seq::<LinkOwner>::tracked_empty();
212 let tracked repr_perms = Seq::<LinkInnerPerms<M>>::tracked_empty();
213 let tracked metadata_perms = Seq::<MetadataPerm>::tracked_empty();
214 let tracked res = LinkedListOwner::<M> {
215 list,
216 repr_perms,
217 metadata_perms,
218 list_id: 0,
219 _marker: core::marker::PhantomData,
220 };
221 res
222}
223
224pub open spec fn fresh_list_id<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
226 lists: Map<ListId, LinkedListOwner<M>>,
227 cursors: Map<CursorId, CursorOwner<M>>,
228) -> ListId {
229 choose|id: ListId| !lists.dom().contains(id) && !cursors.dom().contains(id)
230}
231
232pub proof fn lemma_fresh_list_id_not_in_dom<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
233 lists: Map<ListId, LinkedListOwner<M>>,
234 cursors: Map<CursorId, CursorOwner<M>>,
235)
236 ensures
237 !lists.dom().contains(fresh_list_id(lists, cursors)) && !cursors.dom().contains(
238 fresh_list_id(lists, cursors),
239 ),
240{
241 lemma_finite_int_set_has_unused(lists.dom() + cursors.dom());
242}
243
244pub proof fn push_front_embedded<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
246 tracked regions: &mut MetaRegionOwners,
247 tracked owner: &mut LinkedListOwner<M>,
248 tracked frame_own: &mut UniqueFrameOwner<Link<M>>,
249 used_ids: Set<u64>,
250)
251 requires
252 old(regions).inv(),
253 old(owner).inv(),
254 old(owner).relate_region(*old(regions)),
255 old(frame_own).inv(),
256 old(frame_own).global_inv(*old(regions)),
257 old(frame_own).frame_link_inv(*old(regions)),
258 ensures
259 final(regions).inv(),
260 final(owner).inv(),
261 final(owner).relate_region(*final(regions)),
262 final(owner).list == old(owner).list.insert(0, final(frame_own).meta_own),
263 old(owner).list_id != 0 ==> final(owner).list_id == old(owner).list_id,
264 final(owner).list_id != 0,
265 old(owner).list_id == 0 ==> !used_ids.contains(final(owner).list_id),
266 final(frame_own).meta_own.slot_vaddr == old(frame_own).meta_own.slot_vaddr,
267 final(frame_own).meta_own.in_list == final(owner).list_id,
268 forall|k: int|
269 #![trigger final(regions).slots[k]]
270 #![trigger final(regions).slot_owners[k]]
271 k != old(frame_own).slot_index && (old(owner).list.len() > 0 ==> k != meta_to_index(
272 old(owner).list[0].slot_vaddr,
273 )) ==> final(regions).slots[k] == old(regions).slots[k] && final(regions).slot_owners[k]
274 == old(regions).slot_owners[k],
275 forall|l: LinkedListOwner<M>|
276 #![trigger l.relate_region(*old(regions))]
277 l.inv() && l.relate_region(*old(regions)) && l.list_id != final(owner).list_id
278 ==> l.relate_region(*final(regions)),
279 list_registry_ok(*final(regions), *final(owner)),
280 forall|l: LinkedListOwner<M>|
281 #![trigger l.relate_region(*old(regions))]
282 l.inv() && l.relate_region(*old(regions)) && list_registry_ok(*old(regions), l)
283 && l.list_id != final(owner).list_id ==> list_registry_ok(*final(regions), l),
284 forall|fo: UniqueFrameOwner<Link<M>>|
285 #![trigger fo.global_inv(*old(regions))]
286 fo.global_inv(*old(regions)) && fo.frame_link_inv(*old(regions)) && old(
287 regions,
288 ).slot_owners[fo.slot_index].in_list_perm.value() == 0 && fo.slot_index != old(
289 frame_own,
290 ).slot_index ==> fo.global_inv(*final(regions)) && fo.frame_link_inv(*final(regions))
291 && final(regions).slot_owners[fo.slot_index].in_list_perm.value() == 0,
292{
293 axiom_insert_before_at_embedded(regions, owner, frame_own, 0, used_ids);
294}
295
296pub open spec fn fresh_loose_id<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
298 m: Map<LooseId, UniqueFrameOwner<Link<M>>>,
299) -> LooseId {
300 choose|id: LooseId| !m.dom().contains(id)
301}
302
303pub proof fn tracked_pop_front_embedded<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
306 tracked regions: &mut MetaRegionOwners,
307 tracked owner: &mut LinkedListOwner<M>,
308) -> (tracked frame_own: UniqueFrameOwner<Link<M>>)
309 requires
310 old(regions).inv(),
311 old(owner).inv(),
312 old(owner).relate_region(*old(regions)),
313 old(owner).list.len() > 0,
314 ensures
315 final(regions).inv(),
316 final(owner).inv(),
317 final(owner).relate_region(*final(regions)),
318 final(owner).list == old(owner).list.remove(0),
319 final(owner).list_id == old(owner).list_id,
320 frame_own.inv(),
322 frame_own.global_inv(*final(regions)),
323 frame_own.frame_link_inv(*final(regions)),
324 frame_own.slot_index == meta_to_index(old(owner).list[0].slot_vaddr),
325 final(regions).slot_owners[frame_own.slot_index].in_list_perm.value() == 0,
326 forall|j: int|
327 #![trigger final(regions).slots[j]]
328 #![trigger final(regions).slot_owners[j]]
329 j != meta_to_index(old(owner).list[0].slot_vaddr) && (old(owner).list.len() > 1 ==> j
330 != meta_to_index(old(owner).list[1].slot_vaddr)) ==> final(regions).slots[j] == old(
331 regions,
332 ).slots[j] && final(regions).slot_owners[j] == old(regions).slot_owners[j],
333 forall|l: LinkedListOwner<M>|
335 #![trigger l.relate_region(*old(regions))]
336 l.inv() && l.relate_region(*old(regions)) && l.list_id != final(owner).list_id
337 ==> l.relate_region(*final(regions)),
338 list_registry_ok(*final(regions), *final(owner)),
339 forall|l: LinkedListOwner<M>|
340 #![trigger l.relate_region(*old(regions))]
341 l.inv() && l.relate_region(*old(regions)) && list_registry_ok(*old(regions), l)
342 && l.list_id != final(owner).list_id ==> list_registry_ok(*final(regions), l),
343 forall|fo: UniqueFrameOwner<Link<M>>|
344 #![trigger fo.global_inv(*old(regions))]
345 fo.global_inv(*old(regions)) && fo.frame_link_inv(*old(regions)) && old(
346 regions,
347 ).slot_owners[fo.slot_index].in_list_perm.value() == 0 ==> fo.global_inv(
348 *final(regions),
349 ) && fo.frame_link_inv(*final(regions))
350 && final(regions).slot_owners[fo.slot_index].in_list_perm.value() == 0
351 && fo.slot_index != meta_to_index(old(owner).list[0].slot_vaddr),
352{
353 let tracked frame_own = axiom_take_at_embedded(regions, owner, 0);
354 frame_own
355}
356
357pub proof fn lemma_push_back_embedded<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
360 tracked regions: &mut MetaRegionOwners,
361 tracked owner: &mut LinkedListOwner<M>,
362 tracked frame_own: &mut UniqueFrameOwner<Link<M>>,
363 used_ids: Set<u64>,
364)
365 requires
366 old(regions).inv(),
367 old(owner).inv(),
368 old(owner).relate_region(*old(regions)),
369 old(frame_own).inv(),
370 old(frame_own).global_inv(*old(regions)),
371 old(frame_own).frame_link_inv(*old(regions)),
372 ensures
373 final(regions).inv(),
374 final(owner).inv(),
375 final(owner).relate_region(*final(regions)),
376 final(owner).list == old(owner).list.insert(
377 old(owner).list.len() as int,
378 final(frame_own).meta_own,
379 ),
380 old(owner).list_id != 0 ==> final(owner).list_id == old(owner).list_id,
381 final(owner).list_id != 0,
382 old(owner).list_id == 0 ==> !used_ids.contains(final(owner).list_id),
383 final(frame_own).meta_own.slot_vaddr == old(frame_own).meta_own.slot_vaddr,
384 final(frame_own).meta_own.in_list == final(owner).list_id,
385 forall|k: int|
386 #![trigger final(regions).slots[k]]
387 #![trigger final(regions).slot_owners[k]]
388 k != old(frame_own).slot_index && (old(owner).list.len() > 0 ==> k != meta_to_index(
389 old(owner).list[old(owner).list.len() - 1].slot_vaddr,
390 )) ==> final(regions).slots[k] == old(regions).slots[k] && final(regions).slot_owners[k]
391 == old(regions).slot_owners[k],
392 forall|l: LinkedListOwner<M>|
393 #![trigger l.relate_region(*old(regions))]
394 l.inv() && l.relate_region(*old(regions)) && l.list_id != final(owner).list_id
395 ==> l.relate_region(*final(regions)),
396 list_registry_ok(*final(regions), *final(owner)),
397 forall|l: LinkedListOwner<M>|
398 #![trigger l.relate_region(*old(regions))]
399 l.inv() && l.relate_region(*old(regions)) && list_registry_ok(*old(regions), l)
400 && l.list_id != final(owner).list_id ==> list_registry_ok(*final(regions), l),
401 forall|fo: UniqueFrameOwner<Link<M>>|
402 #![trigger fo.global_inv(*old(regions))]
403 fo.global_inv(*old(regions)) && fo.frame_link_inv(*old(regions)) && old(
404 regions,
405 ).slot_owners[fo.slot_index].in_list_perm.value() == 0 && fo.slot_index != old(
406 frame_own,
407 ).slot_index ==> fo.global_inv(*final(regions)) && fo.frame_link_inv(*final(regions))
408 && final(regions).slot_owners[fo.slot_index].in_list_perm.value() == 0,
409{
410 let ghost n = owner.list.len() as int;
411 axiom_insert_before_at_embedded(regions, owner, frame_own, n, used_ids);
412}
413
414pub proof fn tracked_pop_back_embedded<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
417 tracked regions: &mut MetaRegionOwners,
418 tracked owner: &mut LinkedListOwner<M>,
419) -> (tracked frame_own: UniqueFrameOwner<Link<M>>)
420 requires
421 old(regions).inv(),
422 old(owner).inv(),
423 old(owner).relate_region(*old(regions)),
424 old(owner).list.len() > 0,
425 ensures
426 final(regions).inv(),
427 final(owner).inv(),
428 final(owner).relate_region(*final(regions)),
429 final(owner).list == old(owner).list.remove(old(owner).list.len() - 1),
430 final(owner).list_id == old(owner).list_id,
431 frame_own.inv(),
432 frame_own.global_inv(*final(regions)),
433 frame_own.frame_link_inv(*final(regions)),
434 frame_own.slot_index == meta_to_index(
435 old(owner).list[old(owner).list.len() - 1].slot_vaddr,
436 ),
437 final(regions).slot_owners[frame_own.slot_index].in_list_perm.value() == 0,
438 forall|j: int|
439 #![trigger final(regions).slots[j]]
440 #![trigger final(regions).slot_owners[j]]
441 j != meta_to_index(old(owner).list[old(owner).list.len() - 1].slot_vaddr) && (old(
442 owner,
443 ).list.len() > 1 ==> j != meta_to_index(
444 old(owner).list[old(owner).list.len() - 2].slot_vaddr,
445 )) ==> final(regions).slots[j] == old(regions).slots[j] && final(regions).slot_owners[j]
446 == old(regions).slot_owners[j],
447 forall|l: LinkedListOwner<M>|
448 #![trigger l.relate_region(*old(regions))]
449 l.inv() && l.relate_region(*old(regions)) && l.list_id != final(owner).list_id
450 ==> l.relate_region(*final(regions)),
451 list_registry_ok(*final(regions), *final(owner)),
452 forall|l: LinkedListOwner<M>|
453 #![trigger l.relate_region(*old(regions))]
454 l.inv() && l.relate_region(*old(regions)) && list_registry_ok(*old(regions), l)
455 && l.list_id != final(owner).list_id ==> list_registry_ok(*final(regions), l),
456 forall|fo: UniqueFrameOwner<Link<M>>|
457 #![trigger fo.global_inv(*old(regions))]
458 fo.global_inv(*old(regions)) && fo.frame_link_inv(*old(regions)) && old(
459 regions,
460 ).slot_owners[fo.slot_index].in_list_perm.value() == 0 ==> fo.global_inv(
461 *final(regions),
462 ) && fo.frame_link_inv(*final(regions))
463 && final(regions).slot_owners[fo.slot_index].in_list_perm.value() == 0
464 && fo.slot_index != meta_to_index(
465 old(owner).list[old(owner).list.len() - 1].slot_vaddr,
466 ),
467{
468 let ghost n = owner.list.len() - 1;
469 let tracked frame_own = axiom_take_at_embedded(regions, owner, n);
470 frame_own
471}
472
473pub axiom fn axiom_insert_before_at_embedded<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
475 tracked regions: &mut MetaRegionOwners,
476 tracked owner: &mut LinkedListOwner<M>,
477 tracked frame_own: &mut UniqueFrameOwner<Link<M>>,
478 n: int,
479 used_ids: Set<u64>,
480)
481 requires
482 old(regions).inv(),
483 old(owner).inv(),
484 old(owner).relate_region(*old(regions)),
485 old(frame_own).inv(),
486 old(frame_own).global_inv(*old(regions)),
487 old(frame_own).frame_link_inv(*old(regions)),
488 0 <= n <= old(owner).list.len(),
489 ensures
490 final(regions).inv(),
491 final(owner).inv(),
492 final(owner).relate_region(*final(regions)),
493 final(owner).list == old(owner).list.insert(n, final(frame_own).meta_own),
494 old(owner).list_id != 0 ==> final(owner).list_id == old(owner).list_id,
495 final(owner).list_id != 0,
496 old(owner).list_id == 0 ==> !used_ids.contains(final(owner).list_id),
497 final(frame_own).meta_own.slot_vaddr == old(frame_own).meta_own.slot_vaddr,
498 final(frame_own).meta_own.in_list == final(owner).list_id,
499 forall|k: int|
500 #![trigger final(regions).slots[k]]
501 #![trigger final(regions).slot_owners[k]]
502 k != old(frame_own).slot_index && (n > 0 ==> k != meta_to_index(
503 old(owner).list[n - 1].slot_vaddr,
504 )) && (n < old(owner).list.len() ==> k != meta_to_index(old(owner).list[n].slot_vaddr))
505 ==> final(regions).slots[k] == old(regions).slots[k]
506 && final(regions).slot_owners[k] == old(regions).slot_owners[k],
507 forall|l: LinkedListOwner<M>|
508 #![trigger l.relate_region(*old(regions))]
509 l.inv() && l.relate_region(*old(regions)) && l.list_id != final(owner).list_id
510 ==> l.relate_region(*final(regions)),
511 list_registry_ok(*final(regions), *final(owner)),
512 forall|l: LinkedListOwner<M>|
513 #![trigger l.relate_region(*old(regions))]
514 l.inv() && l.relate_region(*old(regions)) && list_registry_ok(*old(regions), l)
515 && l.list_id != final(owner).list_id ==> list_registry_ok(*final(regions), l),
516 forall|fo: UniqueFrameOwner<Link<M>>|
517 #![trigger fo.global_inv(*old(regions))]
518 fo.global_inv(*old(regions)) && fo.frame_link_inv(*old(regions)) && old(
519 regions,
520 ).slot_owners[fo.slot_index].in_list_perm.value() == 0 && fo.slot_index != old(
521 frame_own,
522 ).slot_index ==> fo.global_inv(*final(regions)) && fo.frame_link_inv(*final(regions))
523 && final(regions).slot_owners[fo.slot_index].in_list_perm.value() == 0,
524;
525
526pub axiom fn axiom_take_at_embedded<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
528 tracked regions: &mut MetaRegionOwners,
529 tracked owner: &mut LinkedListOwner<M>,
530 n: int,
531) -> (tracked frame_own: UniqueFrameOwner<Link<M>>)
532 requires
533 old(regions).inv(),
534 old(owner).inv(),
535 old(owner).relate_region(*old(regions)),
536 0 <= n < old(owner).list.len(),
537 ensures
538 final(regions).inv(),
539 final(owner).inv(),
540 final(owner).relate_region(*final(regions)),
541 final(owner).list == old(owner).list.remove(n),
542 final(owner).list_id == old(owner).list_id,
543 frame_own.inv(),
544 frame_own.global_inv(*final(regions)),
545 frame_own.frame_link_inv(*final(regions)),
546 frame_own.slot_index == meta_to_index(old(owner).list[n].slot_vaddr),
547 final(regions).slot_owners[frame_own.slot_index].in_list_perm.value() == 0,
548 forall|j: int|
549 #![trigger final(regions).slots[j]]
550 #![trigger final(regions).slot_owners[j]]
551 j != meta_to_index(old(owner).list[n].slot_vaddr) && (n > 0 ==> j != meta_to_index(
552 old(owner).list[n - 1].slot_vaddr,
553 )) && (n < old(owner).list.len() - 1 ==> j != meta_to_index(
554 old(owner).list[n + 1].slot_vaddr,
555 )) ==> final(regions).slots[j] == old(regions).slots[j] && final(regions).slot_owners[j]
556 == old(regions).slot_owners[j],
557 forall|l: LinkedListOwner<M>|
558 #![trigger l.relate_region(*old(regions))]
559 l.inv() && l.relate_region(*old(regions)) && l.list_id != final(owner).list_id
560 ==> l.relate_region(*final(regions)),
561 list_registry_ok(*final(regions), *final(owner)),
562 forall|l: LinkedListOwner<M>|
563 #![trigger l.relate_region(*old(regions))]
564 l.inv() && l.relate_region(*old(regions)) && list_registry_ok(*old(regions), l)
565 && l.list_id != final(owner).list_id ==> list_registry_ok(*final(regions), l),
566 forall|fo: UniqueFrameOwner<Link<M>>|
567 #![trigger fo.global_inv(*old(regions))]
568 fo.global_inv(*old(regions)) && fo.frame_link_inv(*old(regions)) && old(
569 regions,
570 ).slot_owners[fo.slot_index].in_list_perm.value() == 0 ==> fo.global_inv(
571 *final(regions),
572 ) && fo.frame_link_inv(*final(regions))
573 && final(regions).slot_owners[fo.slot_index].in_list_perm.value() == 0
574 && fo.slot_index != meta_to_index(old(owner).list[n].slot_vaddr),
575;
576
577pub axiom fn axiom_list_drop_embedded<M: AnyFrameMeta + Repr<MetaSlotSmall>>(
579 tracked regions: &mut MetaRegionOwners,
580 tracked owner: LinkedListOwner<M>,
581)
582 requires
583 old(regions).inv(),
584 owner.inv(),
585 owner.relate_region(*old(regions)),
586 forall|i: int|
587 #![trigger meta_to_index(owner.list[i].slot_vaddr)]
588 0 <= i < owner.list.len() ==> old(regions).slot_owners[meta_to_index(
589 owner.list[i].slot_vaddr,
590 )].paths_in_pt.is_empty(),
591 ensures
592 final(regions).inv(),
593 final(regions).slots.dom() =~= old(regions).slots.dom(),
594 owner.list.len() == 0 ==> *final(regions) == *old(regions),
596 forall|i: int|
598 #![trigger meta_to_index(owner.list[i].slot_vaddr)]
599 0 <= i < owner.list.len() ==> {
600 let idx = meta_to_index(owner.list[i].slot_vaddr);
601 &&& final(regions).ref_count(idx) == REF_COUNT_UNUSED
602 &&& final(regions).slot_owners[idx].in_list_perm.value() == 0
603 },
604 forall|idx: int|
606 #![trigger final(regions).slot_owners[idx]]
607 (forall|i: int|
608 0 <= i < owner.list.len() ==> idx != #[trigger] meta_to_index(
609 owner.list[i].slot_vaddr,
610 )) ==> final(regions).slot_owners[idx] == old(regions).slot_owners[idx]
611 && final(regions).slots[idx] == old(regions).slots[idx],
612 forall|l: LinkedListOwner<M>|
614 #![trigger l.relate_region(*old(regions))]
615 l.inv() && l.relate_region(*old(regions)) && l.list_id != owner.list_id
616 ==> l.relate_region(*final(regions)),
617 forall|l: LinkedListOwner<M>|
618 #![trigger l.relate_region(*old(regions))]
619 l.inv() && l.relate_region(*old(regions)) && list_registry_ok(*old(regions), l)
620 && l.list_id != owner.list_id ==> list_registry_ok(*final(regions), l),
621 forall|fo: UniqueFrameOwner<Link<M>>|
624 #![trigger fo.global_inv(*old(regions))]
625 fo.global_inv(*old(regions)) && fo.frame_link_inv(*old(regions)) && old(
626 regions,
627 ).slot_owners[fo.slot_index].in_list_perm.value() == 0 ==> fo.global_inv(
628 *final(regions),
629 ) && fo.frame_link_inv(*final(regions))
630 && final(regions).slot_owners[fo.slot_index].in_list_perm.value() == 0,
631;
632
633impl<M: AnyFrameMeta + Repr<MetaSlotSmall>> ListStore<M> {
637 pub proof fn step_size(tracked &self, id: ListId) -> (res: nat)
640 requires
641 self.inv(),
642 self.lists.dom().contains(id),
643 ensures
644 res == self.lists[id].list.len(),
645 {
646 self.lists[id].list.len()
647 }
648
649 pub proof fn step_is_empty(tracked &self, id: ListId) -> (res: bool)
651 requires
652 self.inv(),
653 self.lists.dom().contains(id),
654 ensures
655 res <==> self.lists[id].list.len() == 0,
656 {
657 self.lists[id].list.len() == 0
658 }
659
660 pub proof fn step_contains(tracked &self, id: ListId, frame: Paddr) -> (res: bool)
662 requires
663 self.inv(),
664 self.lists.dom().contains(id),
665 ensures
666 res <==> (valid_frame_paddr(frame) && exists|i: int|
667 0 <= i < self.lists[id].list.len() && #[trigger] meta_to_index(
668 self.lists[id].list[i].slot_vaddr,
669 ) == frame_to_index(frame)),
670 {
671 let idx = frame_to_index(frame);
672 if valid_frame_paddr(frame) {
673 self.regions.lemma_contains_valid_frame_paddr(frame);
674 if self.lists[id].list_id != 0 {
675 let res = self.regions.slot_owners[idx].in_list_perm.value()
676 == self.lists[id].list_id;
677 res
678 } else {
679 false
680 }
681 } else {
682 false
683 }
684 }
685
686 pub proof fn step_list_new(tracked &mut self) -> (res: ListId)
688 requires
689 old(self).inv(),
690 ensures
691 final(self).inv(),
692 final(self).regions == old(self).regions,
693 final(self).loose == old(self).loose,
694 !old(self).lists.dom().contains(res),
695 final(self).lists == old(self).lists.insert(res, final(self).lists[res]),
696 final(self).lists[res].list.len() == 0,
697 {
698 let ghost id = fresh_list_id(self.lists, self.cursors);
699 lemma_fresh_list_id_not_in_dom(self.lists, self.cursors);
700 let tracked empty = tracked_empty_list_owner::<M>();
701 self.lists.tracked_insert(id, empty);
702 assert(self.lists[id].relate_region(self.regions)) by {
703 reveal(LinkedListOwner::relate_region);
704 };
705 id
706 }
707
708 pub proof fn step_list_drop(tracked &mut self, id: ListId)
710 requires
711 old(self).inv(),
712 old(self).lists.dom().contains(id),
713 ensures
714 final(self).inv(),
715 !final(self).lists.dom().contains(id),
716 final(self).loose == old(self).loose,
717 final(self).cursors == old(self).cursors,
718 {
719 self.lists[id].lemma_relate_region_shape(self.regions);
720 assert forall|i: int|
721 #![trigger meta_to_index(self.lists[id].list[i].slot_vaddr)]
722 0 <= i < self.lists[id].list.len() implies self.regions.slot_owners[meta_to_index(
723 self.lists[id].list[i].slot_vaddr,
724 )].paths_in_pt.is_empty() by {
725 let idx = meta_to_index(self.lists[id].list[i].slot_vaddr);
726 let _ = self.lists[id].list[i];
727 self.lists[id].lemma_relate_region_at_index(self.regions, i);
728 self.lists[id].lemma_relate_region_at_facts(self.regions, i);
729 assert(self.regions.contains(idx));
730 assert(self.regions.ref_count(idx) == REF_COUNT_UNIQUE);
731 assert(self.regions.slot_owners[idx].usage is Frame);
732 };
733
734 let tracked owner = self.lists.tracked_remove(id);
735 axiom_list_drop_embedded(&mut self.regions, owner);
736 }
737
738 pub proof fn step_push_front(tracked &mut self, id: ListId, lid: LooseId)
742 requires
743 old(self).inv(),
744 old(self).lists.dom().contains(id),
745 old(self).loose.dom().contains(lid),
746 ensures
747 final(self).inv(),
748 {
749 let ghost old_self = *self;
750 let ghost used = Set::<u64>::full().unwrap().filter(
752 |x: u64|
753 (exists|i: ListId| #[trigger]
754 old_self.lists.dom().contains(i) && i != id && old_self.lists[i].list_id == x)
755 || (exists|cid: CursorId| #[trigger]
756 old_self.cursors.dom().contains(cid) && old_self.cursors[cid].list_own.list_id
757 == x),
758 );
759
760 let tracked mut owner = self.lists.tracked_remove(id);
761 let tracked mut frame_own = self.loose.tracked_remove(lid);
762 push_front_embedded(&mut self.regions, &mut owner, &mut frame_own, used);
763 self.lists.tracked_insert(id, owner);
764 }
765
766 pub proof fn step_pop_front(tracked &mut self, id: ListId) -> (res: Option<LooseId>)
770 requires
771 old(self).inv(),
772 old(self).lists.dom().contains(id),
773 ensures
774 final(self).inv(),
775 old(self).lists[id].list.len() == 0 ==> res is None && *final(self) == *old(self),
776 old(self).lists[id].list.len() > 0 ==> res is Some,
777 {
778 if self.lists[id].list.len() == 0 {
779 Option::None
780 } else {
781 let tracked mut owner = self.lists.tracked_remove(id);
782 let tracked frame_own = tracked_pop_front_embedded(&mut self.regions, &mut owner);
783 self.lists.tracked_insert(id, owner);
784 let ghost new_loose = fresh_loose_id(self.loose);
785
786 self.loose.tracked_insert(new_loose, frame_own);
787
788 Option::Some(new_loose)
789 }
790 }
791
792 pub proof fn step_push_back(tracked &mut self, id: ListId, lid: LooseId)
796 requires
797 old(self).inv(),
798 old(self).lists.dom().contains(id),
799 old(self).loose.dom().contains(lid),
800 ensures
801 final(self).inv(),
802 {
803 let ghost old_self = *self;
804 let ghost used = Set::<u64>::full().unwrap().filter(
805 |x: u64|
806 (exists|i: ListId| #[trigger]
807 old_self.lists.dom().contains(i) && i != id && old_self.lists[i].list_id == x)
808 || (exists|cid: CursorId| #[trigger]
809 old_self.cursors.dom().contains(cid) && old_self.cursors[cid].list_own.list_id
810 == x),
811 );
812
813 let tracked mut owner = self.lists.tracked_remove(id);
814 let tracked mut frame_own = self.loose.tracked_remove(lid);
815 lemma_push_back_embedded(&mut self.regions, &mut owner, &mut frame_own, used);
816
817 self.lists.tracked_insert(id, owner);
818 }
819
820 pub proof fn step_pop_back(tracked &mut self, id: ListId) -> (res: Option<LooseId>)
824 requires
825 old(self).inv(),
826 old(self).lists.dom().contains(id),
827 ensures
828 final(self).inv(),
829 old(self).lists[id].list.len() == 0 ==> res is None && *final(self) == *old(self),
830 old(self).lists[id].list.len() > 0 ==> res is Some,
831 {
832 if self.lists[id].list.len() == 0 {
833 Option::None
834 } else {
835 let tracked mut owner = self.lists.tracked_remove(id);
836 let tracked frame_own = tracked_pop_back_embedded(&mut self.regions, &mut owner);
837 self.lists.tracked_insert(id, owner);
838 let ghost new_loose = fresh_loose_id(self.loose);
839
840 self.loose.tracked_insert(new_loose, frame_own);
841
842 Option::Some(new_loose)
843 }
844 }
845
846 pub proof fn step_insert_before_at(tracked &mut self, id: ListId, n: int, lid: LooseId)
849 requires
850 old(self).inv(),
851 old(self).lists.dom().contains(id),
852 old(self).loose.dom().contains(lid),
853 0 <= n <= old(self).lists[id].list.len(),
854 ensures
855 final(self).inv(),
856 {
857 let ghost old_self = *self;
858 let ghost used = Set::<u64>::full().unwrap().filter(
859 |x: u64|
860 (exists|i: ListId| #[trigger]
861 old_self.lists.dom().contains(i) && i != id && old_self.lists[i].list_id == x)
862 || (exists|cid: CursorId| #[trigger]
863 old_self.cursors.dom().contains(cid) && old_self.cursors[cid].list_own.list_id
864 == x),
865 );
866
867 let tracked mut owner = self.lists.tracked_remove(id);
868 let tracked mut frame_own = self.loose.tracked_remove(lid);
869 axiom_insert_before_at_embedded(&mut self.regions, &mut owner, &mut frame_own, n, used);
870
871 self.lists.tracked_insert(id, owner);
872 }
873
874 pub proof fn step_take_at(tracked &mut self, id: ListId, n: int) -> (res: Option<LooseId>)
879 requires
880 old(self).inv(),
881 old(self).lists.dom().contains(id),
882 ensures
883 final(self).inv(),
884 !(0 <= n < old(self).lists[id].list.len()) ==> res is None && *final(self) == *old(
885 self,
886 ),
887 0 <= n < old(self).lists[id].list.len() ==> res is Some,
888 {
889 if !(0 <= n < self.lists[id].list.len()) {
890 Option::None
893 } else {
894 let tracked mut owner = self.lists.tracked_remove(id);
895 let tracked frame_own = axiom_take_at_embedded(&mut self.regions, &mut owner, n);
896 self.lists.tracked_insert(id, owner);
897 let ghost new_loose = fresh_loose_id(self.loose);
898
899 self.loose.tracked_insert(new_loose, frame_own);
900
901 Option::Some(new_loose)
902 }
903 }
904
905 pub proof fn step_cursor_front_mut(tracked &mut self, id: ListId)
912 requires
913 old(self).inv(),
914 old(self).lists.dom().contains(id),
915 ensures
916 final(self).inv(),
917 !final(self).lists.dom().contains(id),
918 final(self).cursors.dom().contains(id),
919 final(self).cursors[id] == CursorOwner::front_owner(old(self).lists[id]),
920 {
921 let tracked owner = self.lists.tracked_remove(id);
922 let tracked cur = CursorOwner::tracked_front_owner(owner);
923 self.cursors.tracked_insert(id, cur);
924 }
925
926 pub proof fn step_cursor_back_mut(tracked &mut self, id: ListId)
929 requires
930 old(self).inv(),
931 old(self).lists.dom().contains(id),
932 ensures
933 final(self).inv(),
934 !final(self).lists.dom().contains(id),
935 final(self).cursors.dom().contains(id),
936 final(self).cursors[id] == CursorOwner::back_owner(old(self).lists[id]),
937 {
938 let tracked owner = self.lists.tracked_remove(id);
939 let tracked cur = CursorOwner::tracked_back_owner(owner);
940 self.cursors.tracked_insert(id, cur);
941 }
942
943 pub proof fn step_cursor_mut_at(tracked &mut self, id: ListId, frame: Paddr) -> (res: bool)
945 requires
946 old(self).inv(),
947 old(self).lists.dom().contains(id),
948 ensures
949 final(self).inv(),
950 res == (exists|i: int|
952 0 <= i < old(self).lists[id].list.len() && #[trigger] meta_to_index(
953 old(self).lists[id].list[i].slot_vaddr,
954 ) == frame_to_index(frame)),
955 res ==> !final(self).lists.dom().contains(id) && final(self).cursors.dom().contains(id)
958 && exists|i: int|
959 0 <= i < old(self).lists[id].list.len() && #[trigger] meta_to_index(
960 old(self).lists[id].list[i].slot_vaddr,
961 ) == #[trigger] frame_to_index(frame) && final(self).cursors[id]
962 == CursorOwner::cursor_mut_at_owner(old(self).lists[id], i),
963 !res ==> *final(self) == *old(self),
965 {
966 if exists|i: int|
967 0 <= i < self.lists[id].list.len() && #[trigger] meta_to_index(
968 self.lists[id].list[i].slot_vaddr,
969 ) == frame_to_index(frame) {
970 let ghost index = choose|i: int|
971 0 <= i < self.lists[id].list.len() && #[trigger] meta_to_index(
972 self.lists[id].list[i].slot_vaddr,
973 ) == frame_to_index(frame);
974 let tracked owner = self.lists.tracked_remove(id);
975 let tracked cur = CursorOwner::tracked_cursor_mut_at_owner(owner, index);
976 self.cursors.tracked_insert(id, cur);
977 true
978 } else {
979 false
980 }
981 }
982
983 pub proof fn step_move_next(tracked &mut self, id: CursorId)
985 requires
986 old(self).inv(),
987 old(self).cursors.dom().contains(id),
988 ensures
989 final(self).inv(),
990 final(self).regions == old(self).regions,
991 final(self).cursors[id] == old(self).cursors[id].move_next_owner_spec(),
992 {
993 let tracked cur = self.cursors.tracked_remove(id);
994 let ghost ni = cur.move_next_owner_spec().index;
995 let tracked CursorOwner { list_own, index: _ } = cur;
996 let tracked cur2 = CursorOwner::tracked_cursor_mut_at_owner(list_own, ni);
997 self.cursors.tracked_insert(id, cur2);
998 }
999
1000 pub proof fn step_move_prev(tracked &mut self, id: CursorId)
1002 requires
1003 old(self).inv(),
1004 old(self).cursors.dom().contains(id),
1005 ensures
1006 final(self).inv(),
1007 final(self).regions == old(self).regions,
1008 final(self).cursors[id] == old(self).cursors[id].move_prev_owner_spec(),
1009 {
1010 let tracked cur = self.cursors.tracked_remove(id);
1011 let ghost ni = cur.move_prev_owner_spec().index;
1012 let tracked CursorOwner { list_own, index: _ } = cur;
1013 let tracked cur2 = CursorOwner::tracked_cursor_mut_at_owner(list_own, ni);
1014 self.cursors.tracked_insert(id, cur2);
1015 }
1016
1017 pub proof fn step_current_meta(tracked &self, id: CursorId) -> (res: Option<LinkOwner>)
1019 requires
1020 self.inv(),
1021 self.cursors.dom().contains(id),
1022 ensures
1023 res == self.cursors[id].current(),
1024 res.is_some() <==> 0 <= self.cursors[id].index < self.cursors[id].length(),
1025 {
1026 self.cursors[id].current()
1027 }
1028
1029 pub proof fn step_as_list(tracked &self, id: CursorId) -> (res: Seq<LinkOwner>)
1032 requires
1033 self.inv(),
1034 self.cursors.dom().contains(id),
1035 ensures
1036 res == self.cursors[id].list_own.list,
1037 res.len() == self.cursors[id].length(),
1038 {
1039 self.cursors[id].list_own.list
1040 }
1041
1042 pub proof fn step_cursor_drop(tracked &mut self, id: CursorId)
1046 requires
1047 old(self).inv(),
1048 old(self).cursors.dom().contains(id),
1049 ensures
1050 final(self).inv(),
1051 !final(self).cursors.dom().contains(id),
1052 final(self).lists.dom().contains(id),
1053 final(self).lists[id] == old(self).cursors[id].list_own,
1054 {
1055 let tracked cur = self.cursors.tracked_remove(id);
1056 let tracked CursorOwner { list_own, index: _ } = cur;
1057 self.lists.tracked_insert(id, list_own);
1058 }
1059
1060 pub proof fn step_cursor_insert_before(tracked &mut self, id: CursorId, lid: LooseId)
1062 requires
1063 old(self).inv(),
1064 old(self).cursors.dom().contains(id),
1065 old(self).loose.dom().contains(lid),
1066 ensures
1067 final(self).inv(),
1068 {
1069 let ghost old_self = *self;
1070 let ghost n = self.cursors[id].index;
1071 let ghost used = Set::<u64>::full().unwrap().filter(
1073 |x: u64|
1074 (exists|i: ListId| #[trigger]
1075 old_self.lists.dom().contains(i) && old_self.lists[i].list_id == x) || (exists|
1076 cid: CursorId,
1077 | #[trigger]
1078 old_self.cursors.dom().contains(cid) && cid != id
1079 && old_self.cursors[cid].list_own.list_id == x),
1080 );
1081
1082 let tracked cur = self.cursors.tracked_remove(id);
1083 let tracked CursorOwner { list_own: mut owner, index: _ } = cur;
1084 let tracked mut frame_own = self.loose.tracked_remove(lid);
1085 axiom_insert_before_at_embedded(&mut self.regions, &mut owner, &mut frame_own, n, used);
1086 let tracked cur2 = CursorOwner::tracked_cursor_mut_at_owner(owner, n + 1);
1087 self.cursors.tracked_insert(id, cur2);
1088 }
1089
1090 pub proof fn step_cursor_take_current(tracked &mut self, id: CursorId) -> (res: Option<LooseId>)
1092 requires
1093 old(self).inv(),
1094 old(self).cursors.dom().contains(id),
1095 ensures
1096 final(self).inv(),
1097 !(0 <= old(self).cursors[id].index < old(self).cursors[id].length()) ==> res is None
1098 && *final(self) == *old(self),
1099 0 <= old(self).cursors[id].index < old(self).cursors[id].length() ==> res is Some,
1100 {
1101 if !(0 <= self.cursors[id].index < self.cursors[id].length()) {
1102 Option::None
1105 } else {
1106 let ghost n = self.cursors[id].index;
1107
1108 let tracked cur = self.cursors.tracked_remove(id);
1109 let tracked CursorOwner { list_own: mut owner, index: _ } = cur;
1110 let tracked frame_own = axiom_take_at_embedded(&mut self.regions, &mut owner, n);
1111 let tracked cur2 = CursorOwner::tracked_cursor_mut_at_owner(owner, n);
1112 self.cursors.tracked_insert(id, cur2);
1113 let ghost new_loose = fresh_loose_id(self.loose);
1114
1115 self.loose.tracked_insert(new_loose, frame_own);
1116
1117 Option::Some(new_loose)
1118 }
1119 }
1120}
1121
1122}