ostd/specs/task/
cpu_core.rs1use vstd::{prelude::*, resource::Loc};
10use vstd_extra::resource::ghost_resource::excl::ExclusiveGhost;
11
12use crate::specs::task::cpu_local::CpuLocalAuth;
13
14use core::marker::PhantomData;
15
16use crate::cpu::CpuId;
17
18verus! {
19
20pub ghost struct CpuCoreOwnerView {
22 pub cpu: CpuId,
24 pub current_task: Option<Loc>,
26 pub locals_key: Seq<Loc>,
28}
29
30pub trait CpuCoreLocalState {
38 spec fn belongs_to_cpu(self, cpu: CpuId) -> bool;
39
40 spec fn local_key(self) -> Seq<Loc>;
45}
46
47impl CpuCoreLocalState for () {
48 open spec fn belongs_to_cpu(self, _cpu: CpuId) -> bool {
49 true
50 }
51
52 open spec fn local_key(self) -> Seq<Loc> {
53 Seq::empty()
54 }
55}
56
57impl<A: CpuCoreLocalState, B: CpuCoreLocalState> CpuCoreLocalState for (A, B) {
58 open spec fn belongs_to_cpu(self, cpu: CpuId) -> bool {
59 self.0.belongs_to_cpu(cpu) && self.1.belongs_to_cpu(cpu)
60 }
61
62 open spec fn local_key(self) -> Seq<Loc> {
63 self.0.local_key() + self.1.local_key()
64 }
65}
66
67pub tracked struct CpuCoreOwnerHandle<L: CpuCoreLocalState> {
74 state: ExclusiveGhost<CpuCoreOwnerView>,
75 marker: PhantomData<L>,
76}
77
78pub tracked struct CpuCoreOwner<L: CpuCoreLocalState> {
84 handle: CpuCoreOwnerHandle<L>,
85 locals: L,
86}
87
88impl<L: CpuCoreLocalState> View for CpuCoreOwnerHandle<L> {
89 type V = CpuCoreOwnerView;
90
91 closed spec fn view(&self) -> Self::V {
92 self.state.view()
93 }
94}
95
96impl<L: CpuCoreLocalState> View for CpuCoreOwner<L> {
97 type V = CpuCoreOwnerView;
98
99 closed spec fn view(&self) -> Self::V {
100 self.handle@
101 }
102}
103
104impl<L: CpuCoreLocalState> CpuCoreOwnerHandle<L> {
105 pub closed spec fn id(&self) -> Loc {
107 self.state.id()
108 }
109
110 pub closed spec fn cpu(&self) -> CpuId {
112 self@.cpu
113 }
114
115 pub closed spec fn current_task(&self) -> Option<Loc> {
117 self@.current_task
118 }
119
120 pub open spec fn is_idle(&self) -> bool {
122 self.current_task() is None
123 }
124
125 pub closed spec fn wf(&self) -> bool {
127 self.state.wf()
128 }
129
130 pub closed spec fn expected_locals_key(&self) -> Seq<Loc> {
132 self@.locals_key
133 }
134
135 pub proof fn tracked_restore(tracked self, tracked locals: L) -> (tracked res: CpuCoreOwner<L>)
137 requires
138 self.wf(),
139 locals.belongs_to_cpu(self.cpu()),
140 locals.local_key() == self.expected_locals_key(),
141 ensures
142 res.id() == self.id(),
143 res@ == self@,
144 res.wf(),
145 res.locals() == locals,
146 res.locals().local_key() == self.expected_locals_key(),
147 {
148 CpuCoreOwner { handle: self, locals }
149 }
150}
151
152impl<L: CpuCoreLocalState> CpuCoreOwner<L> {
153 pub proof fn new(cpu: CpuId, tracked locals: L) -> (tracked res: Self)
155 requires
156 locals.belongs_to_cpu(cpu),
157 ensures
158 res.cpu() == cpu,
159 res.is_idle(),
160 res.wf(),
161 res.locals() == locals,
162 {
163 let ghost locals_key = locals.local_key();
164 let tracked state = ExclusiveGhost::alloc(
165 CpuCoreOwnerView { cpu, current_task: None, locals_key },
166 );
167 let tracked handle = CpuCoreOwnerHandle { state, marker: PhantomData };
168 CpuCoreOwner { handle, locals }
169 }
170
171 pub closed spec fn id(&self) -> Loc {
173 self.handle.id()
174 }
175
176 pub closed spec fn cpu(&self) -> CpuId {
178 self@.cpu
179 }
180
181 pub closed spec fn current_task(&self) -> Option<Loc> {
183 self@.current_task
184 }
185
186 pub open spec fn is_idle(&self) -> bool {
188 self.current_task() is None
189 }
190
191 pub closed spec fn locals(&self) -> L {
193 self.locals
194 }
195
196 pub closed spec fn locals_key(&self) -> Seq<Loc> {
198 self.handle.expected_locals_key()
199 }
200
201 pub closed spec fn wf(&self) -> bool {
203 &&& self.handle.wf()
204 &&& self.locals().belongs_to_cpu(self.cpu())
205 &&& self.locals().local_key() == self.locals_key()
206 }
207
208 pub proof fn tracked_schedule_in(tracked &mut self, task: Loc)
210 requires
211 old(self).wf(),
212 old(self).is_idle(),
213 ensures
214 final(self).id() == old(self).id(),
215 final(self).cpu() == old(self).cpu(),
216 final(self).current_task() == Some(task),
217 final(self).locals() == old(self).locals(),
218 final(self).locals_key() == old(self).locals_key(),
219 final(self).wf(),
220 {
221 let ghost next = CpuCoreOwnerView {
222 cpu: self.cpu(),
223 current_task: Some(task),
224 locals_key: self.locals_key(),
225 };
226 self.handle.state.update(next);
227 }
228
229 pub proof fn tracked_schedule_out(tracked &mut self) -> (task: Loc)
231 requires
232 old(self).wf(),
233 !old(self).is_idle(),
234 ensures
235 old(self).current_task() == Some(task),
236 final(self).id() == old(self).id(),
237 final(self).cpu() == old(self).cpu(),
238 final(self).is_idle(),
239 final(self).locals() == old(self).locals(),
240 final(self).locals_key() == old(self).locals_key(),
241 final(self).wf(),
242 {
243 let task = self.current_task()->0;
244 let ghost next = CpuCoreOwnerView {
245 cpu: self.cpu(),
246 current_task: None,
247 locals_key: self.locals_key(),
248 };
249 self.handle.state.update(next);
250 task
251 }
252
253 pub proof fn tracked_open(tracked self) -> (tracked res: (CpuCoreOwnerHandle<L>, L))
259 requires
260 self.wf(),
261 ensures
262 res.0.id() == self.id(),
263 res.0@ == self@,
264 res.0.wf(),
265 res.0.expected_locals_key() == self.locals_key(),
266 res.1 == self.locals(),
267 res.1.belongs_to_cpu(res.0.cpu()),
268 res.1.local_key() == res.0.expected_locals_key(),
269 {
270 (self.handle, self.locals)
271 }
272}
273
274proof fn cpu_core_owns_cpu_local_points_to<V>(initial: Map<CpuId, V>, cpu: CpuId, new_value: V)
277 requires
278 initial.contains_key(cpu),
279{
280 let tracked (mut auth, mut points_to_set) = CpuLocalAuth::new(initial);
281 let tracked points_to = points_to_set.tracked_take(cpu);
282 let tracked mut core = CpuCoreOwner::new(cpu, points_to);
283
284 let ghost task = auth.id();
285 core.tracked_schedule_in(task);
286 let tracked (handle, mut points_to) = core.tracked_open();
287 assert(handle.cpu() == cpu);
288 assert(handle.current_task() == Some(task));
289
290 points_to.tracked_update(&mut auth, new_value);
291 let tracked mut core = handle.tracked_restore(points_to);
292 assert(core.cpu() == cpu);
293 assert(core.current_task() == Some(task));
294
295 let finished_task = core.tracked_schedule_out();
296 assert(finished_task == task);
297 assert(core.is_idle());
298}
299
300}