Skip to content

Commit 6b0168d

Browse files
committed
prove: util::range_alloc
1 parent 8b53a4b commit 6b0168d

2 files changed

Lines changed: 53 additions & 2 deletions

File tree

ostd/src/util/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
mod either;
44
//mod macros;
55
//pub(crate) mod ops;
6-
//pub(crate) mod range_alloc;
6+
pub(crate) mod range_alloc;
77

88
pub use either::Either;

ostd/src/util/range_alloc.rs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,66 @@
11
// SPDX-License-Identifier: MPL-2.0
2+
use vstd::prelude::*;
3+
24
use alloc::collections::btree_map::BTreeMap;
35
use core::ops::Range;
46

57
use crate::sync::{PreemptDisabled, SpinLock, SpinLockGuard};
68

9+
#[verus_verify]
710
pub struct RangeAllocator {
811
fullrange: Range<usize>,
9-
freelist: SpinLock<Option<BTreeMap<usize, FreeRange>>>,
12+
// TODO: PreemptDisabled added, SpinLock should be improved.
13+
freelist: SpinLock<Option<BTreeMap<usize, FreeRange>>, PreemptDisabled>,
1014
}
1115

1216
/// An error returned when allocating from a [`RangeAllocator`].
17+
#[verus_verify]
1318
#[derive(Debug)]
1419
pub struct RangeAllocError;
1520

21+
verus! {
22+
23+
impl View for RangeAllocator {
24+
type V = Range<int>;
25+
26+
/// Specification view of the allocator's managed full range.
27+
closed spec fn view(&self) -> Range<int> {
28+
Range { start: self.fullrange.start as int, end: self.fullrange.end as int }
29+
}
30+
}
31+
32+
} // verus!
33+
#[verus_verify]
1634
impl RangeAllocator {
35+
#[verus_spec(ret =>
36+
ensures
37+
ret@.start == fullrange.start,
38+
ret@.end == fullrange.end,
39+
)]
1740
pub const fn new(fullrange: Range<usize>) -> Self {
1841
Self {
1942
fullrange,
2043
freelist: SpinLock::new(None),
2144
}
2245
}
2346

47+
#[verus_spec(ret =>
48+
ensures
49+
ret.start == self@.start,
50+
ret.end == self@.end,
51+
)]
2452
pub const fn fullrange(&self) -> &Range<usize> {
2553
&self.fullrange
2654
}
2755

2856
/// Allocates a specific kernel virtual area.
57+
#[verifier::external_body]
58+
#[verus_spec(res =>
59+
requires allocate_range.start < allocate_range.end,
60+
ensures
61+
res is Ok ==> (self@.start <= allocate_range.start
62+
&& allocate_range.end <= self@.end),
63+
)]
2964
pub fn alloc_specific(&self, allocate_range: &Range<usize>) -> Result<(), RangeAllocError> {
3065
debug_assert!(allocate_range.start < allocate_range.end);
3166

@@ -69,6 +104,13 @@ impl RangeAllocator {
69104
/// Allocates a range specific by the `size`.
70105
///
71106
/// This is currently implemented with a simple FIRST-FIT algorithm.
107+
#[verifier::external_body]
108+
#[verus_spec(res =>
109+
ensures
110+
res is Ok ==> (res->Ok_0.end - res->Ok_0.start == size),
111+
res is Ok ==> (self@.start <= res->Ok_0.start
112+
&& res->Ok_0.end <= self@.end),
113+
)]
72114
pub fn alloc(&self, size: usize) -> Result<Range<usize>, RangeAllocError> {
73115
let mut lock_guard = self.get_freelist_guard();
74116
let freelist = lock_guard.as_mut().unwrap();
@@ -101,6 +143,7 @@ impl RangeAllocator {
101143
}
102144

103145
/// Frees a `range`.
146+
#[verifier::external_body]
104147
pub fn free(&self, range: Range<usize>) {
105148
let mut lock_guard = self.freelist.lock();
106149
let freelist = lock_guard.as_mut().unwrap_or_else(|| {
@@ -137,6 +180,7 @@ impl RangeAllocator {
137180
}
138181
}
139182

183+
#[verifier::external_body]
140184
fn get_freelist_guard(
141185
&self,
142186
) -> SpinLockGuard<Option<BTreeMap<usize, FreeRange>>, PreemptDisabled> {
@@ -150,11 +194,18 @@ impl RangeAllocator {
150194
}
151195
}
152196

197+
#[verus_verify]
153198
struct FreeRange {
154199
block: Range<usize>,
155200
}
156201

202+
#[verus_verify]
157203
impl FreeRange {
204+
#[verus_spec(ret =>
205+
ensures
206+
ret.block.start == range.start,
207+
ret.block.end == range.end,
208+
)]
158209
const fn new(range: Range<usize>) -> Self {
159210
Self { block: range }
160211
}

0 commit comments

Comments
 (0)