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}
37
38#[inline]
40pub fn exit(code: usize) -> ! {
41 sysp_exit(code)
42}
43
44#[inline]
45pub fn wait(pid: Pid) -> Result<usize, ErrorStatus> {
54 let mut dest_exit_code = 0;
55 err_from_u16!(sysp_wait(pid, &mut dest_exit_code), dest_exit_code)
56}
57
58#[cfg_attr(
60 not(any(feature = "std", feature = "rustc-dep-of-std")),
61 unsafe(no_mangle)
62)]
63#[inline(always)]
64extern "C" fn sysp_spawn(
75 name_ptr: OptionalStrPtr,
76 name_len: usize,
77 path_ptr: StrPtr,
78 path_len: usize,
79 argv_ptr: OptionalPtrMut<RawSlice<u8>>,
81 argv_len: usize,
82 flags: SpawnFlags,
84 priority: Optional<ContextPriority>,
85 dest_pid: OptionalPtrMut<Pid>,
86 stdin: Optional<Ri>,
88 stdout: Optional<Ri>,
89 stderr: Optional<Ri>,
90) -> SyscallResult {
91 use safa_abi::raw::processes::PSpawnConfig;
92 let (stdin, stdout, stderr): (Option<_>, Option<_>, Option<_>) =
93 (stdin.into(), stdout.into(), stderr.into());
94
95 let stdio = {
96 if stdin.is_none() && stdout.is_none() && stderr.is_none() {
97 None
98 } else {
99 let stdout = stdout.or(systry_get_stdout().into());
100 let stdin = stdin.or(systry_get_stdin().into());
101 let stderr = stderr.or(systry_get_stderr().into());
102
103 Some(TaskStdio::new(stdout, stdin, stderr))
104 }
105 };
106
107 let stdio = stdio.as_ref();
108 let stdio_ptr = stdio.map(|m| m as *const _).unwrap_or(core::ptr::null());
109 let (_, mut env) = unsafe { crate::process::env::duplicate_env() };
110
111 let config = PSpawnConfig {
112 revision: 2,
113 name: unsafe { RawSlice::from_raw_parts(name_ptr, name_len) },
114 argv: unsafe { RawSliceMut::from_raw_parts(argv_ptr, argv_len) },
115 env: unsafe { RawSliceMut::from_raw_parts(env.as_mut_ptr(), env.len()) },
116 flags,
117 stdio: stdio_ptr,
118 priority,
119 };
120
121 syscall!(
122 SyscallNum::SysPSpawn,
123 path_ptr as usize,
124 path_len,
125 (&raw const config) as usize,
126 dest_pid as *mut _ as usize,
127 )
128}
129
130#[inline]
140pub unsafe fn unsafe_spawn(
141 name: Option<&str>,
142 path: &str,
143 argv: *mut [&str],
144 flags: SpawnFlags,
145 priority: Option<ContextPriority>,
146 stdin: Option<Ri>,
147 stdout: Option<Ri>,
148 stderr: Option<Ri>,
149) -> Result<Pid, ErrorStatus> {
150 let mut pid = 0;
151
152 let name = name.map(|s| s.as_bytes());
153 let name_ptr = name.map(|s| s.as_ptr()).unwrap_or(core::ptr::null());
154 let name_len = name.map(|s| s.len()).unwrap_or(0);
155
156 let argv = argv as *mut [&[u8]];
157 let argv = unsafe { RawSliceMut::from_slices(argv) };
158
159 err_from_u16!(
160 sysp_spawn(
161 name_ptr,
162 name_len,
163 path.as_ptr(),
164 path.len(),
165 argv.as_mut_ptr(),
166 argv.len(),
167 flags,
168 priority.into(),
169 &mut pid,
170 stdin.into(),
171 stdout.into(),
172 stderr.into(),
173 ),
174 pid
175 )
176}
177
178#[inline]
186pub fn spawn(
187 name: Option<&str>,
188 path: &str,
189 mut argv: Vec<&str>,
190 flags: SpawnFlags,
191 priority: Option<ContextPriority>,
192 stdin: Option<Ri>,
193 stdout: Option<Ri>,
194 stderr: Option<Ri>,
195) -> Result<Pid, ErrorStatus> {
196 let argv: &mut [&str] = &mut argv;
197 unsafe {
198 unsafe_spawn(
199 name,
200 path,
201 argv as *mut _,
202 flags,
203 priority,
204 stdin,
205 stdout,
206 stderr,
207 )
208 }
209}