kernel/ipc/
syscall.rs

1//! IPC system calls
2//! 
3//! This module provides system call implementations for IPC operations
4//! such as pipe creation, message passing, and shared memory.
5
6use crate::{
7    arch::Trapframe,
8    task::mytask,
9    ipc::pipe::UnidirectionalPipe,
10};
11
12/// sys_pipe - Create a pipe pair
13/// 
14/// Creates a unidirectional pipe with read and write ends.
15/// 
16/// Arguments:
17/// - pipefd: Pointer to an array of 2 integers where file descriptors will be stored
18///   - pipefd[0] will contain the read end file descriptor
19///   - pipefd[1] will contain the write end file descriptor
20/// 
21/// Returns:
22/// - 0 on success
23/// - usize::MAX on error
24pub fn sys_pipe(trapframe: &mut Trapframe) -> usize {
25    let task = match mytask() {
26        Some(task) => task,
27        None => return usize::MAX,
28    };
29    
30    let pipefd_ptr = trapframe.get_arg(0);
31    
32    // Increment PC to avoid infinite loop if pipe creation fails
33    trapframe.increment_pc_next(task);
34    
35    // Translate the pointer to get access to the pipefd array
36    let pipefd_vaddr = match task.vm_manager.translate_vaddr(pipefd_ptr) {
37        Some(addr) => addr as *mut u32,
38        None => return usize::MAX, // Invalid pointer
39    };
40    
41    // Create pipe pair with default buffer size (4KB)
42    const DEFAULT_PIPE_BUFFER_SIZE: usize = 4096;
43    let (read_obj, write_obj) = UnidirectionalPipe::create_pair(DEFAULT_PIPE_BUFFER_SIZE);
44    
45    // Insert into handle table with explicit IPC metadata
46    use crate::object::handle::{HandleMetadata, HandleType, AccessMode};
47    
48    let read_metadata = HandleMetadata {
49        handle_type: HandleType::IpcChannel,
50        access_mode: AccessMode::ReadOnly,
51        special_semantics: None,
52    };
53    
54    let write_metadata = HandleMetadata {
55        handle_type: HandleType::IpcChannel,
56        access_mode: AccessMode::WriteOnly,
57        special_semantics: None,
58    };
59    
60    let read_handle = match task.handle_table.insert_with_metadata(read_obj, read_metadata) {
61        Ok(handle) => handle,
62        Err(_) => return usize::MAX, // Too many open handles
63    };
64    
65    let write_handle = match task.handle_table.insert_with_metadata(write_obj, write_metadata) {
66        Ok(handle) => handle,
67        Err(_) => {
68            // Clean up the read handle if write handle allocation fails
69            let _ = task.handle_table.remove(read_handle);
70            return usize::MAX;
71        }
72    };
73    
74    // Write the handles to user space
75    unsafe {
76        *pipefd_vaddr = read_handle;
77        *pipefd_vaddr.add(1) = write_handle;
78    }
79    
80    0 // Success
81}
82
83/// sys_pipe2 - Create a pipe pair with flags (future implementation)
84/// 
85/// Extended version of sys_pipe that supports flags for controlling
86/// pipe behavior (e.g., O_NONBLOCK, O_CLOEXEC).
87pub fn sys_pipe2(trapframe: &mut Trapframe) -> usize {
88    let _pipefd_ptr = trapframe.get_arg(0);
89    let _flags = trapframe.get_arg(1);
90    
91    // For now, just call the basic sys_pipe implementation
92    // TODO: Implement flag handling
93    sys_pipe(trapframe)
94}