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