ax_task/sched/system/task_system/
outcome.rs1use super::super::thread_sched::DeadlineActivity;
4use crate::{
5 runtime::switch::{RuntimeSwitchPlan, ThreadRuntimeBinding},
6 sched::{CpuId, SchedulePolicy},
7 thread::{SwitchReason, ThreadCore, ThreadExtensionView, ThreadId},
8};
9
10#[derive(Debug)]
12pub struct ScheduleDecision {
13 pub(super) previous: Option<ThreadId>,
14 pub(super) next: ThreadId,
15 pub(super) runtime_switch_plan: Option<RuntimeSwitchPlan>,
16 pub(super) switch_reason: SwitchReason,
17 pub(super) timestamp_ns: u64,
18}
19
20#[derive(Debug)]
22pub enum YieldOutcome {
23 Unchanged,
25 Switch(ScheduleDecision),
27}
28
29impl YieldOutcome {
30 pub(crate) const fn decision_mut(&mut self) -> Option<&mut ScheduleDecision> {
31 match self {
32 Self::Unchanged => None,
33 Self::Switch(decision) => Some(decision),
34 }
35 }
36}
37
38#[doc(hidden)]
43pub struct SwitchInCompletion {
44 thread: Option<ThreadId>,
45 policy: Option<SchedulePolicy>,
46 extension: Option<ThreadExtensionView>,
47 charged_runtime_ns: u64,
48 trace_wake: Option<fn()>,
49}
50
51impl SwitchInCompletion {
52 pub(crate) const NONE: Self = Self {
53 thread: None,
54 policy: None,
55 extension: None,
56 charged_runtime_ns: 0,
57 trace_wake: None,
58 };
59
60 pub(crate) fn for_core(
61 core: &ThreadCore,
62 policy: SchedulePolicy,
63 charged_runtime_ns: u64,
64 ) -> Self {
65 Self {
66 thread: Some(core.id()),
67 policy: Some(policy),
68 extension: core.extension_view(),
69 charged_runtime_ns,
70 trace_wake: None,
71 }
72 }
73
74 pub(crate) fn with_trace_wake(mut self, wake: Option<fn()>) -> Self {
75 self.trace_wake = wake;
76 self
77 }
78
79 #[doc(hidden)]
80 pub fn finish(self) {
81 if let (Some(thread), Some(policy), Some(extension)) =
82 (self.thread, self.policy, self.extension)
83 {
84 unsafe {
89 (extension.ops().on_switch_in)(
90 extension.data(),
91 thread,
92 policy,
93 self.charged_runtime_ns,
94 )
95 };
96 }
97 if let Some(wake) = self.trace_wake {
101 wake();
102 }
103 }
104}
105
106#[derive(Debug)]
112pub enum SchedulerOutcome {
113 Quiescent,
115 ParkingDeferred,
117 OwnerWorkPending,
119 Decision(ScheduleDecision),
121}
122
123impl SchedulerOutcome {
124 pub const fn decision(&self) -> Option<&ScheduleDecision> {
126 match self {
127 Self::Decision(decision) => Some(decision),
128 Self::Quiescent | Self::ParkingDeferred | Self::OwnerWorkPending => None,
129 }
130 }
131
132 pub(crate) const fn decision_mut(&mut self) -> Option<&mut ScheduleDecision> {
133 match self {
134 Self::Decision(decision) => Some(decision),
135 Self::Quiescent | Self::ParkingDeferred | Self::OwnerWorkPending => None,
136 }
137 }
138
139 pub const fn parking_deferred(&self) -> bool {
142 matches!(self, Self::ParkingDeferred)
143 }
144
145 pub const fn owner_work_pending(&self) -> bool {
147 matches!(self, Self::OwnerWorkPending)
148 }
149}
150
151impl ScheduleDecision {
152 pub const fn previous(&self) -> Option<ThreadId> {
154 self.previous
155 }
156
157 pub const fn next(&self) -> ThreadId {
159 self.next
160 }
161
162 pub const fn switch_reason(&self) -> SwitchReason {
164 self.switch_reason
165 }
166
167 pub const fn timestamp_ns(&self) -> u64 {
169 self.timestamp_ns
170 }
171
172 pub fn requires_context_switch(&self) -> bool {
174 self.previous() != Some(self.next())
175 }
176
177 pub(crate) fn take_runtime_switch_plan(&mut self) -> Option<RuntimeSwitchPlan> {
178 self.runtime_switch_plan.take()
179 }
180}
181
182#[derive(Clone, Copy, Debug)]
183pub(crate) struct SwitchEndpoint {
184 thread: ThreadId,
185 binding: ThreadRuntimeBinding,
186 address_space_identity: crate::runtime::resource::AddressSpaceMembarrierId,
187}
188
189impl SwitchEndpoint {
190 pub(crate) const fn new(
191 thread: ThreadId,
192 binding: ThreadRuntimeBinding,
193 address_space_identity: crate::runtime::resource::AddressSpaceMembarrierId,
194 ) -> Self {
195 Self {
196 thread,
197 binding,
198 address_space_identity,
199 }
200 }
201
202 pub(crate) const fn thread(self) -> ThreadId {
203 self.thread
204 }
205
206 pub(crate) const fn binding(self) -> ThreadRuntimeBinding {
207 self.binding
208 }
209
210 pub(crate) const fn address_space_identity(
211 self,
212 ) -> crate::runtime::resource::AddressSpaceMembarrierId {
213 self.address_space_identity
214 }
215}
216
217#[derive(Clone, Copy, Debug, Eq, PartialEq)]
219pub struct ChargeOutcome {
220 pub(super) slice_expired: bool,
221 pub(super) deadline_overrun: bool,
222}
223
224#[derive(Clone, Copy, Debug, Eq, PartialEq)]
226pub struct DeadlineRuntimeSnapshot {
227 pub(super) remaining_runtime_ns: u64,
228 pub(super) overruns: u64,
229 pub(super) pi_boosted: bool,
230 pub(super) donor: Option<ThreadId>,
231}
232
233#[derive(Clone, Copy, Debug, Eq, PartialEq)]
235pub struct DeadlineActivitySnapshot {
236 pub(super) activity: DeadlineActivity,
237 pub(super) bandwidth_cpu: Option<CpuId>,
238 pub(super) zero_lag_ns: Option<u64>,
239}
240
241impl DeadlineActivitySnapshot {
242 pub const fn activity(self) -> DeadlineActivity {
244 self.activity
245 }
246
247 pub const fn bandwidth_cpu(self) -> Option<CpuId> {
249 self.bandwidth_cpu
250 }
251
252 pub const fn zero_lag_ns(self) -> Option<u64> {
254 self.zero_lag_ns
255 }
256}
257
258impl DeadlineRuntimeSnapshot {
259 pub const fn remaining_runtime_ns(self) -> u64 {
261 self.remaining_runtime_ns
262 }
263
264 pub const fn overruns(self) -> u64 {
266 self.overruns
267 }
268
269 pub const fn pi_boosted(self) -> bool {
272 self.pi_boosted
273 }
274
275 pub const fn donor(self) -> Option<ThreadId> {
277 self.donor
278 }
279}
280
281#[derive(Clone, Copy, Debug, Eq, PartialEq)]
283pub struct OwnerControlDrain {
284 pub(super) drained: usize,
285 pub(super) pending: bool,
286}
287
288impl OwnerControlDrain {
289 pub const fn drained(self) -> usize {
291 self.drained
292 }
293
294 pub const fn pending(self) -> bool {
296 self.pending
297 }
298}
299
300impl ChargeOutcome {
301 pub const fn slice_expired(self) -> bool {
303 self.slice_expired
304 }
305
306 pub const fn deadline_overrun(self) -> bool {
308 self.deadline_overrun
309 }
310}