ax_task/sched/system/cpu/remote/
owner.rs1use super::*;
2
3#[derive(Debug)]
4pub(super) struct OwnerState {
5 claimed: AtomicBool,
6 idle_thread: AtomicU64,
7 busy_runtime_ns: AtomicU64,
8}
9
10impl OwnerState {
11 pub(super) const fn new() -> Self {
12 Self {
13 claimed: AtomicBool::new(false),
14 idle_thread: AtomicU64::new(0),
15 busy_runtime_ns: AtomicU64::new(0),
16 }
17 }
18}
19
20impl CpuRemote {
21 pub const fn owner(&self) -> CpuId {
23 self.owner
24 }
25
26 pub unsafe fn claim_local(
34 &self,
35 cpu: *mut CpuLocal,
36 ) -> Result<CpuLocalOwnerBorrow<'_>, TaskError> {
37 let cpu = NonNull::new(cpu).ok_or(TaskError::InvalidRuntimeHandle)?;
38 self.owner_state
39 .claimed
40 .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
41 .map_err(|_| TaskError::CpuOwnerBorrowed)?;
42
43 let actual = unsafe { cpu.as_ref() }.owner();
47 if actual != self.owner {
48 self.owner_state.claimed.store(false, Ordering::Release);
49 return Err(TaskError::CpuOwnerMismatch {
50 expected: self.owner.as_u32(),
51 actual: actual.as_u32(),
52 });
53 }
54 #[cfg(feature = "qperf-metrics")]
55 crate::diagnostics::counters::record_runtime_cpu_owner_claim();
56 Ok(CpuLocalOwnerBorrow {
57 remote: self,
58 cpu,
59 release_claim: true,
60 _not_send_or_sync: PhantomData,
61 })
62 }
63
64 pub unsafe fn borrow_local_in_scheduler_frame(
72 &self,
73 cpu: NonNull<CpuLocal>,
74 ) -> CpuLocalOwnerBorrow<'_> {
75 CpuLocalOwnerBorrow {
76 remote: self,
77 cpu,
78 release_claim: false,
79 _not_send_or_sync: PhantomData,
80 }
81 }
82
83 pub fn current_thread(&self) -> Option<ThreadId> {
85 self.lock_run_queue(RunQueueGuardSource::OwnerCurrentThreadObservation)
86 .current_thread()
87 }
88
89 pub fn idle_thread(&self) -> Option<ThreadId> {
91 decode_thread_id(self.owner_state.idle_thread.load(Ordering::Acquire))
92 }
93
94 pub(in crate::sched::system::cpu) fn publish_idle_thread(&self, idle: ThreadId) {
95 self.owner_state
96 .idle_thread
97 .store(idle.as_u64(), Ordering::Release);
98 }
99
100 pub fn busy_runtime_ns(&self) -> u64 {
102 self.owner_state.busy_runtime_ns.load(Ordering::Relaxed)
103 }
104
105 pub(in crate::sched::system::cpu) fn charge_busy_runtime(&self, runtime_ns: u64) {
106 let committed = self.owner_state.busy_runtime_ns.load(Ordering::Relaxed);
110 self.owner_state
111 .busy_runtime_ns
112 .store(committed.saturating_add(runtime_ns), Ordering::Relaxed);
113 }
114}
115
116pub struct CpuLocalOwnerBorrow<'remote> {
123 remote: &'remote CpuRemote,
124 cpu: NonNull<CpuLocal>,
125 release_claim: bool,
126 _not_send_or_sync: PhantomData<*mut ()>,
127}
128
129impl CpuLocalOwnerBorrow<'_> {
130 pub fn as_pin_mut(&mut self) -> Pin<&mut CpuLocal> {
132 unsafe { Pin::new_unchecked(self.cpu.as_mut()) }
136 }
137}
138
139impl Deref for CpuLocalOwnerBorrow<'_> {
140 type Target = CpuLocal;
141
142 fn deref(&self) -> &Self::Target {
143 unsafe { self.cpu.as_ref() }
146 }
147}
148
149impl Drop for CpuLocalOwnerBorrow<'_> {
150 fn drop(&mut self) {
151 if self.release_claim {
152 self.remote
153 .owner_state
154 .claimed
155 .store(false, Ordering::Release);
156 }
157 }
158}
159
160fn decode_thread_id(raw: u64) -> Option<ThreadId> {
161 (raw != 0).then(|| ThreadId::from_parts(raw as u32, (raw >> 32) as u32))
162}