kernel/abi/xv6/riscv64/
proc.rs1use crate::{
2 arch::{Trapframe, get_cpu},
3 fs::FileType,
4 library::std::string::cstring_to_string,
5 sched::scheduler::get_scheduler,
6 task::{CloneFlags, WaitError, get_parent_waitpid_waker, mytask},
7};
8use alloc::string::{String, ToString};
9
10fn to_absolute_path_v2(task: &crate::task::Task, path: &str) -> Result<String, ()> {
12 if path.starts_with('/') {
13 Ok(path.to_string())
14 } else {
15 let vfs = task.vfs.read().clone().ok_or(())?;
16 Ok(vfs.resolve_path_to_absolute(path))
17 }
18}
19
20fn get_path_str_v2(ptr: *const u8) -> Result<String, ()> {
23 const MAX_PATH_LENGTH: usize = 128;
24 cstring_to_string(ptr, MAX_PATH_LENGTH)
25 .map(|(s, _)| s)
26 .map_err(|_| ())
27}
28
29pub fn sys_fork(
30 _abi: &mut crate::abi::xv6::riscv64::Xv6Riscv64Abi,
31 trapframe: &mut Trapframe,
32) -> usize {
33 let parent_task = mytask().unwrap();
34
35 trapframe.increment_pc_next(parent_task); parent_task.vcpu.lock().store(trapframe);
39
40 match parent_task.clone_task(CloneFlags::default()) {
42 Ok(mut child_task) => {
43 child_task.vcpu.lock().iregs.reg[10] = 0; let scheduler = get_scheduler();
46 let cpu_id = get_cpu().get_cpuid();
47 let parent_id = parent_task.get_id();
48
49 let child_id = scheduler.add_task(child_task, cpu_id);
51
52 if let Some(child) = scheduler.get_task_by_id(child_id) {
54 child.set_parent_id(parent_id);
55 }
56 if let Some(parent) = scheduler.get_task_by_id(parent_id) {
57 parent.add_child(child_id);
58 }
59
60 let child_namespace_id = scheduler
62 .get_task_by_id(child_id)
63 .map(|t| t.get_namespace_id())
64 .unwrap_or(0);
65
66 child_namespace_id
68 }
69 Err(_) => {
70 usize::MAX }
72 }
73}
74
75pub fn sys_exit(
76 _abi: &mut crate::abi::xv6::riscv64::Xv6Riscv64Abi,
77 trapframe: &mut Trapframe,
78) -> usize {
79 let task = mytask().unwrap();
80 task.vcpu.lock().store(trapframe);
81 let exit_code = trapframe.get_arg(0) as i32;
82 task.exit(exit_code);
83 get_scheduler().schedule(trapframe);
84 usize::MAX }
86
87pub fn sys_wait(
88 _abi: &mut crate::abi::xv6::riscv64::Xv6Riscv64Abi,
89 trapframe: &mut Trapframe,
90) -> usize {
91 let task = mytask().unwrap();
92 let status_ptr = trapframe.get_arg(0) as *mut i32;
93
94 loop {
96 for child_pid in task.get_children().clone() {
98 match task.wait(child_pid) {
99 Ok(status) => {
100 if status_ptr != core::ptr::null_mut() {
102 let status_ptr = task
103 .vm_manager
104 .translate_vaddr(status_ptr as usize)
105 .unwrap() as *mut i32;
106 unsafe {
107 *status_ptr = status;
108 }
109 }
110 trapframe.increment_pc_next(task);
111 return child_pid;
112 }
113 Err(error) => match error {
114 WaitError::ChildNotExited(_) => continue,
115 _ => {
116 trapframe.increment_pc_next(task);
117 return usize::MAX;
118 }
119 },
120 }
121 }
122
123 let parent_waker = get_parent_waitpid_waker(task.get_id());
125 parent_waker.wait(task.get_id(), trapframe);
126 continue;
128 }
129}
130
131pub fn sys_kill(
132 _abi: &mut crate::abi::xv6::riscv64::Xv6Riscv64Abi,
133 trapframe: &mut Trapframe,
134) -> usize {
135 let task = mytask().unwrap();
136 let pid = trapframe.get_arg(0) as usize;
137 let signal = trapframe.get_arg(1) as i32;
138
139 trapframe.increment_pc_next(task);
140
141 if signal != 9 {
143 return usize::MAX; }
145
146 let scheduler = get_scheduler();
148 if let Some(target_task) = scheduler.get_task_by_id(pid) {
149 target_task.exit(9); 0 } else {
153 usize::MAX }
155}
156
157pub fn sys_sbrk(
158 _abi: &mut crate::abi::xv6::riscv64::Xv6Riscv64Abi,
159 trapframe: &mut Trapframe,
160) -> usize {
161 let task = mytask().unwrap();
162 let increment = trapframe.get_arg(0);
163 let brk = task.get_brk();
164 trapframe.increment_pc_next(task);
165 match task.set_brk(unsafe { brk.unchecked_add(increment) }) {
166 Ok(_) => brk,
167 Err(_) => usize::MAX, }
169}
170
171pub fn sys_chdir(
172 _abi: &mut crate::abi::xv6::riscv64::Xv6Riscv64Abi,
173 trapframe: &mut Trapframe,
174) -> usize {
175 let task = mytask().unwrap();
176 trapframe.increment_pc_next(task);
177
178 let path_ptr = task
179 .vm_manager
180 .translate_vaddr(trapframe.get_arg(0) as usize)
181 .unwrap() as *const u8;
182 let path = match get_path_str_v2(path_ptr) {
183 Ok(p) => match to_absolute_path_v2(&task, &p) {
184 Ok(abs_path) => abs_path,
185 Err(_) => return usize::MAX,
186 },
187 Err(_) => return usize::MAX, };
189
190 let file = match task.vfs.read().clone() {
192 Some(vfs) => vfs.open(&path, 0),
193 None => return usize::MAX, };
195 if file.is_err() {
196 return usize::MAX; }
198 let kernel_obj = file.unwrap();
199 let file_handle = kernel_obj.as_file().unwrap();
200 if file_handle.metadata().unwrap().file_type != FileType::Directory {
202 return usize::MAX; }
204
205 if let Some(vfs) = task.vfs.read().clone() {
207 let _ = vfs.set_cwd_by_path(&path);
208 }
209
210 0
211}
212
213pub fn sys_getpid(
214 _abi: &mut crate::abi::xv6::riscv64::Xv6Riscv64Abi,
215 trapframe: &mut Trapframe,
216) -> usize {
217 let task = mytask().unwrap();
218 trapframe.increment_pc_next(task);
219 task.get_namespace_id()
221}
222
223pub fn sys_sleep(
224 _abi: &mut crate::abi::xv6::riscv64::Xv6Riscv64Abi,
225 trapframe: &mut Trapframe,
226) -> usize {
227 let ticks = trapframe.get_arg(0) as u64;
228 let task = mytask().unwrap();
229
230 trapframe.increment_pc_next(task);
232
233 task.sleep(trapframe, ticks);
235
236 0
238}