use super::*;
impl CpuRunQueueState {
pub(in crate::sched::system::cpu) fn update_current(
&mut self,
runtime_ns: u64,
reclaimed_ns: u64,
deadline_extra_bw_scaled: u64,
) -> Result<RqCurrentUpdate, TaskError> {
self.update_current_for_event(
runtime_ns,
reclaimed_ns,
deadline_extra_bw_scaled,
CurrentAccountingEvent::RuntimeUpdate,
)
}
pub(in crate::sched::system::cpu) fn clock_event_current(
&mut self,
runtime_ns: u64,
reclaimed_ns: u64,
deadline_extra_bw_scaled: u64,
) -> Result<RqCurrentUpdate, TaskError> {
self.update_current_for_event(
runtime_ns,
reclaimed_ns,
deadline_extra_bw_scaled,
CurrentAccountingEvent::ClockEvent,
)
}
pub(in crate::sched::system::cpu) fn task_tick_current(
&mut self,
runtime_ns: u64,
reclaimed_ns: u64,
deadline_extra_bw_scaled: u64,
tick_ns: u64,
) -> Result<RqCurrentUpdate, TaskError> {
self.update_current_for_event(
runtime_ns,
reclaimed_ns,
deadline_extra_bw_scaled,
CurrentAccountingEvent::SchedulerTick { tick_ns },
)
}
pub(in crate::sched::system::cpu) fn task_tick_and_clock_event_current(
&mut self,
runtime_ns: u64,
reclaimed_ns: u64,
deadline_extra_bw_scaled: u64,
tick_ns: u64,
) -> Result<RqCurrentUpdate, TaskError> {
self.update_current_for_event(
runtime_ns,
reclaimed_ns,
deadline_extra_bw_scaled,
CurrentAccountingEvent::SchedulerTickWithClockEvent { tick_ns },
)
}
pub(super) fn update_current_for_event(
&mut self,
runtime_ns: u64,
reclaimed_ns: u64,
deadline_extra_bw_scaled: u64,
event: CurrentAccountingEvent,
) -> Result<RqCurrentUpdate, TaskError> {
let now_ns = self
.clock
.snapshot()
.ok_or(TaskError::InvalidConfiguration)?
.task()
.as_nanos();
let current_thread = self.current_thread().ok_or(TaskError::NoRunnableThread)?;
if self.idle() == Some(current_thread) {
self.queue
.current_mut()
.expect("current identity must retain its dispatch")
.account_dedicated_idle_until(now_ns);
return Ok(RqCurrentUpdate::DedicatedIdle);
}
let bandwidth = self.queue.deadline_bandwidth();
let (mut charge, policy, current_entity, rt_quota_exempt) = self.queue.charge_current(
runtime_ns,
now_ns,
bandwidth.inactive_bw_scaled(),
deadline_extra_bw_scaled,
bandwidth.max_bw_scaled(),
reclaimed_ns,
)?;
let deadline_replenish_reschedule = if charge.deadline_replenished {
self.queue
.requeue_replenished_deadline_current(current_thread)?
} else {
false
};
if let Some(current_fair) = current_entity.fair() {
self.queue.update_fair_virtual_time(Some(current_fair));
}
let class_tick = event.runs_class_tick(charge.slice_expired).then(|| {
SchedulerClass::for_policy(policy).task_tick(
&mut self.queue,
current_thread,
policy,
¤t_entity,
charge,
event.periodic_tick_ns(),
)
});
if class_tick.is_some_and(|tick| tick.slice_expired) {
charge.slice_expired = true;
}
let class_tick_reschedule = class_tick.is_some_and(|tick| tick.request_reschedule);
let deadline_runtime_reschedule =
matches!(policy, SchedulePolicy::Deadline(_)) && charge.slice_expired;
let reschedule = if deadline_runtime_reschedule || deadline_replenish_reschedule {
Some(RescheduleKind::Immediate)
} else {
class_tick_reschedule
.then_some(event.class_reschedule_kind(policy, charge.slice_expired))
};
Ok(RqCurrentUpdate::Task {
charge,
reschedule,
realtime: matches!(
policy,
SchedulePolicy::Fifo { .. } | SchedulePolicy::RoundRobin { .. }
),
rt_quota_exempt,
})
}
}