kernel/abi/xv6/riscv64/
proc.rs1use alloc::string::{String, ToString};
2use crate::{
3 arch::{get_cpu, Trapframe},
4 fs::FileType,
5 library::std::string::cstring_to_string,
6 sched::scheduler::get_scheduler,
7 task::{get_parent_waker, mytask, CloneFlags, WaitError}
8};
9
10fn to_absolute_path_v2(task: &crate::task::Task, path: &str) -> Result<String, ()> {
13 if path.starts_with('/') {
14 Ok(path.to_string())
15 } else {
16 let cwd = task.cwd.clone().ok_or(())?;
17 let mut absolute_path = cwd;
18 if !absolute_path.ends_with('/') {
19 absolute_path.push('/');
20 }
21 absolute_path.push_str(path);
22 let mut components = alloc::vec::Vec::new();
24 for comp in absolute_path.split('/') {
25 match comp {
26 "" | "." => {},
27 ".." => { components.pop(); },
28 _ => components.push(comp),
29 }
30 }
31 Ok("/".to_string() + &components.join("/"))
32 }
33}
34
35fn get_path_str_v2(ptr: *const u8) -> Result<String, ()> {
38 const MAX_PATH_LENGTH: usize = 128;
39 cstring_to_string(ptr, MAX_PATH_LENGTH).map(|(s, _)| s).map_err(|_| ())
40}
41
42pub fn sys_fork(_abi: &mut crate::abi::xv6::riscv64::Xv6Riscv64Abi, trapframe: &mut Trapframe) -> usize {
43 let parent_task = mytask().unwrap();
44
45 trapframe.increment_pc_next(parent_task); parent_task.vcpu.store(trapframe);
49
50 match parent_task.clone_task(CloneFlags::default()) {
52 Ok(mut child_task) => {
53 let child_id = child_task.get_id();
54 child_task.vcpu.regs.reg[10] = 0; get_scheduler().add_task(child_task, get_cpu().get_cpuid());
56 child_id
58 },
59 Err(_) => {
60 usize::MAX }
62 }
63}
64
65pub fn sys_exit(_abi: &mut crate::abi::xv6::riscv64::Xv6Riscv64Abi, trapframe: &mut Trapframe) -> usize {
66 let task = mytask().unwrap();
67 task.vcpu.store(trapframe);
68 let exit_code = trapframe.get_arg(0) as i32;
69 task.exit(exit_code);
70 get_scheduler().schedule(get_cpu());
71}
72
73pub fn sys_wait(_abi: &mut crate::abi::xv6::riscv64::Xv6Riscv64Abi, trapframe: &mut Trapframe) -> usize {
74 let task = mytask().unwrap();
75 let status_ptr = trapframe.get_arg(0) as *mut i32;
76
77 for pid in task.get_children().clone() {
78 match task.wait(pid) {
79 Ok(status) => {
80 if status_ptr != core::ptr::null_mut() {
82 let status_ptr = task.vm_manager.translate_vaddr(status_ptr as usize).unwrap() as *mut i32;
83 unsafe {
84 *status_ptr = status;
85 }
86 }
87 trapframe.increment_pc_next(task);
88 return pid;
89 },
90 Err(error) => {
91 match error {
92 WaitError::ChildNotExited(_) => continue,
93 _ => {
94 return trapframe.get_return_value();
95 },
96 }
97 }
98 }
99 }
100
101 let parent_waker = get_parent_waker(task.get_id());
104 parent_waker.wait(task, trapframe);
105}
106
107pub fn sys_kill(_abi: &mut crate::abi::xv6::riscv64::Xv6Riscv64Abi, _trapframe: &mut Trapframe) -> usize {
108 usize::MAX
111}
112
113pub fn sys_sbrk(_abi: &mut crate::abi::xv6::riscv64::Xv6Riscv64Abi, trapframe: &mut Trapframe) -> usize {
114 let task = mytask().unwrap();
115 let increment = trapframe.get_arg(0);
116 let brk = task.get_brk();
117 trapframe.increment_pc_next(task);
118 match task.set_brk(unsafe { brk.unchecked_add(increment) }) {
119 Ok(_) => brk,
120 Err(_) => usize::MAX, }
122}
123
124pub fn sys_chdir(_abi: &mut crate::abi::xv6::riscv64::Xv6Riscv64Abi, trapframe: &mut Trapframe) -> usize {
125 let task = mytask().unwrap();
126 trapframe.increment_pc_next(task);
127
128 let path_ptr = task.vm_manager.translate_vaddr(trapframe.get_arg(0) as usize).unwrap() as *const u8;
129 let path = match get_path_str_v2(path_ptr) {
130 Ok(p) => match to_absolute_path_v2(&task, &p) {
131 Ok(abs_path) => abs_path,
132 Err(_) => return usize::MAX,
133 },
134 Err(_) => return usize::MAX, };
136
137 let file = match task.vfs.as_ref() {
139 Some(vfs) => vfs.open(&path, 0),
140 None => return usize::MAX, };
142 if file.is_err() {
143 return usize::MAX; }
145 let kernel_obj = file.unwrap();
146 let file_handle = kernel_obj.as_file().unwrap();
147 if file_handle.metadata().unwrap().file_type != FileType::Directory {
149 return usize::MAX; }
151
152 task.cwd = Some(path); 0
155}
156
157pub fn sys_getpid(_abi: &mut crate::abi::xv6::riscv64::Xv6Riscv64Abi, trapframe: &mut Trapframe) -> usize {
158 let task = mytask().unwrap();
159 trapframe.increment_pc_next(task);
160 task.get_id()
161}