Skip to main content

ax_task/sched/system/task_system/deadline/
observation.rs

1//! Observation under the owning scheduler transaction.
2
3use super::*;
4
5impl TaskSystem {
6    /// Returns Deadline budget and PI rescue state for diagnostics and ABI glue.
7    pub fn deadline_runtime(&self, thread: ThreadId) -> Result<DeadlineRuntimeSnapshot, TaskError> {
8        let core = {
9            let state = self.state.lock();
10            Arc::clone(&state.thread_record(thread)?.core)
11        };
12        let sched = core.sched().lock();
13        let pi_boosted = sched.pi.deadline_donor.is_some();
14        let donor = sched.pi.deadline_donor;
15        let local_entity = core.sched().active_option(&sched).map(|active| {
16            if pi_boosted {
17                active.entity().clone()
18            } else {
19                active.base_entity().clone()
20            }
21        });
22        let effective_entity = if let Some(entity) = local_entity {
23            entity
24        } else {
25            let owner = sched
26                .placement
27                .assigned_cpu()
28                .ok_or(TaskError::InvalidConfiguration)?;
29            let remote = self
30                .cpu_remotes
31                .get(owner.as_usize())
32                .ok_or(TaskError::InvalidConfiguration)?;
33            // Keep the task-control lock across the owner-rq observation. This
34            // is the read-side equivalent of Linux `task_rq_lock()`: policy,
35            // placement, and CBS state come from one ordered transaction.
36            let transaction = OwnerRqTxn::begin(self, remote);
37            let entity = if pi_boosted {
38                transaction.scheduling_entity(thread)
39            } else {
40                transaction.base_scheduling_entity(thread)
41            };
42            let Some(entity) = entity else {
43                transaction.commit();
44                return Err(TaskError::InvalidConfiguration);
45            };
46            transaction.commit();
47            entity
48        };
49        let deadline = effective_entity
50            .deadline()
51            .ok_or(TaskError::InvalidConfiguration)?;
52        Ok(DeadlineRuntimeSnapshot {
53            remaining_runtime_ns: deadline.remaining_runtime_ns(),
54            overruns: deadline.overruns(),
55            pi_boosted,
56            donor,
57        })
58    }
59
60    /// Returns the thread's GRUB activity, zero-lag, and runqueue ownership.
61    pub fn deadline_activity(
62        &self,
63        thread: ThreadId,
64    ) -> Result<DeadlineActivitySnapshot, TaskError> {
65        let state = self.state.lock();
66        let record = state.thread_record(thread)?;
67        let sched = record.sched.lock();
68        if !matches!(sched.policy.base, SchedulePolicy::Deadline(_)) {
69            return Err(TaskError::InvalidConfiguration);
70        }
71        Ok(DeadlineActivitySnapshot {
72            activity: sched.deadline.bandwidth.activity(),
73            bandwidth_cpu: sched.deadline.bandwidth.reservation_owner(),
74            zero_lag_ns: sched
75                .deadline
76                .bandwidth
77                .zero_lag()
78                .map(SchedulerTimestamp::as_nanos),
79        })
80    }
81}