1use core::{
4 ffi::{c_char, c_int, c_ulong, c_void},
5 sync::atomic::Ordering,
6};
7
8use alloc::{string::ToString, sync::Arc, vec::Vec};
9
10use crate::{
11 arch::{
12 timer::{clock_freq, get_time},
13 trap::{SumGuard, restore},
14 },
15 ipc::{SignalHandlerTable, SignalPending, signal_pending},
16 kernel::{
17 FUTEX_MANAGER, SCHEDULER, Scheduler, SharedTask, TASK_MANAGER, TIMER, TIMER_QUEUE,
18 TaskManagerTrait, TaskState, TaskStruct, TimerEntry, current_cpu, current_task,
19 exit_process, schedule, sleep_task_with_block, sleep_task_with_guard_and_block,
20 syscall::util::{get_args_safe, get_path_safe},
21 time::{REALTIME, realtime_now},
22 yield_task,
23 },
24 mm::{
25 address::{UsizeConvert, Vaddr},
26 frame_allocator::{alloc_contig_frames, alloc_frame},
27 memory_space::MemorySpace,
28 },
29 sync::SpinLock,
30 uapi::{
31 errno::{
32 EAGAIN, EFAULT, EINTR, EINVAL, EIO, EISDIR, ENOENT, ENOEXEC, ENOSYS, EPERM, ESRCH,
33 ETIMEDOUT,
34 },
35 futex::{FUTEX_CLOCK_REALTIME, FUTEX_PRIVATE, FUTEX_WAIT, FUTEX_WAKE, RobustListHead},
36 resource::{RLIM_NLIMITS, Rlimit, Rusage},
37 sched::CloneFlags,
38 signal::{NUM_SIGALRM, NUM_SIGPROF, NUM_SIGVTALRM},
39 time::{
40 Itimerval, TimeSpec,
41 clock_flags::TIMER_ABSTIME,
42 clock_id::{
43 CLOCK_BOOTTIME, CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID, CLOCK_REALTIME,
44 CLOCK_TAI,
45 },
46 itimer_id::{ITIMER_PROF, ITIMER_REAL, ITIMER_VIRTUAL},
47 },
48 types::{SizeT, StackT},
49 wait::{WaitFlags, WaitStatus},
50 },
51 util::user_buffer::{read_from_user, write_to_user},
52 vfs::FsError,
53};
54
55pub fn exit(code: c_int) -> c_int {
65 let task = current_task();
68 if task.lock().is_process() {
69 exit_process(task, code & 0xFF);
70 } else {
71 TASK_MANAGER.lock().exit_task(task, code & 0xFF);
72 }
73 schedule();
74 unreachable!("exit: exit_task should not return.");
75}
76
77pub fn exit_group(code: c_int) -> ! {
88 exit_process(current_task(), code & 0xFF);
90 schedule();
91 unreachable!("exit: exit_task should not return.");
92}
93
94pub fn clone(
103 flags: c_ulong, stack: c_ulong, ptid: *mut c_int, _tls: *mut c_void, ctid: *mut c_int, ) -> c_int {
109 let requested_flags = if let Some(requested_flags) = CloneFlags::from_bits(flags as usize) {
110 requested_flags
111 } else {
112 return -EINVAL;
113 };
114 if !requested_flags.is_known() {
115 return -EINVAL;
116 }
117 if !requested_flags.is_supported() {
118 return -ENOSYS;
119 }
120 if requested_flags.contains(CloneFlags::VM) && stack == 0 {
123 return -EINVAL;
124 }
125 let tid = { TASK_MANAGER.lock().allocate_tid() };
126 let (
127 c_pid,
128 c_ppid,
129 c_pgid,
130 space,
131 signal_handlers,
132 blocked,
133 signal,
134 signal_stack,
135 ptf,
136 fd_table,
137 fs,
138 uts,
139 rlimit,
140 ) = {
141 let cpu = current_cpu().lock();
142 let task = cpu.current_task.as_ref().unwrap().lock();
143 (
144 task.pid,
145 task.ppid,
146 task.pgid,
147 task.memory_space
148 .clone()
149 .expect("fork: can only call fork on a user task."),
150 task.signal_handlers.clone(),
151 task.blocked,
152 task.shared_pending.clone(),
153 task.signal_stack.clone(),
154 task.trap_frame_ptr.load(Ordering::SeqCst),
155 task.fd_table.clone(),
156 task.fs.clone(),
157 task.uts_namespace.clone(),
158 task.rlimit.clone(),
159 )
160 };
161 let exit_signal = requested_flags.get_exit_signal();
162 let space = if requested_flags.contains(CloneFlags::VM) {
163 space
164 } else {
165 Arc::new(SpinLock::new(
166 space
167 .lock()
168 .clone_for_fork()
169 .expect("fork: clone memory space failed."),
170 ))
171 };
172 let fd_table = if requested_flags.contains(CloneFlags::FILES) {
173 fd_table
174 } else {
175 Arc::new(fd_table.clone_table())
176 };
177 let fs = if requested_flags.contains(CloneFlags::FS) {
178 fs
179 } else {
180 Arc::new(SpinLock::new(fs.lock().clone()))
181 };
182 let ppid = if requested_flags.contains(CloneFlags::PARENT) {
183 c_ppid
184 } else {
185 c_pid
186 };
187 let pid = if requested_flags.contains(CloneFlags::THREAD) {
188 c_pid
189 } else {
190 tid
191 };
192 let (signal, signal_handler, signal_stack) = if requested_flags.contains(CloneFlags::SIGHAND) {
193 (signal, signal_handlers, signal_stack)
194 } else {
195 (
196 Arc::new(SpinLock::new(SignalPending::empty())),
197 Arc::new(SpinLock::new(SignalHandlerTable::new())),
198 Arc::new(SpinLock::new(StackT::default())),
199 )
200 };
201
202 let kstack_tracker = alloc_contig_frames(4).expect("fork: alloc kstack failed.");
203 let trap_frame_tracker = alloc_frame().expect("fork: alloc trap frame failed");
204 let child_task = TaskStruct::utask_create(
205 tid,
206 pid,
207 ppid,
208 c_pgid,
209 TaskStruct::empty_children(),
210 kstack_tracker,
211 trap_frame_tracker,
212 space,
213 signal_handler,
214 blocked,
215 signal,
216 signal_stack,
217 exit_signal,
218 uts,
219 rlimit,
220 fd_table,
221 fs,
222 );
223
224 if requested_flags.contains(CloneFlags::CHILD_SETTID) {
225 unsafe {
226 write_to_user(ctid, tid as c_int);
227 }
228 }
229 if requested_flags.contains(CloneFlags::PARENT_SETTID) {
230 unsafe {
231 write_to_user(ptid, tid as c_int);
232 }
233 }
234
235 let tf = child_task.trap_frame_ptr.load(Ordering::SeqCst);
236 unsafe {
237 (*tf).set_clone_trap_frame(&*ptf, child_task.kstack_base, stack as usize);
238 }
239 let child_task = child_task.into_shared();
240 current_task()
241 .lock()
242 .children
243 .lock()
244 .push(child_task.clone());
245
246 TASK_MANAGER.lock().add_task(child_task.clone());
247 SCHEDULER.lock().add_task(child_task);
248 tid as c_int
249}
250
251pub fn execve(
258 path: *const c_char,
259 argv: *const *const c_char,
260 envp: *const *const c_char,
261) -> c_int {
262 let (path_str, argv_strings, envp_strings) = unsafe {
264 let _guard = SumGuard::new();
265 let path_str = match get_path_safe(path) {
266 Ok(s) => s.to_string(),
267 Err(_) => {
268 return FsError::InvalidArgument.to_errno() as i32;
269 }
270 };
271 let argv_strings = get_args_safe(argv, "argv").unwrap_or_else(|_| Vec::new());
272 let envp_strings = get_args_safe(envp, "envp").unwrap_or_else(|_| Vec::new());
273 (path_str, argv_strings, envp_strings)
274 };
275
276 let data = match crate::vfs::vfs_load_elf(&path_str) {
277 Ok(data) => data,
278 Err(FsError::NotFound) => return -ENOENT,
279 Err(FsError::IsDirectory) => return -EISDIR,
280 Err(_) => return -EIO,
281 };
282
283 let (data, argv_strings, envp_strings) =
284 if data.len() >= 2 && data[0] == b'#' && data[1] == b'!' {
285 if let Ok((path, args)) = parse_hashbang(&data) {
286 let mut new_argv = Vec::new();
287 new_argv.push(path.to_string());
288 if let Some(arg) = args {
290 new_argv.push(arg.to_string());
291 }
292 new_argv.push(path_str.clone()); new_argv.extend(argv_strings.iter().skip(1).cloned());
294 let data = match crate::vfs::vfs_load_elf(path) {
295 Ok(d) => d,
296 Err(FsError::NotFound) => return -ENOENT,
297 Err(FsError::IsDirectory) => return -EISDIR,
298 Err(_) => return -EIO,
299 };
300 (data, new_argv, envp_strings)
301 } else {
302 return -EINVAL;
303 }
304 } else {
305 (data, argv_strings, envp_strings)
306 };
307
308 let (space, entry, sp, phdr_addr, phnum, phent) = match do_execve_prepare(&data) {
314 Ok(res) => res,
315 Err(e) => return e,
316 };
317
318 crate::earlyprintln!(
320 "[execve] Dropping {} byte ELF buffer before switching to user space",
321 data.len()
322 );
323 drop(data);
324
325 drop(path_str);
327
328 do_execve_switch(
330 space,
331 entry,
332 sp,
333 argv_strings, envp_strings, phdr_addr,
336 phnum,
337 phent,
338 )
339}
340
341pub fn wait4(pid: c_int, wstatus: *mut c_int, options: c_int, _rusage: *mut Rusage) -> c_int {
364 let cur_task = current_cpu().lock().current_task.as_ref().unwrap().clone();
366 let opt = if let Some(opt) = WaitFlags::from_bits(options as usize) {
367 opt
368 } else {
369 return -EINVAL;
370 };
371 let cur_pgid = cur_task.lock().pgid;
372 let match_pid = |child_task: &SharedTask| {
373 match pid {
374 -1 => true, 0 => child_task.lock().pgid == cur_pgid, p if p > 0 => child_task.lock().pid == p as u32, p if p < -1 => child_task.lock().pgid == (-p) as u32, _ => unreachable!("wait4: unreachable pid match case."),
379 }
380 };
381 let check_exited = opt.contains(WaitFlags::EXITED)
382 || (!opt.contains(WaitFlags::STOPPED) && !opt.contains(WaitFlags::CONTINUED));
383
384 let zombie: fn(TaskState) -> bool = if check_exited {
385 |ch| ch == TaskState::Zombie
386 } else {
387 |_ch| false
388 };
389 let continued: fn(TaskState) -> bool = if opt.contains(WaitFlags::CONTINUED) {
390 |ch| ch == TaskState::Running
391 } else {
392 |_ch| false
393 };
394 let stopped: fn(TaskState) -> bool = if opt.contains(WaitFlags::STOPPED) {
395 |ch| ch == TaskState::Stopped || ch == TaskState::Zombie
396 } else {
397 |_ch| false
398 };
399 let cond = |ch: &SharedTask| {
400 if !match_pid(ch) {
401 return false;
402 }
403 let state = ch.lock().state;
404 zombie(state) || continued(state) || stopped(state)
405 };
406
407 let task = loop {
408 {
409 let mut t = cur_task.lock();
410 if let Some(res) = t.check_child(cond, !opt.contains(WaitFlags::NOWAIT)) {
411 crate::pr_debug!("wait4: found child pid={}", res.lock().pid);
412 break res;
413 } else {
414 if opt.contains(WaitFlags::NOHANG) {
415 return 0;
416 }
417 }
418 {
419 let mut wc = t.wait_child.lock();
420 if !wc.contains(&cur_task) {
421 wc.add_task(cur_task.clone());
422 }
423 }
424 sleep_task_with_guard_and_block(&mut t, cur_task.clone(), true);
425 }
426 yield_task();
428 };
429
430 let (tid, state, exit_code) = {
431 let t = task.lock();
432 (t.tid, t.state, t.exit_code)
433 };
434
435 let status = match state {
436 TaskState::Zombie => {
437 WaitStatus::exit_code(exit_code.expect("Zombie must set exit code.") as u8, 0)
439 }
440 TaskState::Stopped => {
441 WaitStatus::stop_code(0) }
443 TaskState::Running => WaitStatus::continued_code(),
444 _ => {
445 unreachable!("wait4: unexpected task state.")
446 }
447 };
448
449 unsafe {
450 write_to_user(wstatus, status.raw());
451 }
452
453 if state == TaskState::Zombie && !opt.contains(WaitFlags::NOWAIT) {
457 {
461 let parent = current_task();
462 let p_lock = parent.lock();
463 let mut children = p_lock.children.lock();
464 let old_len = children.len();
465 children.retain(|c| c.lock().tid != tid);
466 crate::earlyprintln!(
467 "[wait4] Removed from parent.children: {} -> {}",
468 old_len,
469 children.len()
470 );
471 }
472 TASK_MANAGER.lock().release_task(task);
473 }
474
475 tid as c_int
476}
477
478pub fn get_pid() -> c_int {
482 current_task().lock().pid as c_int
483}
484
485pub fn get_ppid() -> c_int {
489 current_task().lock().ppid as c_int
490}
491
492pub fn get_pgid(pid: c_int) -> c_int {
501 use crate::uapi::errno::ESRCH;
502
503 if pid == 0 {
504 return current_task().lock().pgid as c_int;
505 }
506
507 if pid < 0 {
508 return -ESRCH as c_int;
509 }
510
511 let manager = TASK_MANAGER.lock();
512 let task_opt = manager.get_task(pid as u32);
513 drop(manager);
514
515 match task_opt {
516 Some(task) => task.lock().pgid as c_int,
517 None => -ESRCH as c_int,
518 }
519}
520
521pub fn set_pgid(pid: c_int, pgid: c_int) -> c_int {
523 use crate::uapi::errno::{EACCES, EINVAL, EPERM, ESRCH};
524
525 let current = current_task();
526 let current_locked = current.lock();
527 let current_pid = current_locked.tid as c_int;
528 let current_ppid = current_locked.ppid as c_int;
529 drop(current_locked);
530
531 let target_pid = if pid == 0 { current_pid } else { pid };
532 let target_pgid = if pgid == 0 { target_pid } else { pgid };
533
534 if target_pgid < 0 {
535 return -EINVAL as c_int;
536 }
537
538 let manager = TASK_MANAGER.lock();
539 let task_opt = manager.get_task(target_pid as u32);
540 drop(manager);
541
542 let task = match task_opt {
543 Some(t) => t,
544 None => return -ESRCH as c_int,
545 };
546
547 let mut task_locked = task.lock();
548
549 if target_pid != current_pid && task_locked.ppid as c_int != current_pid {
551 return -ESRCH as c_int;
552 }
553
554 if task_locked.pgid == task_locked.tid {
556 return -EPERM as c_int;
557 }
558
559 task_locked.pgid = target_pgid as u32;
561 0
562}
563
564pub fn getrlimit(resource: c_int, rlim: *mut Rlimit) -> c_int {
571 if resource as usize >= RLIM_NLIMITS {
572 return -EINVAL;
573 }
574 let rlimit = current_task().lock().rlimit.lock().limits[resource as usize];
575 unsafe {
576 write_to_user(rlim, rlimit);
577 }
578 0
579 }
581
582pub fn setrlimit(resource: c_int, rlim: *const Rlimit) -> c_int {
589 if resource as usize >= RLIM_NLIMITS {
590 return -EINVAL;
591 }
592 let new_limit = unsafe { read_from_user(rlim) };
593 if new_limit.rlim_cur > new_limit.rlim_max {
594 return -EINVAL;
595 }
596 {
597 let rlimit_lock = current_task().lock().rlimit.clone();
598 rlimit_lock.lock().limits[resource as usize] = new_limit;
599 }
600 0
601 }
603
604pub fn prlimit(
613 pid: c_int,
614 resource: c_int,
615 new_limit: *const Rlimit,
616 old_limit: *mut Rlimit,
617) -> c_int {
618 if resource as usize >= RLIM_NLIMITS {
619 return -EINVAL;
620 }
621 let target_task = if pid == 0 {
622 current_task()
623 } else {
624 let tm = TASK_MANAGER.lock();
625 match tm.get_task(pid as u32) {
626 Some(t) => t,
627 None => return -ESRCH,
628 }
629 };
630
631 if !old_limit.is_null() {
632 let rlimit = target_task.lock().rlimit.lock().limits[resource as usize];
633 unsafe {
634 write_to_user(old_limit, rlimit);
635 }
636 }
637
638 if !new_limit.is_null() {
639 let new_rlim = unsafe { read_from_user(new_limit) };
640 if new_rlim.rlim_cur > new_rlim.rlim_max {
641 return -EINVAL;
642 }
643 let rlimit_lock = target_task.lock().rlimit.clone();
644 rlimit_lock.lock().limits[resource as usize] = new_rlim;
645 }
646
647 0
648 }
650
651pub fn nanosleep(duration: *const TimeSpec, rem: *mut TimeSpec) -> c_int {
658 let req = unsafe { read_from_user(duration) };
659 if req.tv_sec == 0 && req.tv_nsec == 0 {
660 return 0;
661 }
662 if req.tv_sec < 0 || req.tv_nsec < 0 || req.tv_nsec > 999999999 {
663 return -EINVAL;
664 }
665 let mut result = 0;
666 let task = current_task();
667 let trigger = get_time() + req.into_freq(clock_freq());
668
669 let mut timer_q = TIMER_QUEUE.lock();
670 timer_q.push(trigger, task.clone());
671 sleep_task_with_block(task.clone(), true);
672 drop(timer_q);
673 yield_task();
674
675 TIMER_QUEUE.lock().remove_task(&task);
679
680 if !rem.is_null() {
681 let dur = trigger.saturating_sub(get_time());
682 let remaining_ticks = if dur > 0 {
683 result = -EINTR;
685 dur
686 } else {
687 0
688 };
689 let rem_ts = TimeSpec::from_freq(remaining_ticks, clock_freq());
690 unsafe {
691 write_to_user(rem, rem_ts);
692 }
693 }
694
695 result
696 }
698
699pub fn gettid() -> c_int {
700 current_task().lock().tid as c_int
701}
702
703pub fn clock_nanosleep(
712 clk_id: c_int,
713 flags: c_int,
714 req: *const TimeSpec,
715 rem: *mut TimeSpec,
716) -> c_int {
717 let time_req = unsafe { read_from_user(req) };
718 let is_abstime = (flags & TIMER_ABSTIME) != 0;
719 let sleep_ticks = time_req.into_freq(clock_freq());
720 let trigger = if is_abstime {
721 sleep_ticks
722 } else {
723 let now = match clk_id {
724 CLOCK_REALTIME => REALTIME.read().into_freq(clock_freq()),
725 CLOCK_MONOTONIC => get_time(),
726 CLOCK_TAI | CLOCK_BOOTTIME | CLOCK_PROCESS_CPUTIME_ID => return -ENOSYS,
727 _ => return -EINVAL,
728 };
729 now.saturating_add(sleep_ticks)
730 };
731
732 let mut result = 0;
733 let task = current_task();
734
735 let mut timer_q = TIMER_QUEUE.lock();
736 timer_q.push(trigger, task.clone());
737 sleep_task_with_block(task.clone(), true);
738 drop(timer_q);
739 yield_task();
740
741 TIMER_QUEUE.lock().remove_task(&task);
743
744 if !rem.is_null() {
745 let dur = trigger.saturating_sub(get_time());
746 let remaining_ticks = if dur > 0 {
747 result = -EINTR;
749 dur
750 } else {
751 0
752 };
753 let rem_ts = TimeSpec::from_freq(remaining_ticks, clock_freq());
754 unsafe {
755 write_to_user(rem, rem_ts);
756 }
757 }
758
759 result
760}
761
762pub fn getitimer(which: c_int, curr_value: *mut Itimerval) -> c_int {
769 match which {
770 ITIMER_REAL | ITIMER_VIRTUAL | ITIMER_PROF => {}
771 _ => return -EINVAL,
772 }
773 let sig = match which {
774 ITIMER_REAL => NUM_SIGALRM,
775 ITIMER_VIRTUAL => NUM_SIGVTALRM,
776 ITIMER_PROF => NUM_SIGPROF,
777 _ => unreachable!("getitimer: unreachable which case."),
778 };
779 let mut val = Itimerval::zero();
780 if let Some(timer) = TIMER.lock().find_entry(¤t_task(), sig) {
781 let now = get_time();
782 let remaining = if *timer.0 > now { *timer.0 - now } else { 0 };
783 let it_value = TimeSpec::from_freq(remaining, clock_freq()).to_timeval();
784 let it_interval = timer.1.it_interval.to_timeval();
785 val = Itimerval {
786 it_value,
787 it_interval,
788 };
789 }
790 unsafe {
791 write_to_user(curr_value, val);
792 }
793 0
794}
795
796pub fn setitimer(which: c_int, new_value: *const Itimerval, old_value: *mut Itimerval) -> c_int {
804 match which {
805 ITIMER_REAL | ITIMER_VIRTUAL | ITIMER_PROF => {}
806 _ => return -EINVAL,
807 }
808 let sig = match which {
809 ITIMER_REAL => NUM_SIGALRM,
810 ITIMER_VIRTUAL => NUM_SIGVTALRM,
811 ITIMER_PROF => NUM_SIGPROF,
812 _ => unreachable!("setitimer: unreachable which case."),
813 };
814
815 let mut binding = TIMER.lock();
816 let new_itimer = unsafe { read_from_user(new_value) };
817 if !new_itimer.it_value.is_zero() {
818 let trigger = get_time() + new_itimer.it_value.into_freq(clock_freq());
819 let interval = new_itimer.it_interval.to_timespec();
820 let entry = TimerEntry {
821 task: current_task(),
822 sig,
823 it_interval: interval,
824 };
825 binding.push(trigger, entry);
826 }
827 if !old_value.is_null() {
828 let mut val = Itimerval::zero();
829 if let Some(timer) = binding.find_entry(¤t_task(), sig) {
830 let now = get_time();
831 let remaining = if *timer.0 > now { *timer.0 - now } else { 0 };
832 let it_value = TimeSpec::from_freq(remaining, clock_freq()).to_timeval();
833 let it_interval = timer.1.it_interval.to_timeval();
834 val = Itimerval {
835 it_value,
836 it_interval,
837 };
838 }
839 unsafe {
840 write_to_user(old_value, val);
841 }
842 }
843
844 0
845}
846
847pub fn futex(
858 uaddr: *mut u32,
859 op: c_int,
860 val: u32,
861 timeout: *const TimeSpec,
862 _uaddr2: *mut u32,
863 _val3: u32,
864) -> c_int {
865 let _private = (op & FUTEX_PRIVATE as c_int) != 0; let realtime = (op & FUTEX_CLOCK_REALTIME as c_int) != 0;
867 let op = op & !(FUTEX_PRIVATE as c_int) & !(FUTEX_CLOCK_REALTIME as c_int);
868 let mut fm = FUTEX_MANAGER.lock();
870 match op as u32 {
871 FUTEX_WAIT => {
872 let user_val = unsafe { read_from_user(uaddr) };
874 let memory_space = current_task()
875 .lock()
876 .memory_space
877 .as_ref()
878 .expect("futex: current task has no memory space.")
879 .clone();
880 let paddr = if let Some(paddr) = memory_space
881 .lock()
882 .translate(Vaddr::from_usize(uaddr as usize))
883 {
884 paddr.as_usize()
885 } else {
886 return -EFAULT;
887 };
888 if user_val != val as u32 {
889 return -EAGAIN;
890 }
891
892 let task = current_task();
893 let waitq = fm.get_wait_queue(paddr);
894 waitq.sleep(task.clone());
895 sleep_task_with_block(task.clone(), true);
896
897 if !timeout.is_null() {
898 let ts = unsafe { read_from_user(timeout) };
899 if ts.tv_sec < 0 || ts.tv_nsec < 0 || ts.tv_nsec > 999999999 {
900 return -EINVAL;
901 }
902 let sleep_ticks = ts.into_freq(clock_freq());
903 let trigger = if realtime {
904 let now = realtime_now().into_freq(clock_freq());
905 now.saturating_add(sleep_ticks)
906 } else {
907 let now = get_time();
908 now.saturating_add(sleep_ticks)
909 };
910 TIMER_QUEUE.lock().push(trigger, task.clone());
911 drop(fm);
912 yield_task();
913 if TIMER_QUEUE.lock().remove_task(&task).is_none() {
914 let mut fm = FUTEX_MANAGER.lock();
916 let waitq = fm.get_wait_queue(paddr);
917 waitq.remove_task(&task);
919 return -ETIMEDOUT;
920 }
921 } else {
922 drop(fm);
923 yield_task();
924 }
925 if signal_pending(&task) {
926 let mut fm = FUTEX_MANAGER.lock();
928 let waitq = fm.get_wait_queue(paddr);
929 waitq.remove_task(&task);
930 return -EINTR;
931 }
932 0
935 }
936 FUTEX_WAKE => {
937 let mut wake_count = 0;
938 let paddr = {
939 let memory_space = current_task()
940 .lock()
941 .memory_space
942 .as_ref()
943 .expect("futex: current task has no memory space.")
944 .clone();
945 if let Some(paddr) = memory_space
946 .lock()
947 .translate(Vaddr::from_usize(uaddr as usize))
948 {
949 paddr.as_usize()
950 } else {
951 return -EFAULT;
952 }
953 };
954 let mut fm = FUTEX_MANAGER.lock();
955 let waitq = fm.get_wait_queue(paddr);
956 for _ in 0..val {
957 waitq.wake_up_one();
958 wake_count += 1;
959 }
960 wake_count
961 }
962 _ => -ENOSYS,
963 }
964}
965
966pub fn set_tid_address(tidptr: *mut c_int) -> c_int {
977 let task = current_task();
978 task.lock().clear_child_tid = tidptr as usize;
979 current_task().lock().tid as c_int
980}
981
982pub fn get_robust_list(pid: c_int, head_ptr: *mut *mut RobustListHead, sizep: *mut SizeT) -> c_int {
990 let task = if pid == 0 {
991 current_task()
992 } else {
993 let tm = TASK_MANAGER.lock();
994 match tm.get_task(pid as u32) {
995 Some(t) => t,
996 None => return -ESRCH,
997 }
998 };
999 let (head, size) = {
1000 let t = task.lock();
1001 let head = match t.robust_list {
1002 Some(h) => h as *mut RobustListHead,
1003 None => core::ptr::null_mut(),
1004 };
1005 let size = size_of::<RobustListHead>() as SizeT;
1006 (head, size)
1007 };
1008 unsafe {
1009 write_to_user(head_ptr, head);
1010 write_to_user(sizep, size);
1011 }
1012 0
1013}
1014
1015pub fn set_robust_list(head: *const RobustListHead, size: SizeT) -> c_int {
1022 if size != size_of::<RobustListHead>() as SizeT {
1023 return -EINVAL;
1024 }
1025 let task = current_task();
1026 task.lock().robust_list = Some(head as usize);
1027 0
1028}
1029
1030pub fn setsid() -> c_int {
1034 let task = current_task();
1035 let mut t = task.lock();
1036 if t.pid == t.pgid {
1037 return -EPERM;
1038 }
1039 let new_pgid = t.pid;
1040 t.pgid = new_pgid;
1041 new_pgid as c_int
1042}
1043
1044fn parse_hashbang(data: &[u8]) -> Result<(&str, Option<&str>), ()> {
1046 let line_end = data.iter().position(|&b| b == b'\n').unwrap_or(data.len());
1048 let line_start = data[2..line_end]
1050 .iter()
1051 .position(|&b| b != b' ' && b != b'\t')
1052 .unwrap_or(line_end - 2)
1053 + 2;
1054 let line = &data[line_start..line_end];
1055
1056 let parts: Vec<&[u8]> = line
1058 .split(|&b| b == b' ' || b == b'\t')
1059 .filter(|p| !p.is_empty()) .collect();
1061
1062 if parts.is_empty() {
1063 return Err(()); }
1065
1066 let interpreter_path = core::str::from_utf8(parts[0]).map_err(|_| ())?;
1068
1069 let interpreter_arg = parts
1071 .get(1)
1072 .map(|p| core::str::from_utf8(p))
1073 .transpose()
1074 .map_err(|_| ())?;
1075
1076 Ok((interpreter_path, interpreter_arg))
1077}
1078
1079fn do_execve_prepare(
1081 data: &[u8],
1082) -> Result<
1083 (
1084 Arc<SpinLock<MemorySpace>>,
1085 usize,
1086 usize,
1087 usize,
1088 usize,
1089 usize,
1090 ),
1091 c_int,
1092> {
1093 let (space, entry, sp, phdr_addr, phnum, phent) = match MemorySpace::from_elf(data) {
1094 Ok(res) => res,
1095 Err(_) => return Err(-ENOEXEC),
1096 };
1097
1098 let space = Arc::new(SpinLock::new(space));
1099 Ok((space, entry, sp, phdr_addr, phnum, phent))
1100}
1101
1102fn do_execve_switch(
1105 space: Arc<SpinLock<MemorySpace>>,
1106 entry: usize,
1107 sp: usize,
1108 argv: Vec<alloc::string::String>,
1109 envp: Vec<alloc::string::String>,
1110 phdr_addr: usize,
1111 phnum: usize,
1112 phent: usize,
1113) -> c_int {
1114 let task = current_task();
1115
1116 task.lock().fd_table.close_exec();
1117
1118 current_cpu().lock().switch_space(space.clone());
1120
1121 {
1124 let argv_refs: Vec<&str> = argv.iter().map(|s| s.as_str()).collect();
1126 let envp_refs: Vec<&str> = envp.iter().map(|s| s.as_str()).collect();
1127
1128 let mut t = task.lock();
1129 t.execve(
1130 space.clone(),
1131 entry,
1132 sp,
1133 argv_refs.as_slice(),
1134 envp_refs.as_slice(),
1135 phdr_addr,
1136 phnum,
1137 phent,
1138 );
1139 } let tfp = task.lock().trap_frame_ptr.load(Ordering::SeqCst);
1142
1143 drop(argv);
1145 drop(envp);
1146 drop(space); drop(task); unsafe {
1152 restore(&*tfp);
1153 }
1154 -1
1155}