1use alloc::sync::Arc;
2
3use super::*;
4
5pub fn spawn_raw<F>(entry: F, name: String, stack_size: usize) -> Result<ThreadHandle, TaskError>
7where
8 F: FnOnce() + Send + 'static,
9{
10 unsafe { spawn_raw_with_extension(entry, name, stack_size, None) }
12}
13
14pub fn prepare_raw<F>(
19 entry: F,
20 name: String,
21 stack_size: usize,
22) -> Result<PreparedThread, TaskError>
23where
24 F: FnOnce() + Send + 'static,
25{
26 unsafe {
27 prepare_raw_with_options(
29 entry,
30 name,
31 stack_size,
32 None,
33 None,
34 SchedulePolicy::default(),
35 InitialContextState::kernel(),
36 )
37 }
38}
39
40pub fn spawn_raw_with_affinity<F>(
42 entry: F,
43 name: String,
44 stack_size: usize,
45 affinity: CpuSet,
46) -> Result<ThreadHandle, TaskError>
47where
48 F: FnOnce() + Send + 'static,
49{
50 unsafe { spawn_raw_with_extension_and_affinity(entry, name, stack_size, None, Some(affinity)) }
53}
54
55pub fn spawn_raw_with_policy_and_affinity<F>(
58 entry: F,
59 name: String,
60 stack_size: usize,
61 policy: SchedulePolicy,
62 affinity: CpuSet,
63) -> Result<ThreadHandle, TaskError>
64where
65 F: FnOnce() + Send + 'static,
66{
67 unsafe {
70 spawn_raw_with_options(
71 entry,
72 name,
73 stack_size,
74 None,
75 Some(affinity),
76 policy,
77 InitialContextState::kernel(),
78 )
79 }
80}
81
82pub unsafe fn spawn_raw_with_extension<F>(
95 entry: F,
96 name: String,
97 stack_size: usize,
98 os_extension: Option<ThreadExtension>,
99) -> Result<ThreadHandle, TaskError>
100where
101 F: FnOnce() + Send + 'static,
102{
103 unsafe { spawn_raw_with_extension_and_affinity(entry, name, stack_size, os_extension, None) }
106}
107
108pub unsafe fn spawn_raw_with_extension_and_affinity<F>(
121 entry: F,
122 name: String,
123 stack_size: usize,
124 os_extension: Option<ThreadExtension>,
125 affinity: Option<CpuSet>,
126) -> Result<ThreadHandle, TaskError>
127where
128 F: FnOnce() + Send + 'static,
129{
130 unsafe {
131 spawn_raw_with_options(
133 entry,
134 name,
135 stack_size,
136 os_extension,
137 affinity,
138 SchedulePolicy::default(),
139 InitialContextState::kernel(),
140 )
141 }
142}
143
144pub unsafe fn spawn_raw_with_extension_in_address_space<F>(
152 entry: F,
153 name: String,
154 stack_size: usize,
155 os_extension: Option<ThreadExtension>,
156 address_space: TaskAddressSpace,
157) -> Result<ThreadHandle, TaskError>
158where
159 F: FnOnce() + Send + 'static,
160{
161 unsafe {
162 spawn_raw_with_options(
165 entry,
166 name,
167 stack_size,
168 os_extension,
169 None,
170 SchedulePolicy::default(),
171 InitialContextState::user(address_space),
172 )
173 }
174}
175
176pub unsafe fn spawn_raw_with_extension_in_address_space_and_policy<F>(
183 entry: F,
184 name: String,
185 stack_size: usize,
186 os_extension: Option<ThreadExtension>,
187 address_space: TaskAddressSpace,
188 policy: SchedulePolicy,
189) -> Result<ThreadHandle, TaskError>
190where
191 F: FnOnce() + Send + 'static,
192{
193 unsafe {
194 spawn_raw_with_options(
197 entry,
198 name,
199 stack_size,
200 os_extension,
201 None,
202 policy,
203 InitialContextState::user(address_space),
204 )
205 }
206}
207
208pub unsafe fn prepare_raw_with_extension_in_address_space_and_scheduler_state<F>(
222 entry: F,
223 name: String,
224 stack_size: usize,
225 os_extension: Option<ThreadExtension>,
226 address_space: TaskAddressSpace,
227 policy: SchedulePolicy,
228 affinity: CpuSet,
229) -> Result<PreparedThread, TaskError>
230where
231 F: FnOnce() + Send + 'static,
232{
233 unsafe {
234 prepare_raw_with_options(
235 entry,
236 name,
237 stack_size,
238 os_extension,
239 Some(affinity),
240 policy,
241 InitialContextState::user(address_space),
242 )
243 }
244}
245
246#[cfg(all(target_arch = "riscv64", feature = "fp-simd"))]
253pub unsafe fn spawn_raw_with_extension_in_address_space_and_fp_state<F>(
254 entry: F,
255 name: String,
256 stack_size: usize,
257 os_extension: Option<ThreadExtension>,
258 address_space: TaskAddressSpace,
259 fp_state: ax_hal::cpu::FpState,
260) -> Result<ThreadHandle, TaskError>
261where
262 F: FnOnce() + Send + 'static,
263{
264 unsafe {
265 spawn_raw_with_options(
268 entry,
269 name,
270 stack_size,
271 os_extension,
272 None,
273 SchedulePolicy::default(),
274 InitialContextState::user_with_fp_state(address_space, fp_state),
275 )
276 }
277}
278
279#[cfg(all(target_arch = "riscv64", feature = "fp-simd"))]
286pub unsafe fn spawn_raw_with_extension_in_address_space_and_fp_state_and_policy<F>(
287 entry: F,
288 name: String,
289 stack_size: usize,
290 os_extension: Option<ThreadExtension>,
291 address_space: TaskAddressSpace,
292 fp_state: ax_hal::cpu::FpState,
293 policy: SchedulePolicy,
294) -> Result<ThreadHandle, TaskError>
295where
296 F: FnOnce() + Send + 'static,
297{
298 unsafe {
299 spawn_raw_with_options(
302 entry,
303 name,
304 stack_size,
305 os_extension,
306 None,
307 policy,
308 InitialContextState::user_with_fp_state(address_space, fp_state),
309 )
310 }
311}
312
313#[cfg(all(target_arch = "riscv64", feature = "fp-simd"))]
320pub unsafe fn prepare_raw_with_extension_in_address_space_and_fp_scheduler_state<F>(
321 entry: F,
322 name: String,
323 stack_size: usize,
324 os_extension: Option<ThreadExtension>,
325 address_space: TaskAddressSpace,
326 fp_state: ax_hal::cpu::FpState,
327 policy: SchedulePolicy,
328 affinity: CpuSet,
329) -> Result<PreparedThread, TaskError>
330where
331 F: FnOnce() + Send + 'static,
332{
333 unsafe {
334 prepare_raw_with_options(
335 entry,
336 name,
337 stack_size,
338 os_extension,
339 Some(affinity),
340 policy,
341 InitialContextState::user_with_fp_state(address_space, fp_state),
342 )
343 }
344}
345
346#[cfg(all(target_arch = "x86_64", feature = "fp-simd", feature = "uspace"))]
357pub unsafe fn prepare_raw_with_extension_in_address_space_and_inherited_fp_scheduler_state<F>(
358 entry: F,
359 name: String,
360 stack_size: usize,
361 os_extension: Option<ThreadExtension>,
362 address_space: TaskAddressSpace,
363 policy: SchedulePolicy,
364 affinity: CpuSet,
365) -> Result<PreparedThread, TaskError>
366where
367 F: FnOnce() + Send + 'static,
368{
369 if let Err(error) = context::validate_current_user_fp_clone_context() {
370 unsafe { release_transferred_extension(os_extension) };
373 return Err(error);
374 }
375 unsafe {
376 prepare_raw_with_options(
377 entry,
378 name,
379 stack_size,
380 os_extension,
381 Some(affinity),
382 policy,
383 InitialContextState::user_inheriting_current_fp_state(address_space),
384 )
385 }
386}
387
388unsafe fn spawn_raw_with_options<F>(
389 entry: F,
390 name: String,
391 stack_size: usize,
392 os_extension: Option<ThreadExtension>,
393 affinity: Option<CpuSet>,
394 policy: SchedulePolicy,
395 context_state: InitialContextState,
396) -> Result<ThreadHandle, TaskError>
397where
398 F: FnOnce() + Send + 'static,
399{
400 unsafe {
401 prepare_raw_with_options(
402 entry,
403 name,
404 stack_size,
405 os_extension,
406 affinity,
407 policy,
408 context_state,
409 )
410 }?
411 .publish()
412}
413
414unsafe fn prepare_raw_with_options<F>(
415 entry: F,
416 name: String,
417 stack_size: usize,
418 os_extension: Option<ThreadExtension>,
419 affinity: Option<CpuSet>,
420 policy: SchedulePolicy,
421 context_state: InitialContextState,
422) -> Result<PreparedThread, TaskError>
423where
424 F: FnOnce() + Send + 'static,
425{
426 if stack_size == 0 {
427 unsafe { release_transferred_extension(os_extension) };
429 return Err(TaskError::InvalidConfiguration);
430 }
431 let Some(system) = task_system() else {
432 unsafe { release_transferred_extension(os_extension) };
434 return Err(TaskError::NotInitialized);
435 };
436 let resources = match create_thread_resources(stack_size, runtime_thread_entry, context_state) {
437 Ok(resources) => resources,
438 Err(error) => {
439 unsafe { release_transferred_extension(os_extension) };
441 return Err(error);
442 }
443 };
444 let start = Arc::new(RuntimeThreadStart::new());
445 let data = Box::into_raw(Box::new(RuntimeThreadData::new(
446 Box::new(entry),
447 name,
448 os_extension,
449 Arc::clone(&start),
450 )))
451 .expose_provenance();
452 let extension = unsafe {
455 runtime_thread_extension(data)
457 };
458 let mut spec = unsafe {
459 ThreadSpec::new(policy)
462 .with_extension(extension)
463 .with_resources(resources)
464 };
465 if let Some(affinity) = affinity {
466 spec = spec.with_affinity(affinity);
467 }
468 let handle = system.create_thread(spec)?;
469 Ok(PreparedThread::new(system, handle, start))
470}