1 use system_error::SystemError; 2 3 use crate::{ 4 arch::ipc::signal::SigSet, 5 filesystem::vfs::file::FileMode, 6 ipc::signal::set_current_sig_blocked, 7 mm::VirtAddr, 8 syscall::{ 9 user_access::{UserBufferReader, UserBufferWriter}, 10 Syscall, 11 }, 12 time::PosixTimeSpec, 13 }; 14 15 use super::{EPollCtlOption, EPollEvent, EventPoll}; 16 17 impl Syscall { 18 pub fn epoll_create(max_size: i32) -> Result<usize, SystemError> { 19 if max_size < 0 { 20 return Err(SystemError::EINVAL); 21 } 22 23 return EventPoll::do_create_epoll(FileMode::empty()); 24 } 25 26 pub fn epoll_create1(flag: usize) -> Result<usize, SystemError> { 27 let flags = FileMode::from_bits_truncate(flag as u32); 28 29 let ret = EventPoll::do_create_epoll(flags); 30 ret 31 } 32 33 pub fn epoll_wait( 34 epfd: i32, 35 events: VirtAddr, 36 max_events: i32, 37 timeout: i32, 38 ) -> Result<usize, SystemError> { 39 if max_events <= 0 || max_events as u32 > EventPoll::EP_MAX_EVENTS { 40 return Err(SystemError::EINVAL); 41 } 42 43 let mut timespec = None; 44 if timeout == 0 { 45 timespec = Some(PosixTimeSpec::new(0, 0)); 46 } 47 48 if timeout > 0 { 49 let sec: i64 = timeout as i64 / 1000; 50 let nsec: i64 = 1000000 * (timeout as i64 % 1000); 51 52 timespec = Some(PosixTimeSpec::new(sec, nsec)) 53 } 54 55 // 从用户传入的地址中拿到epoll_events 56 let mut epds_writer = UserBufferWriter::new( 57 events.as_ptr::<EPollEvent>(), 58 max_events as usize * core::mem::size_of::<EPollEvent>(), 59 true, 60 )?; 61 62 let epoll_events = epds_writer.buffer::<EPollEvent>(0)?; 63 return EventPoll::do_epoll_wait(epfd, epoll_events, max_events, timespec); 64 } 65 66 pub fn epoll_ctl(epfd: i32, op: usize, fd: i32, event: VirtAddr) -> Result<usize, SystemError> { 67 let op = EPollCtlOption::from_op_num(op)?; 68 let mut epds = EPollEvent::default(); 69 if op != EPollCtlOption::Del { 70 // 不为EpollCtlDel时不允许传入空指针 71 if event.is_null() { 72 return Err(SystemError::EFAULT); 73 } 74 75 // 还是一样的问题,C标准的epoll_event大小为12字节,而内核实现的epoll_event内存对齐后为16字节 76 // 这样分别拷贝其实和整体拷贝差别不大,内核使用内存对其版本甚至可能提升性能 77 let epds_reader = UserBufferReader::new( 78 event.as_ptr::<EPollEvent>(), 79 core::mem::size_of::<EPollEvent>(), 80 true, 81 )?; 82 83 // 拷贝到内核 84 epds_reader.copy_one_from_user(&mut epds, 0)?; 85 } 86 87 return EventPoll::do_epoll_ctl(epfd, op, fd, &mut epds, false); 88 } 89 90 /// ## 在epoll_wait时屏蔽某些信号 91 pub fn epoll_pwait( 92 epfd: i32, 93 epoll_event: VirtAddr, 94 max_events: i32, 95 timespec: i32, 96 sigmask: &mut SigSet, 97 ) -> Result<usize, SystemError> { 98 // 设置屏蔽的信号 99 set_current_sig_blocked(sigmask); 100 101 let wait_ret = Self::epoll_wait(epfd, epoll_event, max_events, timespec); 102 103 if wait_ret.is_err() && *wait_ret.as_ref().unwrap_err() != SystemError::EINTR { 104 // TODO: 恢复信号? 105 // link:https://code.dragonos.org.cn/xref/linux-6.1.9/fs/eventpoll.c#2294 106 } 107 wait_ret 108 } 109 } 110