ax_task/thread/
current.rs1use alloc::sync::Arc;
4use core::marker::PhantomData;
5
6pub use crate::{
7 runtime::switch::dispatch::{
8 ExitPermit, commit_current_exit, exit_current_thread, prepare_current_exit,
9 yield_current_cpu,
10 },
11 sync::wait_queue::{sleep, sleep_until},
12 thread::{
13 current::park::{
14 CurrentParkDisposition, CurrentParkResume, CurrentParkStart, PreparedCurrentPark,
15 begin_current_park,
16 },
17 execution::exit_current,
18 },
19};
20use crate::{
21 runtime::{
22 context::{
23 RuntimeSchedulerFrameGuard, runtime_current_cpu_mut, runtime_task_system,
24 validate_schedule_context,
25 },
26 switch::{RuntimeScheduleOrigin, RuntimeSchedulerEntry, dispatch::execute_switch_plan},
27 task_runtime,
28 },
29 sched::CpuSet,
30 thread::{
31 CurrentThreadToken, TaskError, ThreadCore, ThreadExtensionLease, ThreadHandle, ThreadId,
32 },
33};
34
35pub fn current_thread_handle() -> Result<ThreadHandle, TaskError> {
43 #[cfg(feature = "qperf-metrics")]
44 crate::diagnostics::counters::record_current_thread_handle_query();
45 let publication = current_thread_publication()?;
46 unsafe { publication.acquire_handle() }
49}
50
51#[inline(always)]
53pub fn current_thread_id() -> Result<ThreadId, TaskError> {
54 let identity = current_thread_identity()?;
55 Ok(ThreadId::from_parts(identity.slot, identity.generation))
56}
57
58#[inline(always)]
60pub fn current_thread_token() -> Result<CurrentThreadToken, TaskError> {
61 Ok(CurrentThreadToken::new(current_thread_id()?))
62}
63
64#[inline(always)]
65pub(crate) fn current_thread_identity()
66-> Result<crate::runtime::switch::ThreadIdentityV1, TaskError> {
67 let identity = task_runtime::current_thread_identity();
68 if identity.is_bound() {
69 return Ok(identity);
70 }
71
72 let publication = task_runtime::current_thread_publication();
73 if publication.identity() != identity || !publication.owner().is_none() {
74 return Err(TaskError::InvalidRuntimeHandle);
75 }
76 let _system = runtime_task_system()?;
80 Err(TaskError::NoRunnableThread)
81}
82
83pub(crate) fn current_thread_publication()
84-> Result<crate::runtime::switch::CurrentThreadPublication, TaskError> {
85 let publication = task_runtime::current_thread_publication();
86 let identity = publication.identity();
87 if !identity.is_bound() {
88 if !publication.owner().is_none() {
89 return Err(TaskError::InvalidRuntimeHandle);
90 }
91 let _system = runtime_task_system()?;
96 return Err(TaskError::NoRunnableThread);
97 }
98 if publication.owner().is_none() {
99 return Err(TaskError::InvalidRuntimeHandle);
100 }
101 Ok(publication)
102}
103
104pub(crate) fn current_thread_core_arc() -> Result<Arc<ThreadCore>, TaskError> {
105 let publication = current_thread_publication()?;
106 unsafe { publication.acquire_scheduler_core() }
110}
111
112pub fn validate_blocking_context() -> Result<(), TaskError> {
117 acquire_blocking_permit().map(|_| ())
118}
119
120pub(crate) fn validate_rt_lock_context() -> Result<(), TaskError> {
122 validate_schedule_context(RuntimeScheduleOrigin::Block)
123}
124
125pub(crate) fn validate_sleeping_lock_context() -> Result<(), TaskError> {
126 if crate::runtime::task_runtime::in_hard_irq() || current_thread_core_arc()?.holds_rt_lock() {
127 return Err(TaskError::UnsafeContext);
128 }
129 Ok(())
130}
131
132pub(crate) struct BlockingPermit {
134 _not_send: PhantomData<*mut ()>,
135}
136
137pub(crate) fn acquire_blocking_permit() -> Result<BlockingPermit, TaskError> {
138 validate_schedule_context(RuntimeScheduleOrigin::Block)?;
139 let current = current_thread_core_arc()?;
140 if current.holds_rt_lock() && !current.in_rt_lock_wait() {
141 return Err(TaskError::UnsafeContext);
142 }
143 Ok(BlockingPermit {
144 _not_send: PhantomData,
145 })
146}
147
148pub fn current_thread_extension() -> Result<Option<ThreadExtensionLease>, TaskError> {
153 let handle = current_thread_handle()?;
154 Ok(handle
155 .extension_view()
156 .map(|view| ThreadExtensionLease::new(view, handle)))
157}
158
159pub fn set_current_thread_affinity(affinity: CpuSet) -> Result<(), TaskError> {
165 let mut scheduler_frame = RuntimeSchedulerFrameGuard::enter(
166 RuntimeScheduleOrigin::Yield,
167 RuntimeSchedulerEntry::Task,
168 )?;
169 let current = scheduler_frame.current_thread_ref()?;
170 let system = scheduler_frame.task_system();
171 let mut outcome = {
172 let mut cpu = runtime_current_cpu_mut(&mut scheduler_frame)?;
173 let must_migrate = system.set_current_affinity(cpu.as_mut(), affinity)?;
174 if !must_migrate {
175 return Ok(());
176 }
177
178 unsafe { system.yield_current_in_scheduler_frame(cpu.as_mut()) }.unwrap_or_else(|_| {
184 task_runtime::fatal_invariant(0x4558_0021, current.id().as_u64() as usize);
188 })
189 };
190 let decision = outcome.decision_mut().unwrap_or_else(|| {
191 task_runtime::fatal_invariant(0x4558_0022, current.id().as_u64() as usize)
192 });
193 execute_switch_plan(&mut scheduler_frame, decision);
194 Ok(())
195}
196pub(crate) mod park;