ax_task/sched/system/task_system/deadline/
overrun.rs1use super::*;
4
5impl TaskSystem {
6 pub(in crate::sched::system::task_system) fn publish_deadline_overrun_work(
7 &self,
8 core: Arc<ThreadCore>,
9 ) {
10 let core_ptr = Arc::into_raw(core);
11 let node = unsafe {
12 Pin::new_unchecked((&*core_ptr).deadline_callback_node())
15 };
16 let result = self.deferred_deadline_callbacks.publish(
17 node,
18 InboxMessage::deadline_overrun(
19 unsafe {
20 (*core_ptr).id()
22 },
23 core_ptr.expose_provenance(),
24 ),
25 );
26 if result == PublishResult::Published {
27 self.task_work.publish();
28 return;
29 }
30 unsafe {
31 drop(Arc::from_raw(core_ptr));
34 }
35 if result == PublishResult::WrongKind {
36 task_runtime::fatal_invariant(0x444c_0001, result as usize);
37 }
38 }
39
40 pub(super) fn task_deadline_error(error: TaskDeadlineError) -> TaskError {
41 match error {
42 TaskDeadlineError::Capacity => TaskError::TimerCapacity,
43 TaskDeadlineError::GenerationExhausted | TaskDeadlineError::KindMismatch => {
44 TaskError::InvalidConfiguration
45 }
46 }
47 }
48
49 pub fn dispatch_deadline_overruns(&self, limit: usize) -> Result<usize, TaskError> {
62 if task_runtime::in_hard_irq() {
63 return Err(TaskError::UnsafeContext);
64 }
65 let _consumer = self.task_work.try_claim_consumer()?;
66 self.dispatch_deadline_overruns_inner(limit)
67 .map(|(_, dispatched)| dispatched)
68 }
69
70 pub(in crate::sched::system::task_system) fn dispatch_deadline_overruns_inner(
71 &self,
72 limit: usize,
73 ) -> Result<(usize, usize), TaskError> {
74 const MAX_DISPATCH_BATCH: usize = 64;
75
76 let mut messages = [InboxMessage::EMPTY; MAX_DISPATCH_BATCH];
77 let batch = self
78 .deferred_deadline_callbacks
79 .drain(limit.min(MAX_DISPATCH_BATCH), &mut messages);
80 let mut dispatched = 0;
81 for message in messages.iter().take(batch.drained()) {
82 if message.operation() != InboxOperation::DeadlineOverrun || message.payload() == 0 {
83 task_runtime::fatal_invariant(0x444c_0002, message.payload());
84 }
85 let core = unsafe {
86 Arc::from_raw(ptr::with_exposed_provenance::<ThreadCore>(
89 message.payload(),
90 ))
91 };
92 if core.id() != message.thread_id() {
93 task_runtime::fatal_invariant(0x444c_0003, message.payload());
94 }
95 let claim = self
96 .state
97 .lock()
98 .claim_pending_deadline_overrun(core.id())?;
99 match claim {
100 DeadlineCallbackClaim::NoCallback { has_more } => {
101 if has_more {
102 self.publish_deadline_overrun_work(Arc::clone(&core));
103 }
104 }
105 DeadlineCallbackClaim::Callback { extension, thread } => {
106 unsafe {
110 (extension.ops().on_deadline_overrun)(extension.data(), thread);
111 }
112 if self.state.lock().finish_deadline_callback(thread)? {
113 self.publish_deadline_overrun_work(Arc::clone(&core));
114 }
115 dispatched += 1;
116 }
117 }
118 }
119 if batch.pending() {
120 self.task_work.publish();
121 }
122 Ok((batch.drained(), dispatched))
123 }
124}