xref: /DragonOS/kernel/src/filesystem/eventfd.rs (revision 703ce5a77c1e4bebadc5aaa6cbb21595663d4477)
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