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