1 use crate::filesystem::vfs::file::{File, FileMode}; 2 use crate::filesystem::vfs::syscall::ModeType; 3 use crate::filesystem::vfs::{FilePrivateData, FileSystem, FileType, IndexNode, Metadata}; 4 use crate::libs::spinlock::{SpinLock, SpinLockGuard}; 5 use crate::libs::wait_queue::WaitQueue; 6 use crate::net::event_poll::EPollEventType; 7 use crate::process::ProcessManager; 8 use crate::syscall::Syscall; 9 use alloc::string::String; 10 use alloc::sync::Arc; 11 use alloc::vec::Vec; 12 use core::any::Any; 13 use ida::IdAllocator; 14 use system_error::SystemError; 15 16 static EVENTFD_ID_ALLOCATOR: IdAllocator = IdAllocator::new(0, u32::MAX as usize); 17 18 bitflags! { 19 pub struct EventFdFlags: u32{ 20 /// Provide semaphore-like semantics for reads from the new 21 /// file descriptor. 22 const EFD_SEMAPHORE = 1; 23 /// Set the close-on-exec (FD_CLOEXEC) flag on the new file 24 /// descriptor 25 const EFD_CLOEXEC = 2; 26 /// Set the O_NONBLOCK file status flag on the open file 27 /// description (see open(2)) referred to by the new file 28 /// descriptor 29 const EFD_NONBLOCK = 4; 30 } 31 } 32 33 #[derive(Debug)] 34 pub struct EventFd { 35 count: u64, 36 flags: EventFdFlags, 37 #[allow(unused)] 38 id: u32, 39 } 40 41 impl EventFd { 42 pub fn new(count: u64, flags: EventFdFlags, id: u32) -> Self { 43 EventFd { count, flags, id } 44 } 45 } 46 47 #[derive(Debug)] 48 pub struct EventFdInode { 49 eventfd: SpinLock<EventFd>, 50 wait_queue: WaitQueue, 51 } 52 53 impl EventFdInode { 54 pub fn new(eventfd: EventFd) -> Self { 55 EventFdInode { 56 eventfd: SpinLock::new(eventfd), 57 wait_queue: WaitQueue::default(), 58 } 59 } 60 } 61 62 impl IndexNode for EventFdInode { 63 fn open( 64 &self, 65 _data: SpinLockGuard<FilePrivateData>, 66 _mode: &FileMode, 67 ) -> Result<(), SystemError> { 68 Ok(()) 69 } 70 71 fn close(&self, _data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> { 72 Ok(()) 73 } 74 75 /// # 从 counter 里读取一个 8 字节的int值 76 /// 77 /// 1. counter !=0 78 /// - EFD_SEMAPHORE 如果没有被设置,从 eventfd read,会得到 counter,并将它归0 79 /// - EFD_SEMAPHORE 如果被设置,从 eventfd read,会得到值 1,并将 counter - 1 80 /// 2. counter == 0 81 /// - EFD_NONBLOCK 如果被设置,那么会以 EAGAIN 的错失败 82 /// - 否则 read 会被阻塞,直到为非0。 83 fn read_at( 84 &self, 85 _offset: usize, 86 len: usize, 87 buf: &mut [u8], 88 _data: SpinLockGuard<FilePrivateData>, 89 ) -> Result<usize, SystemError> { 90 if len < 8 { 91 return Err(SystemError::EINVAL); 92 } 93 let mut val = loop { 94 let val = self.eventfd.lock().count; 95 if val != 0 { 96 break val; 97 } 98 if self 99 .eventfd 100 .lock() 101 .flags 102 .contains(EventFdFlags::EFD_NONBLOCK) 103 { 104 return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); 105 } 106 self.wait_queue.sleep(); 107 }; 108 109 let mut eventfd = self.eventfd.lock(); 110 if eventfd.flags.contains(EventFdFlags::EFD_SEMAPHORE) { 111 eventfd.count -= 1; 112 val = 1; 113 } else { 114 eventfd.count = 0; 115 } 116 let val_bytes = val.to_ne_bytes(); 117 buf[..8].copy_from_slice(&val_bytes); 118 return Ok(8); 119 } 120 121 /// # 把一个 8 字节的int值写入到 counter 里 122 /// 123 /// - counter 最大值是 2^64 - 1 124 /// - 如果写入时会发生溢出,则write会被阻塞 125 /// - 如果 EFD_NONBLOCK 被设置,那么以 EAGAIN 失败 126 /// - 以不合法的值写入时,会以 EINVAL 失败 127 /// - 比如 0xffffffffffffffff 不合法 128 /// - 比如 写入的值 size 小于8字节 129 fn write_at( 130 &self, 131 _offset: usize, 132 len: usize, 133 buf: &[u8], 134 _data: SpinLockGuard<FilePrivateData>, 135 ) -> Result<usize, SystemError> { 136 if len < 8 { 137 return Err(SystemError::EINVAL); 138 } 139 let val = u64::from_ne_bytes(buf[..8].try_into().unwrap()); 140 if val == u64::MAX { 141 return Err(SystemError::EINVAL); 142 } 143 loop { 144 let eventfd = self.eventfd.lock(); 145 if u64::MAX - eventfd.count > val { 146 break; 147 } 148 // block until a read() is performed on the 149 // file descriptor, or fails with the error EAGAIN if the 150 // file descriptor has been made nonblocking. 151 if eventfd.flags.contains(EventFdFlags::EFD_NONBLOCK) { 152 return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); 153 } 154 drop(eventfd); 155 self.wait_queue.sleep(); 156 } 157 let mut eventfd = self.eventfd.lock(); 158 eventfd.count += val; 159 self.wait_queue.wakeup_all(None); 160 return Ok(8); 161 } 162 163 /// # 检查 eventfd 的状态 164 /// 165 /// - 如果 counter 的值大于 0 ,那么 fd 的状态就是可读的 166 /// - 如果能无阻塞地写入一个至少为 1 的值,那么 fd 的状态就是可写的 167 fn poll(&self, _private_data: &FilePrivateData) -> Result<usize, SystemError> { 168 let mut events = EPollEventType::empty(); 169 if self.eventfd.lock().count != 0 { 170 events |= EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM; 171 } 172 if self.eventfd.lock().count != u64::MAX { 173 events |= EPollEventType::EPOLLOUT | EPollEventType::EPOLLWRNORM; 174 } 175 return Ok(events.bits() as usize); 176 } 177 178 fn metadata(&self) -> Result<Metadata, SystemError> { 179 let meta = Metadata { 180 mode: ModeType::from_bits_truncate(0o755), 181 file_type: FileType::File, 182 ..Default::default() 183 }; 184 Ok(meta) 185 } 186 187 fn resize(&self, _len: usize) -> Result<(), SystemError> { 188 Ok(()) 189 } 190 fn fs(&self) -> Arc<dyn FileSystem> { 191 panic!("EventFd does not have a filesystem") 192 } 193 fn as_any_ref(&self) -> &dyn Any { 194 self 195 } 196 fn list(&self) -> Result<Vec<String>, SystemError> { 197 Err(SystemError::EINVAL) 198 } 199 } 200 201 impl Syscall { 202 /// # 创建一个 eventfd 文件描述符 203 /// 204 /// ## 参数 205 /// - `init_val`: u32: eventfd 的初始值 206 /// - `flags`: u32: eventfd 的标志 207 /// 208 /// ## 返回值 209 /// - `Ok(usize)`: 成功创建的文件描述符 210 /// - `Err(SystemError)`: 创建失败 211 /// 212 /// See: https://man7.org/linux/man-pages/man2/eventfd2.2.html 213 pub fn sys_eventfd(init_val: u32, flags: u32) -> Result<usize, SystemError> { 214 let flags = EventFdFlags::from_bits(flags).ok_or(SystemError::EINVAL)?; 215 let id = EVENTFD_ID_ALLOCATOR.alloc().ok_or(SystemError::ENOMEM)? as u32; 216 let eventfd = EventFd::new(init_val as u64, flags, id); 217 let inode = Arc::new(EventFdInode::new(eventfd)); 218 let filemode = if flags.contains(EventFdFlags::EFD_CLOEXEC) { 219 FileMode::O_RDWR | FileMode::O_CLOEXEC 220 } else { 221 FileMode::O_RDWR 222 }; 223 let file = File::new(inode, filemode)?; 224 let binding = ProcessManager::current_pcb().fd_table(); 225 let mut fd_table_guard = binding.write(); 226 let fd = fd_table_guard.alloc_fd(file, None).map(|x| x as usize); 227 return fd; 228 } 229 } 230