1use safa_abi::{
2 errors::ErrorStatus,
3 raw::{
4 processes::{ContextPriority, SpawnFlags, TaskStdio},
5 Optional, RawSlice, RawSliceMut,
6 },
7};
8
9use crate::{
10 process::stdio::{systry_get_stderr, systry_get_stdin, systry_get_stdout},
11 syscalls::types::{OptionalPtrMut, OptionalStrPtr, Pid, Ri, StrPtr, SyscallResult},
12};
13
14use super::{define_syscall, SyscallNum};
15
16#[cfg(not(feature = "rustc-dep-of-std"))]
17extern crate alloc;
18use alloc::vec::Vec;
19
20define_syscall! {
21 SyscallNum::SysPExit => {
22 sysp_exit(code: usize) unreachable
24 },
25 SyscallNum::SysPWait => {
26 sysp_wait(pid: Pid, exit_code: OptionalPtrMut<usize>)
35 },
36 SyscallNum::SysPTryCleanUp => {
37 sysp_try_cleanup(pid: Pid, dest_exit_code: OptionalPtrMut<usize>)
44 },
45}
46
47#[inline]
49pub fn exit(code: usize) -> ! {
50 sysp_exit(code)
51}
52
53#[inline]
54pub fn wait(pid: Pid) -> Result<usize, ErrorStatus> {
63 let mut dest_exit_code = 0;
64 err_from_u16!(sysp_wait(pid, &mut dest_exit_code), dest_exit_code)
65}
66#[inline]
67pub fn try_cleanup(pid: Pid) -> Result<Option<usize>, ErrorStatus> {
74 let mut dest_exit_code = 0;
75 let results = err_from_u16!(sysp_try_cleanup(pid, &mut dest_exit_code), dest_exit_code);
76
77 match results {
78 Ok(results) => Ok(Some(results)),
79 Err(ErrorStatus::Generic) => Ok(None),
80 Err(e) => Err(e),
81 }
82}
83
84#[cfg_attr(
86 not(any(feature = "std", feature = "rustc-dep-of-std")),
87 unsafe(no_mangle)
88)]
89#[inline(always)]
90extern "C" fn sysp_spawn(
101 name_ptr: OptionalStrPtr,
102 name_len: usize,
103 path_ptr: StrPtr,
104 path_len: usize,
105 argv_ptr: OptionalPtrMut<RawSlice<u8>>,
107 argv_len: usize,
108 flags: SpawnFlags,
110 priority: Optional<ContextPriority>,
111 dest_pid: OptionalPtrMut<Pid>,
112 stdin: Optional<Ri>,
114 stdout: Optional<Ri>,
115 stderr: Optional<Ri>,
116) -> SyscallResult {
117 use safa_abi::raw::processes::PSpawnConfig;
118 let (stdin, stdout, stderr): (Option<_>, Option<_>, Option<_>) =
119 (stdin.into(), stdout.into(), stderr.into());
120
121 let stdio = {
122 if stdin.is_none() && stdout.is_none() && stderr.is_none() {
123 None
124 } else {
125 let stdout = stdout.or(systry_get_stdout().into());
126 let stdin = stdin.or(systry_get_stdin().into());
127 let stderr = stderr.or(systry_get_stderr().into());
128
129 Some(TaskStdio::new(stdout, stdin, stderr))
130 }
131 };
132
133 let stdio = stdio.as_ref();
134 let stdio_ptr = stdio.map(|m| m as *const _).unwrap_or(core::ptr::null());
135 let (_, mut env) = unsafe { crate::process::env::duplicate_env() };
136
137 let config = PSpawnConfig {
138 revision: 2,
139 name: unsafe { RawSlice::from_raw_parts(name_ptr, name_len) },
140 argv: unsafe { RawSliceMut::from_raw_parts(argv_ptr, argv_len) },
141 env: unsafe { RawSliceMut::from_raw_parts(env.as_mut_ptr(), env.len()) },
142 flags,
143 stdio: stdio_ptr,
144 priority,
145 };
146
147 syscall!(
148 SyscallNum::SysPSpawn,
149 path_ptr as usize,
150 path_len,
151 (&raw const config) as usize,
152 dest_pid as *mut _ as usize,
153 )
154}
155
156#[inline]
166pub unsafe fn unsafe_spawn(
167 name: Option<&str>,
168 path: &str,
169 argv: *mut [&str],
170 flags: SpawnFlags,
171 priority: Option<ContextPriority>,
172 stdin: Option<Ri>,
173 stdout: Option<Ri>,
174 stderr: Option<Ri>,
175) -> Result<Pid, ErrorStatus> {
176 let mut pid = 0;
177
178 let name = name.map(|s| s.as_bytes());
179 let name_ptr = name.map(|s| s.as_ptr()).unwrap_or(core::ptr::null());
180 let name_len = name.map(|s| s.len()).unwrap_or(0);
181
182 let argv = argv as *mut [&[u8]];
183 let argv = unsafe { RawSliceMut::from_slices(argv) };
184
185 err_from_u16!(
186 sysp_spawn(
187 name_ptr,
188 name_len,
189 path.as_ptr(),
190 path.len(),
191 argv.as_mut_ptr(),
192 argv.len(),
193 flags,
194 priority.into(),
195 &mut pid,
196 stdin.into(),
197 stdout.into(),
198 stderr.into(),
199 ),
200 pid
201 )
202}
203
204#[inline]
212pub fn spawn(
213 name: Option<&str>,
214 path: &str,
215 mut argv: Vec<&str>,
216 flags: SpawnFlags,
217 priority: Option<ContextPriority>,
218 stdin: Option<Ri>,
219 stdout: Option<Ri>,
220 stderr: Option<Ri>,
221) -> Result<Pid, ErrorStatus> {
222 let argv: &mut [&str] = &mut argv;
223 unsafe {
224 unsafe_spawn(
225 name,
226 path,
227 argv as *mut _,
228 flags,
229 priority,
230 stdin,
231 stdout,
232 stderr,
233 )
234 }
235}