use ax_task::thread::{PreparedThread, ThreadBuilder};
use super::*;
pub fn builder(name: String) -> ThreadBuilder {
ThreadBuilder::new(name)
.stack_size(default_task_stack_size())
.guard_size(if cfg!(feature = "stack-guard-page") {
PAGE_SIZE
} else {
0
})
}
pub struct UserContextOptions {
pub(super) address_space: TaskAddressSpace,
#[cfg(all(target_arch = "riscv64", feature = "fp-simd"))]
pub(super) fp_state: Option<ax_hal::cpu::registers::FpState>,
#[cfg(all(not(target_arch = "riscv64"), feature = "fp-simd", feature = "uspace"))]
pub(super) inherit_current_fp: bool,
}
impl UserContextOptions {
pub fn new(address_space: TaskAddressSpace) -> Self {
Self {
address_space,
#[cfg(all(target_arch = "riscv64", feature = "fp-simd"))]
fp_state: None,
#[cfg(all(not(target_arch = "riscv64"), feature = "fp-simd", feature = "uspace"))]
inherit_current_fp: false,
}
}
#[cfg(all(target_arch = "riscv64", feature = "fp-simd"))]
pub fn with_fp_state(mut self, state: ax_hal::cpu::registers::FpState) -> Self {
self.fp_state = Some(state);
self
}
#[cfg(all(not(target_arch = "riscv64"), feature = "fp-simd", feature = "uspace"))]
pub fn inherit_current_fp(mut self) -> Self {
self.inherit_current_fp = true;
self
}
}
pub unsafe fn prepare_user_thread(
builder: ThreadBuilder,
entry: impl FnOnce() + Send + 'static,
options: UserContextOptions,
) -> Result<PreparedThread, TaskError> {
#[cfg(all(not(target_arch = "riscv64"), feature = "fp-simd", feature = "uspace"))]
if options.inherit_current_fp {
context::validate_current_user_fp_clone_context()?;
}
unsafe {
builder.prepare_with(entry, |request, trampoline| {
create_user_resources(request, trampoline, options)
})
}
}
pub fn exit_current(code: i32) -> ! {
if primary_bootstrap_thread() == current_thread_id().ok() {
crate::terminate();
}
ax_task::thread::current::exit_current(code)
}