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