1use alloc::{boxed::Box, string::String};
4use core::{
5 pin::Pin,
6 ptr,
7 sync::atomic::{AtomicBool, AtomicI32, Ordering},
8};
9
10use ax_hal::percpu::CpuPin;
11use ax_lazyinit::LazyInit;
12use ax_task::{
13 runtime::{
14 RuntimeHandleResult, RuntimeStatus, TaskSystem, TaskSystemHandle,
15 config::TaskSystemConfig,
16 cpu::{
17 CpuLocal, CpuRemote, CpuRemoteHandle, CurrentCpuLocalHandle, CurrentCpuOwnerHandles,
18 IrqGuardToken, RuntimeCpuId,
19 },
20 resource::{
21 AddressSpaceDestroyOutcome, AddressSpaceHandle, AddressSpaceMembarrierState,
22 AddressSpaceReclaimArmOutcome, ExecutionContextHandle, KernelContextRequest,
23 MembarrierRegistration, MembarrierRegistrationPhase, RuntimeMembarrierAction,
24 StackHandle, StackRequest, ThreadResources, TlsHandle, UserContextRequest,
25 },
26 service::SchedulerTickWorkDisposition,
27 switch::{
28 ContextThreadBinding, CurrentThreadPublication, RuntimeSchedulerFrameEnterResult,
29 RuntimeSwitchPlan, SchedSwitchRecord, ThreadIdentityV1,
30 },
31 task_runtime::impl_trait as impl_task_runtime,
32 },
33 sched::{CpuId, CpuSet, FairMode, Nice, SchedulePolicy},
34 sync::WaitQueue,
35 thread::{
36 SwitchReason, TaskError, ThreadExtension, ThreadExtensionOps, ThreadHandle, ThreadId,
37 ThreadSpec,
38 current::{current_thread_extension, current_thread_handle, current_thread_id},
39 },
40};
41
42mod address_space;
43mod mm_activation;
44pub use mm_activation::{
45 AddressSpaceSwitchProof, SchedulerAddressSpaceActivation, SchedulerAddressSpaceOwner,
46 UserAddressSpaceOwner,
47};
48mod bootstrap;
49pub(crate) mod context;
50
51mod lifecycle;
52mod resources;
53pub(crate) mod runtime_impl;
54pub(crate) mod scheduler_events;
55mod spawn;
56mod thread_resources;
57#[cfg(feature = "uspace")]
58mod user_entry;
59
60pub use address_space::{
61 AddressSpaceCpuState, TaskAddressSpace, detach_current_address_space,
62 switch_current_address_space,
63};
64use address_space::{
65 arm_runtime_address_space_reclaim, destroy_runtime_address_space,
66 release_current_active_address_space, runtime_address_space_membarrier_state,
67 update_runtime_address_space_membarrier_state,
68};
69#[cfg(feature = "uspace")]
70use bootstrap::current_cpu_remote;
71#[cfg(feature = "tls")]
72pub(crate) use bootstrap::initialize_early_bootstrap_tls;
73#[cfg(test)]
74use bootstrap::{IdleEntryAction, idle_entry_action};
75pub(crate) use bootstrap::{
76 PublishedCpuOnline, initialize_primary, publish_current_cpu_online,
77 start_current_ktimer_service, start_deferred_task_work_service,
78};
79use bootstrap::{
80 cpu_remote, current_cpu_owner_handles, idle_context_entry, primary_bootstrap_thread,
81 scheduler_current_cpu_remote_handle, task_system, with_current_cpu_local_mut_owner,
82 with_current_cpu_pin,
83};
84#[cfg(feature = "smp")]
85pub(crate) use bootstrap::{initialize_secondary, run_idle};
86use context::{
87 bind_bootstrap_runtime_context, bind_runtime_context_thread, create_bootstrap_context,
88 create_runtime_context, create_user_runtime_context, destroy_runtime_context,
89 finish_runtime_context_switch_tail, scheduler_current_thread_identity,
90 scheduler_current_thread_publication, switch_runtime_context,
91};
92
93pub(crate) fn runtime_task_system_handle() -> TaskSystemHandle {
94 task_system().map_or(TaskSystemHandle::NONE, |system| {
95 unsafe { TaskSystemHandle::from_raw((system as *const TaskSystem).expose_provenance()) }
98 })
99}
100
101pub(crate) fn scheduler_frame_capabilities(cpu_pin: &CpuPin) -> RuntimeSchedulerFrameEnterResult {
102 unsafe {
107 RuntimeSchedulerFrameEnterResult::success(
108 runtime_task_system_handle(),
109 current_cpu_owner_handles(cpu_pin),
110 )
111 }
112}
113
114#[cfg(feature = "uspace")]
115pub(crate) fn current_cpu_needs_reschedule_pinned(cpu_pin: &CpuPin) -> Result<bool, TaskError> {
116 Ok(current_cpu_remote(cpu_pin)
117 .ok_or(TaskError::NotInitialized)?
118 .needs_reschedule())
119}
120
121#[cfg(feature = "tls")]
122use resources::runtime_tls_pointer;
123use resources::{
124 allocate_runtime_stack, allocate_runtime_tls, deallocate_runtime_stack, deallocate_runtime_tls,
125};
126pub(crate) use scheduler_events::{on_clock_event, publish_scheduler_tick};
127#[cfg(feature = "qperf-metrics")]
128pub(crate) use scheduler_events::{
129 record_irq_return_scheduler_continuation, record_irq_return_scheduler_window,
130};
131
132#[cfg(axtest)]
134pub fn kernel_thread_retains_active_mm_membarrier_state_for_test() -> bool {
135 static IDENTITY_ANCHOR: u8 = 0;
136
137 let identity_raw = (&IDENTITY_ANCHOR as *const u8).expose_provenance();
138 let identity =
141 unsafe { ax_task::runtime::resource::AddressSpaceMembarrierId::from_raw(identity_raw) };
142 let active_mm_state =
145 unsafe { ax_task::runtime::resource::AddressSpaceMembarrierState::new(identity, 0) };
146
147 ax_task::runtime::resource::scheduled_membarrier_state_for_test(
148 active_mm_state,
149 ax_task::runtime::resource::AddressSpaceMembarrierState::NONE,
150 ) == active_mm_state
151}
152pub fn reset_current_user_fp_state() -> Result<(), TaskError> {
154 context::reset_current_user_fp_state()
155}
156
157#[cfg(all(target_arch = "x86_64", feature = "fp-simd", feature = "uspace"))]
159pub fn capture_current_user_fp_state() -> Result<ax_hal::cpu::UserXstate, TaskError> {
160 context::capture_current_user_fp_state()
161}
162
163#[cfg(all(target_arch = "x86_64", feature = "fp-simd", feature = "uspace"))]
165pub fn replace_current_user_fp_state(state: ax_hal::cpu::UserXstate) -> Result<(), TaskError> {
166 context::replace_current_user_fp_state(state)
167}
168pub use lifecycle::{
169 PreparedThread, StagedThread, ThreadOsExtensionBorrow, ThreadOsExtensionLease,
170 current_os_extension, exit_current, join_thread, thread_os_extension, wait_thread,
171};
172#[cfg(test)]
173use lifecycle::{
174 RUNTIME_THREAD_EXTENSION_OPS, RuntimeExtensionKind, classify_runtime_extension,
175 extension_data_after_releasing_lease,
176};
177use lifecycle::{
178 RuntimeThreadData, RuntimeThreadStart, finish_initial_scheduler_switch,
179 release_transferred_extension, runtime_thread_entry, runtime_thread_extension,
180};
181#[cfg(all(feature = "qperf-metrics", any(feature = "ipi", feature = "wake-ipi")))]
182pub(crate) use scheduler_events::{record_scheduler_ipi_consume, record_scheduler_ipi_send};
183#[cfg(all(target_arch = "x86_64", feature = "fp-simd", feature = "uspace"))]
184pub use spawn::prepare_raw_with_extension_in_address_space_and_inherited_fp_scheduler_state;
185pub use spawn::{
186 prepare_raw, prepare_raw_with_extension_in_address_space_and_scheduler_state, spawn_raw,
187 spawn_raw_with_affinity, spawn_raw_with_extension, spawn_raw_with_extension_and_affinity,
188 spawn_raw_with_extension_in_address_space,
189 spawn_raw_with_extension_in_address_space_and_policy, spawn_raw_with_policy_and_affinity,
190};
191#[cfg(all(target_arch = "riscv64", feature = "fp-simd"))]
192pub use spawn::{
193 prepare_raw_with_extension_in_address_space_and_fp_scheduler_state,
194 spawn_raw_with_extension_in_address_space_and_fp_state,
195 spawn_raw_with_extension_in_address_space_and_fp_state_and_policy,
196};
197#[cfg(all(test, feature = "tls"))]
198use thread_resources::assemble_bootstrap_resources;
199use thread_resources::{
200 InitialContextState, create_bootstrap_resources, create_idle_resources, create_thread_resources,
201};
202#[cfg(test)]
203use thread_resources::{
204 ThreadResourceBackend, UnreleasedThreadResources, create_thread_resources_with,
205};
206#[cfg(feature = "uspace")]
207pub use user_entry::UserExecutionContext;
208
209const PAGE_SIZE: usize = 4096;
210
211#[cfg(not(feature = "fs"))]
212const DEFAULT_TASK_STACK_SIZE: usize = 256 * 1024;
213
214const fn runtime_status_error(status: RuntimeStatus) -> TaskError {
215 TaskError::RuntimeFailure(status as u32)
216}
217
218const fn runtime_task_stack_size() -> usize {
219 #[cfg(feature = "fs")]
220 {
221 crate::build_info::TASK_STACK_SIZE
222 }
223 #[cfg(not(feature = "fs"))]
224 {
225 DEFAULT_TASK_STACK_SIZE
226 }
227}
228
229pub const fn default_task_stack_size() -> usize {
231 runtime_task_stack_size()
232}
233
234#[cfg(test)]
235mod tests;