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