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