ax_task/sched/system/task_system/scheduling/
yield_entry.rs1use super::*;
4
5impl TaskSystem {
6 pub fn yield_current(
11 &self,
12 cpu: Pin<&mut CpuLocal>,
13 current: &ThreadHandle,
14 ) -> Result<YieldOutcome, TaskError> {
15 self.yield_current_owner(
16 cpu,
17 Some(current.runtime_core_arc().as_ref()),
18 OwnerRqEntry::IrqSave,
19 )
20 }
21
22 pub(crate) unsafe fn yield_current_in_scheduler_frame(
28 &self,
29 cpu: Pin<&mut CpuLocal>,
30 ) -> Result<YieldOutcome, TaskError> {
31 self.yield_current_owner(cpu, None, OwnerRqEntry::SchedulerFrame)
32 }
33
34 pub(super) fn yield_current_owner(
35 &self,
36 mut cpu: Pin<&mut CpuLocal>,
37 expected_current: Option<&ThreadCore>,
38 rq_entry: OwnerRqEntry,
39 ) -> Result<YieldOutcome, TaskError> {
40 #[cfg(feature = "qperf-metrics")]
41 let owner_entry_started_ns = task_runtime::monotonic_now().as_nanos();
42 let validate_owner = rq_entry.requires_owner_context_validation();
43 if validate_owner {
44 self.ensure_owner_cpu_context(&cpu)?;
45 }
46 let remote = unsafe { cpu.as_ref().get_ref().remote_for_owner() };
49 self.drain_owner_work(cpu.as_mut())?;
50 #[cfg(feature = "qperf-metrics")]
51 let owner_drain_finished_ns = task_runtime::monotonic_now().as_nanos();
52 if validate_owner {
53 self.ensure_owner_cpu_registration_online(&cpu)?;
54 }
55 #[cfg(feature = "qperf-metrics")]
60 let rq_begin_started_ns = task_runtime::monotonic_now().as_nanos();
61 let mut transaction = unsafe { rq_entry.begin(self, remote) };
62 #[cfg(feature = "qperf-metrics")]
63 let rq_begin_finished_ns = task_runtime::monotonic_now().as_nanos();
64 let (previous, current_policy, deadline_task_control) = {
65 let current = transaction.current().unwrap_or_else(|| {
66 task_runtime::fatal_invariant(0x5343_1207, cpu.owner().as_u32() as usize)
67 });
68 let previous_core = current.runtime_core();
69 if expected_current.is_some_and(|expected| !core::ptr::eq(expected, previous_core)) {
70 task_runtime::fatal_invariant(0x5343_1207, cpu.owner().as_u32() as usize);
71 }
72 (
73 previous_core.id(),
74 current.schedule_policy(),
75 current.metadata().deadline_bandwidth_scaled != 0,
76 )
77 };
78 let request = transaction.merge_scheduler_request(SchedulerRequestScope::All);
85 let migration_task_control = request.preemption_requested()
86 && transaction
87 .current_core_ref()
88 .is_some_and(|core| core.sched().placement().requested_migration().is_some());
89 let requires_task_control = deadline_task_control
90 || matches!(current_policy, SchedulePolicy::Deadline(_))
91 || migration_task_control;
92 let kept_class = if requires_task_control {
93 None
94 } else {
95 owner_yield_kept_class(&mut transaction, current_policy)
96 };
97 if let Some(kept_class) = kept_class {
98 if kept_class == SchedulerClass::Fair {
105 let _settled = transaction.settle_current(0);
106 }
107 #[cfg(feature = "qperf-metrics")]
108 {
109 let rq_preflight_finished_ns = task_runtime::monotonic_now().as_nanos();
110 crate::diagnostics::counters::qperf_record_switch_scheduler_detail(
111 10,
112 owner_entry_started_ns,
113 owner_drain_finished_ns,
114 );
115 crate::diagnostics::counters::qperf_record_switch_scheduler_detail(
116 11,
117 rq_begin_started_ns,
118 rq_begin_finished_ns,
119 );
120 crate::diagnostics::counters::qperf_record_switch_scheduler_detail(
121 12,
122 rq_begin_finished_ns,
123 rq_preflight_finished_ns,
124 );
125 }
126 let _ = self.finish_owner_no_switch(
127 cpu.as_mut(),
128 transaction,
129 previous,
130 SchedulerRequestScope::All,
131 OwnerSchedulerDeadline::Unchanged,
132 )?;
133 return Ok(YieldOutcome::Unchanged);
134 }
135 let schedule_out = {
136 let previous_core = transaction.current_core_ref().unwrap_or_else(|| {
137 task_runtime::fatal_invariant(0x5343_1207, cpu.owner().as_u32() as usize)
138 });
139 self.prepare_owner_rq_schedule_out(&transaction, previous_core)
140 };
141 if let Some(schedule_out) = schedule_out {
142 #[cfg(feature = "qperf-metrics")]
143 {
144 let rq_preflight_finished_ns = task_runtime::monotonic_now().as_nanos();
145 crate::diagnostics::counters::qperf_record_switch_scheduler_detail(
146 10,
147 owner_entry_started_ns,
148 owner_drain_finished_ns,
149 );
150 crate::diagnostics::counters::qperf_record_switch_scheduler_detail(
151 11,
152 rq_begin_started_ns,
153 rq_begin_finished_ns,
154 );
155 crate::diagnostics::counters::qperf_record_switch_scheduler_detail(
156 12,
157 rq_begin_finished_ns,
158 rq_preflight_finished_ns,
159 );
160 }
161 return Ok(if schedule_out.is_linked_realtime() {
162 self.yield_current_rq_owned::<true>(cpu.as_mut(), transaction, schedule_out)
163 } else {
164 self.yield_current_rq_owned::<false>(cpu.as_mut(), transaction, schedule_out)
165 });
166 }
167 let previous_core = transaction.current_core().unwrap_or_else(|| {
170 task_runtime::fatal_invariant(0x5343_1207, cpu.owner().as_u32() as usize)
171 });
172 let request = transaction.merge_scheduler_request(SchedulerRequestScope::All);
173 transaction.commit();
174
175 self.yield_current_task_control(cpu, previous_core.as_ref(), rq_entry, remote, request)
176 }
177}