use core::{num::NonZero, time::Duration};
use safa_abi::{
errors::ErrorStatus,
process::{RawContextPriority, RawTSpawnConfig},
};
use crate::{
exported_func,
syscalls::types::{Cid, OptionalPtrMut, RequiredPtr, RequiredPtrMut, SyscallResult},
};
use super::{define_syscall, SyscallNum};
define_syscall! {
SyscallNum::SysTExit => {
syst_exit(code: usize) unreachable
},
SyscallNum::SysTWait => {
syst_wait(cid: Cid)
},
SyscallNum::SysTSleep => {
syst_sleep(n: usize)
},
SyscallNum::SysTYield => {
sysyield()
},
}
#[inline]
pub fn exit(code: usize) -> ! {
syst_exit(code)
}
#[inline]
pub fn yield_now() {
debug_assert!(sysyield().is_success())
}
#[inline]
pub fn wait(cid: Cid) -> Result<(), ErrorStatus> {
err_from_u16!(syst_wait(cid))
}
#[inline]
pub fn sleep(duration: Duration) -> Result<(), ()> {
let ms: usize = duration.as_millis() as usize;
Ok(assert!(syst_sleep(ms).is_success()))
}
define_syscall! {
SyscallNum::SysTSpawn => {
syst_spawn_raw(entry_point: usize, config: RequiredPtr<RawTSpawnConfig>, dest_cid: OptionalPtrMut<Cid>)
},
}
exported_func! {
extern "C" fn syst_spawn(
entry_point: usize,
argument_ptr: *const (),
priority: RawContextPriority,
custom_stack_size: Option<NonZero<usize>>,
dest_cid: OptionalPtrMut<Cid>,
) -> SyscallResult {
let mut config = RawTSpawnConfig::new(
argument_ptr,
priority.into(),
None,
custom_stack_size.into(),
);
let config = unsafe {RequiredPtr::new_unchecked(&raw mut config)};
syst_spawn_raw(entry_point, config, dest_cid)
}
}
#[inline]
pub fn spawn3(
entry_point: fn(thread_id: Cid) -> !,
priority: RawContextPriority,
custom_stack_size: Option<NonZero<usize>>,
) -> Result<Cid, ErrorStatus> {
spawn_inner(
entry_point as usize,
core::ptr::null(),
priority,
custom_stack_size,
)
}
#[inline]
pub fn spawn2(
entry_point: fn(thread_id: Cid, argument: usize) -> !,
argument: usize,
priority: RawContextPriority,
custom_stack_size: Option<NonZero<usize>>,
) -> Result<Cid, ErrorStatus> {
spawn_inner(
entry_point as usize,
argument as *const (),
priority,
custom_stack_size,
)
}
#[inline]
pub fn spawn<T>(
entry_point: fn(thread_id: Cid, argument_ptr: &'static T) -> !,
argument_ptr: &'static T,
priority: RawContextPriority,
custom_stack_size: Option<NonZero<usize>>,
) -> Result<Cid, ErrorStatus> {
spawn_inner(
entry_point as usize,
argument_ptr as *const T as *const (),
priority,
custom_stack_size,
)
}
#[inline(always)]
fn spawn_inner(
entry_point: usize,
argument_ptr: *const (),
priority: RawContextPriority,
custom_stack_size: Option<NonZero<usize>>,
) -> Result<Cid, ErrorStatus> {
let mut cid = 0;
let ptr = RequiredPtrMut::new(&raw mut cid).into();
err_from_u16!(
syst_spawn(
entry_point,
argument_ptr,
priority.into(),
custom_stack_size.into(),
ptr
),
cid
)
}