kernel/abi/xv6/riscv64/
pipe.rs

1use crate::{arch::Trapframe, ipc::UnidirectionalPipe, task::mytask};
2
3pub fn sys_pipe(
4    abi: &mut crate::abi::xv6::riscv64::Xv6Riscv64Abi,
5    trapframe: &mut Trapframe,
6) -> usize {
7    let task = mytask().unwrap();
8    trapframe.increment_pc_next(task);
9
10    let pipefd_ptr = task
11        .vm_manager
12        .translate_vaddr(trapframe.get_arg(0))
13        .expect("Invalid pipefd pointer");
14    let pipefd = unsafe { &mut *(pipefd_ptr as *mut [u32; 2]) };
15
16    let (read_end, write_end) = UnidirectionalPipe::create_pair(4096);
17
18    let read_handle = task
19        .handle_table
20        .insert(read_end)
21        .expect("Failed to insert read end");
22    let write_handle = task
23        .handle_table
24        .insert(write_end)
25        .expect("Failed to insert write end");
26
27    // Allocate XV6 file descriptors and store them in the array
28    let read_fd = match abi.allocate_fd(read_handle as u32) {
29        Ok(fd) => fd,
30        Err(_) => return usize::MAX, // Too many open files
31    };
32    let write_fd = match abi.allocate_fd(write_handle as u32) {
33        Ok(fd) => fd,
34        Err(_) => {
35            // Clean up the read_fd allocation if write_fd fails
36            abi.remove_fd(read_fd);
37            task.handle_table.remove(read_handle);
38            return usize::MAX; // Too many open files
39        }
40    };
41
42    pipefd[0] = read_fd as u32;
43    pipefd[1] = write_fd as u32;
44
45    0
46}