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