sys_pipe2.rs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. use crate::{
  2. arch::syscall::nr::SYS_PIPE2,
  3. filesystem::vfs::{
  4. file::{File, FileMode},
  5. FilePrivateData,
  6. },
  7. ipc::pipe::{LockedPipeInode, PipeFsPrivateData},
  8. libs::spinlock::SpinLock,
  9. process::ProcessManager,
  10. syscall::{
  11. table::{FormattedSyscallParam, Syscall},
  12. user_access::UserBufferWriter,
  13. },
  14. };
  15. use alloc::vec::Vec;
  16. use core::ffi::c_int;
  17. use system_error::SystemError;
  18. pub struct SysPipe2Handle;
  19. // Extracted core logic for pipe2
  20. // pub(super) makes it visible to other modules in kernel/src/ipc/syscall/
  21. pub(super) fn do_kernel_pipe2(fd: *mut i32, flags: FileMode) -> Result<usize, SystemError> {
  22. if !flags
  23. .difference(FileMode::O_CLOEXEC | FileMode::O_NONBLOCK | FileMode::O_DIRECT)
  24. .is_empty()
  25. {
  26. return Err(SystemError::EINVAL);
  27. }
  28. let mut user_buffer = UserBufferWriter::new(fd, core::mem::size_of::<[c_int; 2]>(), true)?;
  29. let fd = user_buffer.buffer::<i32>(0)?;
  30. let pipe_ptr = LockedPipeInode::new();
  31. let mut read_file = File::new(
  32. pipe_ptr.clone(),
  33. FileMode::O_RDONLY | (flags & FileMode::O_NONBLOCK),
  34. )?;
  35. read_file.private_data = SpinLock::new(FilePrivateData::Pipefs(PipeFsPrivateData::new(
  36. FileMode::O_RDONLY,
  37. )));
  38. let mut write_file = File::new(
  39. pipe_ptr.clone(),
  40. FileMode::O_WRONLY | (flags & (FileMode::O_NONBLOCK | FileMode::O_DIRECT)),
  41. )?;
  42. write_file.private_data = SpinLock::new(FilePrivateData::Pipefs(PipeFsPrivateData::new(
  43. FileMode::O_WRONLY | (flags & (FileMode::O_NONBLOCK | FileMode::O_DIRECT)),
  44. )));
  45. if flags.contains(FileMode::O_CLOEXEC) {
  46. read_file.set_close_on_exec(true);
  47. write_file.set_close_on_exec(true);
  48. }
  49. let fd_table_ptr = ProcessManager::current_pcb().fd_table();
  50. let mut fd_table_guard = fd_table_ptr.write();
  51. let read_fd = fd_table_guard.alloc_fd(read_file, None)?;
  52. let write_fd = fd_table_guard.alloc_fd(write_file, None)?;
  53. drop(fd_table_guard);
  54. fd[0] = read_fd;
  55. fd[1] = write_fd;
  56. Ok(0)
  57. }
  58. impl SysPipe2Handle {
  59. #[inline(always)]
  60. fn pipefd(args: &[usize]) -> *mut i32 {
  61. args[0] as *mut c_int
  62. }
  63. #[inline(always)]
  64. fn flags(args: &[usize]) -> FileMode {
  65. FileMode::from_bits_truncate(args[1] as u32)
  66. }
  67. }
  68. impl Syscall for SysPipe2Handle {
  69. fn num_args(&self) -> usize {
  70. 2 // fd_ptr, flags
  71. }
  72. fn handle(&self, args: &[usize], _from_user: bool) -> Result<usize, SystemError> {
  73. let fd_ptr = Self::pipefd(args);
  74. if fd_ptr.is_null() {
  75. return Err(SystemError::EFAULT);
  76. } else {
  77. let flags = FileMode::from_bits_truncate(args[1] as u32);
  78. do_kernel_pipe2(fd_ptr, flags)
  79. }
  80. }
  81. fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
  82. let fd_ptr = Self::pipefd(args);
  83. vec![
  84. FormattedSyscallParam::new("fd_ptr", format!("{}", fd_ptr as usize)), // Format pointer as hex
  85. FormattedSyscallParam::new("flags", format!("{}", Self::flags(args).bits())),
  86. ]
  87. }
  88. }
  89. syscall_table_macros::declare_syscall!(SYS_PIPE2, SysPipe2Handle);