use alloc::sync::Arc;
use super::*;
pub fn spawn_raw<F>(entry: F, name: String, stack_size: usize) -> Result<ThreadHandle, TaskError>
where
F: FnOnce() + Send + 'static,
{
unsafe { spawn_raw_with_extension(entry, name, stack_size, None) }
}
pub fn prepare_raw<F>(
entry: F,
name: String,
stack_size: usize,
) -> Result<PreparedThread, TaskError>
where
F: FnOnce() + Send + 'static,
{
unsafe {
prepare_raw_with_options(
entry,
name,
stack_size,
None,
None,
SchedulePolicy::default(),
InitialContextState::kernel(),
)
}
}
pub fn spawn_raw_with_affinity<F>(
entry: F,
name: String,
stack_size: usize,
affinity: CpuSet,
) -> Result<ThreadHandle, TaskError>
where
F: FnOnce() + Send + 'static,
{
unsafe { spawn_raw_with_extension_and_affinity(entry, name, stack_size, None, Some(affinity)) }
}
pub fn spawn_raw_with_policy_and_affinity<F>(
entry: F,
name: String,
stack_size: usize,
policy: SchedulePolicy,
affinity: CpuSet,
) -> Result<ThreadHandle, TaskError>
where
F: FnOnce() + Send + 'static,
{
unsafe {
spawn_raw_with_options(
entry,
name,
stack_size,
None,
Some(affinity),
policy,
InitialContextState::kernel(),
)
}
}
pub unsafe fn spawn_raw_with_extension<F>(
entry: F,
name: String,
stack_size: usize,
os_extension: Option<ThreadExtension>,
) -> Result<ThreadHandle, TaskError>
where
F: FnOnce() + Send + 'static,
{
unsafe { spawn_raw_with_extension_and_affinity(entry, name, stack_size, os_extension, None) }
}
pub unsafe fn spawn_raw_with_extension_and_affinity<F>(
entry: F,
name: String,
stack_size: usize,
os_extension: Option<ThreadExtension>,
affinity: Option<CpuSet>,
) -> Result<ThreadHandle, TaskError>
where
F: FnOnce() + Send + 'static,
{
unsafe {
spawn_raw_with_options(
entry,
name,
stack_size,
os_extension,
affinity,
SchedulePolicy::default(),
InitialContextState::kernel(),
)
}
}
pub unsafe fn spawn_raw_with_extension_in_address_space<F>(
entry: F,
name: String,
stack_size: usize,
os_extension: Option<ThreadExtension>,
address_space: TaskAddressSpace,
) -> Result<ThreadHandle, TaskError>
where
F: FnOnce() + Send + 'static,
{
unsafe {
spawn_raw_with_options(
entry,
name,
stack_size,
os_extension,
None,
SchedulePolicy::default(),
InitialContextState::user(address_space),
)
}
}
pub unsafe fn spawn_raw_with_extension_in_address_space_and_policy<F>(
entry: F,
name: String,
stack_size: usize,
os_extension: Option<ThreadExtension>,
address_space: TaskAddressSpace,
policy: SchedulePolicy,
) -> Result<ThreadHandle, TaskError>
where
F: FnOnce() + Send + 'static,
{
unsafe {
spawn_raw_with_options(
entry,
name,
stack_size,
os_extension,
None,
policy,
InitialContextState::user(address_space),
)
}
}
pub unsafe fn prepare_raw_with_extension_in_address_space_and_scheduler_state<F>(
entry: F,
name: String,
stack_size: usize,
os_extension: Option<ThreadExtension>,
address_space: TaskAddressSpace,
policy: SchedulePolicy,
affinity: CpuSet,
) -> Result<PreparedThread, TaskError>
where
F: FnOnce() + Send + 'static,
{
unsafe {
prepare_raw_with_options(
entry,
name,
stack_size,
os_extension,
Some(affinity),
policy,
InitialContextState::user(address_space),
)
}
}
#[cfg(all(target_arch = "riscv64", feature = "fp-simd"))]
pub unsafe fn spawn_raw_with_extension_in_address_space_and_fp_state<F>(
entry: F,
name: String,
stack_size: usize,
os_extension: Option<ThreadExtension>,
address_space: TaskAddressSpace,
fp_state: ax_hal::cpu::FpState,
) -> Result<ThreadHandle, TaskError>
where
F: FnOnce() + Send + 'static,
{
unsafe {
spawn_raw_with_options(
entry,
name,
stack_size,
os_extension,
None,
SchedulePolicy::default(),
InitialContextState::user_with_fp_state(address_space, fp_state),
)
}
}
#[cfg(all(target_arch = "riscv64", feature = "fp-simd"))]
pub unsafe fn spawn_raw_with_extension_in_address_space_and_fp_state_and_policy<F>(
entry: F,
name: String,
stack_size: usize,
os_extension: Option<ThreadExtension>,
address_space: TaskAddressSpace,
fp_state: ax_hal::cpu::FpState,
policy: SchedulePolicy,
) -> Result<ThreadHandle, TaskError>
where
F: FnOnce() + Send + 'static,
{
unsafe {
spawn_raw_with_options(
entry,
name,
stack_size,
os_extension,
None,
policy,
InitialContextState::user_with_fp_state(address_space, fp_state),
)
}
}
#[cfg(all(target_arch = "riscv64", feature = "fp-simd"))]
pub unsafe fn prepare_raw_with_extension_in_address_space_and_fp_scheduler_state<F>(
entry: F,
name: String,
stack_size: usize,
os_extension: Option<ThreadExtension>,
address_space: TaskAddressSpace,
fp_state: ax_hal::cpu::FpState,
policy: SchedulePolicy,
affinity: CpuSet,
) -> Result<PreparedThread, TaskError>
where
F: FnOnce() + Send + 'static,
{
unsafe {
prepare_raw_with_options(
entry,
name,
stack_size,
os_extension,
Some(affinity),
policy,
InitialContextState::user_with_fp_state(address_space, fp_state),
)
}
}
#[cfg(all(target_arch = "x86_64", feature = "fp-simd", feature = "uspace"))]
pub unsafe fn prepare_raw_with_extension_in_address_space_and_inherited_fp_scheduler_state<F>(
entry: F,
name: String,
stack_size: usize,
os_extension: Option<ThreadExtension>,
address_space: TaskAddressSpace,
policy: SchedulePolicy,
affinity: CpuSet,
) -> Result<PreparedThread, TaskError>
where
F: FnOnce() + Send + 'static,
{
if let Err(error) = context::validate_current_user_fp_clone_context() {
unsafe { release_transferred_extension(os_extension) };
return Err(error);
}
unsafe {
prepare_raw_with_options(
entry,
name,
stack_size,
os_extension,
Some(affinity),
policy,
InitialContextState::user_inheriting_current_fp_state(address_space),
)
}
}
unsafe fn spawn_raw_with_options<F>(
entry: F,
name: String,
stack_size: usize,
os_extension: Option<ThreadExtension>,
affinity: Option<CpuSet>,
policy: SchedulePolicy,
context_state: InitialContextState,
) -> Result<ThreadHandle, TaskError>
where
F: FnOnce() + Send + 'static,
{
unsafe {
prepare_raw_with_options(
entry,
name,
stack_size,
os_extension,
affinity,
policy,
context_state,
)
}?
.publish()
}
unsafe fn prepare_raw_with_options<F>(
entry: F,
name: String,
stack_size: usize,
os_extension: Option<ThreadExtension>,
affinity: Option<CpuSet>,
policy: SchedulePolicy,
context_state: InitialContextState,
) -> Result<PreparedThread, TaskError>
where
F: FnOnce() + Send + 'static,
{
if stack_size == 0 {
unsafe { release_transferred_extension(os_extension) };
return Err(TaskError::InvalidConfiguration);
}
let Some(system) = task_system() else {
unsafe { release_transferred_extension(os_extension) };
return Err(TaskError::NotInitialized);
};
let resources = match create_thread_resources(stack_size, runtime_thread_entry, context_state) {
Ok(resources) => resources,
Err(error) => {
unsafe { release_transferred_extension(os_extension) };
return Err(error);
}
};
let start = Arc::new(RuntimeThreadStart::new());
let data = Box::into_raw(Box::new(RuntimeThreadData::new(
Box::new(entry),
name,
os_extension,
Arc::clone(&start),
)))
.expose_provenance();
let extension = unsafe {
runtime_thread_extension(data)
};
let mut spec = unsafe {
ThreadSpec::new(policy)
.with_extension(extension)
.with_resources(resources)
};
if let Some(affinity) = affinity {
spec = spec.with_affinity(affinity);
}
let handle = system.create_thread(spec)?;
Ok(PreparedThread::new(system, handle, start))
}