xref: /DragonOS/kernel/src/net/event_poll/mod.rs (revision 81294aa2e6b257f0de5e3c28c3f3c89798330836)
1 use core::{
2     fmt::Debug,
3     sync::atomic::{AtomicBool, Ordering},
4 };
5 
6 use alloc::{
7     collections::LinkedList,
8     sync::{Arc, Weak},
9     vec::Vec,
10 };
11 use system_error::SystemError;
12 
13 use crate::{
14     arch::sched::sched,
15     filesystem::vfs::{
16         file::{File, FileMode},
17         FilePrivateData, IndexNode, Metadata,
18     },
19     include::bindings::bindings::INT32_MAX,
20     libs::{
21         rbtree::RBTree,
22         rwlock::RwLock,
23         spinlock::{SpinLock, SpinLockGuard},
24         wait_queue::WaitQueue,
25     },
26     process::ProcessManager,
27     time::{
28         timer::{next_n_us_timer_jiffies, Timer, WakeUpHelper},
29         TimeSpec,
30     },
31 };
32 
33 pub mod syscall;
34 
35 #[derive(Debug, Clone)]
36 pub struct LockedEventPoll(Arc<SpinLock<EventPoll>>);
37 
38 /// 内核的Epoll对象结构体,当用户创建一个Epoll时,内核就会创建一个该类型对象
39 /// 它对应一个epfd
40 #[derive(Debug)]
41 pub struct EventPoll {
42     /// epoll_wait用到的等待队列
43     epoll_wq: WaitQueue,
44     /// 维护所有添加进来的socket的红黑树
45     ep_items: RBTree<i32, Arc<EPollItem>>,
46     /// 接收就绪的描述符列表
47     ready_list: LinkedList<Arc<EPollItem>>,
48     /// 是否已经关闭
49     shutdown: AtomicBool,
50     self_ref: Option<Weak<SpinLock<EventPoll>>>,
51 }
52 
53 impl EventPoll {
54     pub const EP_MAX_EVENTS: u32 = INT32_MAX / (core::mem::size_of::<EPollEvent>() as u32);
55     pub fn new() -> Self {
56         Self {
57             epoll_wq: WaitQueue::INIT,
58             ep_items: RBTree::new(),
59             ready_list: LinkedList::new(),
60             shutdown: AtomicBool::new(false),
61             self_ref: None,
62         }
63     }
64 }
65 
66 /// EpollItem表示的是Epoll所真正管理的对象
67 /// 每当用户向Epoll添加描述符时都会注册一个新的EpollItem,EpollItem携带了一些被监听的描述符的必要信息
68 #[derive(Debug)]
69 pub struct EPollItem {
70     /// 对应的Epoll
71     epoll: Weak<SpinLock<EventPoll>>,
72     /// 用户注册的事件
73     event: RwLock<EPollEvent>,
74     /// 监听的描述符
75     fd: i32,
76     /// 对应的文件
77     file: Weak<SpinLock<File>>,
78 }
79 
80 impl EPollItem {
81     pub fn new(
82         epoll: Weak<SpinLock<EventPoll>>,
83         events: EPollEvent,
84         fd: i32,
85         file: Weak<SpinLock<File>>,
86     ) -> Self {
87         Self {
88             epoll,
89             event: RwLock::new(events),
90             fd,
91             file,
92         }
93     }
94 
95     pub fn epoll(&self) -> Weak<SpinLock<EventPoll>> {
96         self.epoll.clone()
97     }
98 
99     pub fn event(&self) -> &RwLock<EPollEvent> {
100         &self.event
101     }
102 
103     pub fn file(&self) -> Weak<SpinLock<File>> {
104         self.file.clone()
105     }
106 
107     pub fn fd(&self) -> i32 {
108         self.fd
109     }
110 
111     /// ## 通过epoll_item来执行绑定文件的poll方法,并获取到感兴趣的事件
112     fn ep_item_poll(&self) -> EPollEventType {
113         let file = self.file.upgrade();
114         if file.is_none() {
115             return EPollEventType::empty();
116         }
117         if let Ok(events) = file.unwrap().lock_irqsave().poll() {
118             let events = events as u32 & self.event.read().events;
119             return EPollEventType::from_bits_truncate(events);
120         }
121         return EPollEventType::empty();
122     }
123 }
124 
125 /// ### Epoll文件的私有信息
126 #[derive(Debug, Clone)]
127 pub struct EPollPrivateData {
128     epoll: LockedEventPoll,
129 }
130 
131 /// ### 该结构体将Epoll加入文件系统
132 #[derive(Debug)]
133 pub struct EPollInode {
134     epoll: LockedEventPoll,
135 }
136 
137 impl EPollInode {
138     pub fn new(epoll: LockedEventPoll) -> Arc<Self> {
139         Arc::new(Self { epoll })
140     }
141 }
142 
143 impl IndexNode for EPollInode {
144     fn read_at(
145         &self,
146         _offset: usize,
147         _len: usize,
148         _buf: &mut [u8],
149         _data: &mut crate::filesystem::vfs::FilePrivateData,
150     ) -> Result<usize, SystemError> {
151         Err(SystemError::ENOSYS)
152     }
153 
154     fn write_at(
155         &self,
156         _offset: usize,
157         _len: usize,
158         _buf: &[u8],
159         _data: &mut crate::filesystem::vfs::FilePrivateData,
160     ) -> Result<usize, SystemError> {
161         Err(SystemError::ENOSYS)
162     }
163 
164     fn poll(&self, _private_data: &FilePrivateData) -> Result<usize, SystemError> {
165         // 需要实现epoll嵌套epoll时,需要实现这里
166         todo!()
167     }
168 
169     fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> {
170         todo!()
171     }
172 
173     fn as_any_ref(&self) -> &dyn core::any::Any {
174         self
175     }
176 
177     fn list(&self) -> Result<Vec<alloc::string::String>, SystemError> {
178         Err(SystemError::ENOSYS)
179     }
180 
181     fn metadata(&self) -> Result<Metadata, SystemError> {
182         Ok(Metadata::default())
183     }
184 
185     fn close(&self, _data: &mut FilePrivateData) -> Result<(), SystemError> {
186         // 释放资源
187         let mut epoll = self.epoll.0.lock_irqsave();
188 
189         // 唤醒epoll上面等待的所有进程
190         epoll.shutdown.store(true, Ordering::SeqCst);
191         epoll.ep_wake_all();
192 
193         let fds = epoll.ep_items.keys().cloned().collect::<Vec<_>>();
194 
195         // 清理红黑树里面的epitems
196         for fd in fds {
197             let file = ProcessManager::current_pcb()
198                 .fd_table()
199                 .read()
200                 .get_file_by_fd(fd);
201 
202             if file.is_some() {
203                 file.unwrap()
204                     .lock_irqsave()
205                     .remove_epoll(&Arc::downgrade(&self.epoll.0))?;
206             }
207 
208             epoll.ep_items.remove(&fd);
209         }
210 
211         Ok(())
212     }
213 
214     fn open(&self, _data: &mut FilePrivateData, _mode: &FileMode) -> Result<(), SystemError> {
215         Ok(())
216     }
217 }
218 
219 impl EventPoll {
220     /// ## 创建epoll对象
221     ///
222     /// ### 参数
223     /// - flags: 创建的epoll文件的FileMode
224     ///
225     /// ### 返回值
226     /// - 成功则返回Ok(fd),否则返回Err
227     pub fn do_create_epoll(flags: FileMode) -> Result<usize, SystemError> {
228         if !flags.difference(FileMode::O_CLOEXEC).is_empty() {
229             return Err(SystemError::EINVAL);
230         }
231 
232         // 创建epoll
233         let epoll = LockedEventPoll(Arc::new(SpinLock::new(EventPoll::new())));
234         epoll.0.lock_irqsave().self_ref = Some(Arc::downgrade(&epoll.0));
235 
236         // 创建epoll的inode对象
237         let epoll_inode = EPollInode::new(epoll.clone());
238 
239         let mut ep_file = File::new(
240             epoll_inode,
241             FileMode::O_RDWR | (flags & FileMode::O_CLOEXEC),
242         )?;
243 
244         // 设置ep_file的FilePrivateData
245         ep_file.private_data = FilePrivateData::EPoll(EPollPrivateData { epoll });
246 
247         let current_pcb = ProcessManager::current_pcb();
248         let fd_table = current_pcb.fd_table();
249         let mut fd_table_guard = fd_table.write();
250 
251         let fd = fd_table_guard.alloc_fd(ep_file, None)?;
252 
253         Ok(fd as usize)
254     }
255 
256     /// ## epoll_ctl的具体实现
257     ///
258     /// 根据不同的op对epoll文件进行增删改
259     ///
260     /// ### 参数
261     /// - epfd: 操作的epoll文件描述符
262     /// - op: 对应的操作
263     /// - fd: 操作对应的文件描述符
264     /// - epds: 从用户态传入的event,若op为EpollCtlAdd,则对应注册的监听事件,若op为EPollCtlMod,则对应更新的事件,删除操作不涉及此字段
265     /// - nonblock: 定义这次操作是否为非阻塞(有可能其他地方占有EPoll的锁)
266     pub fn do_epoll_ctl(
267         epfd: i32,
268         op: EPollCtlOption,
269         fd: i32,
270         epds: &mut EPollEvent,
271         nonblock: bool,
272     ) -> Result<usize, SystemError> {
273         let current_pcb = ProcessManager::current_pcb();
274         let fd_table = current_pcb.fd_table();
275         let fd_table_guard = fd_table.read();
276 
277         // 获取epoll和对应fd指向的文件
278         let ep_file = fd_table_guard
279             .get_file_by_fd(epfd)
280             .ok_or(SystemError::EBADF)?;
281         let dst_file = fd_table_guard
282             .get_file_by_fd(fd)
283             .ok_or(SystemError::EBADF)?;
284 
285         // 检查是否允许 EPOLLWAKEUP
286         if op != EPollCtlOption::EpollCtlDel {
287             epds.events &= !EPollEventType::EPOLLWAKEUP.bits();
288         }
289 
290         let events = EPollEventType::from_bits_truncate(epds.events);
291 
292         // 检查获取到的两个文件的正确性
293         // 首先是不能自己嵌套自己
294         // 然后ep_file必须是epoll文件
295         if Arc::ptr_eq(&ep_file, &dst_file) || !Self::is_epoll_file(&ep_file) {
296             return Err(SystemError::EINVAL);
297         }
298 
299         if op != EPollCtlOption::EpollCtlDel && events.contains(EPollEventType::EPOLLEXCLUSIVE) {
300             // epoll独占模式下不允许EpollCtlMod
301             if op == EPollCtlOption::EpollCtlMod {
302                 return Err(SystemError::EINVAL);
303             }
304 
305             // 不支持嵌套的独占唤醒
306             if op == EPollCtlOption::EpollCtlAdd && Self::is_epoll_file(&dst_file)
307                 || !events
308                     .difference(EPollEventType::EPOLLEXCLUSIVE_OK_BITS)
309                     .is_empty()
310             {
311                 return Err(SystemError::EINVAL);
312             }
313         }
314 
315         // 从FilePrivateData获取到epoll
316         if let FilePrivateData::EPoll(epoll_data) = &ep_file.lock_irqsave().private_data {
317             let mut epoll_guard = {
318                 if nonblock {
319                     // 如果设置非阻塞,则尝试获取一次锁
320                     if let Ok(guard) = epoll_data.epoll.0.try_lock_irqsave() {
321                         guard
322                     } else {
323                         return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
324                     }
325                 } else {
326                     epoll_data.epoll.0.lock_irqsave()
327                 }
328             };
329 
330             if op == EPollCtlOption::EpollCtlAdd {
331                 // TODO: 循环检查是否为epoll嵌套epoll的情况,如果是则需要检测其深度
332                 // 这里是需要一种检测算法的,但是目前未考虑epoll嵌套epoll的情况,所以暂时未实现
333                 // Linux算法:https://code.dragonos.org.cn/xref/linux-6.1.9/fs/eventpoll.c?r=&mo=56953&fi=2057#2133
334                 if Self::is_epoll_file(&dst_file) {
335                     todo!();
336                 }
337             }
338 
339             let ep_item = epoll_guard.ep_items.get(&fd);
340             match op {
341                 EPollCtlOption::EpollCtlAdd => {
342                     // 如果已经存在,则返回错误
343                     if ep_item.is_some() {
344                         return Err(SystemError::EEXIST);
345                     }
346                     // 设置epoll
347                     let epitem = Arc::new(EPollItem::new(
348                         Arc::downgrade(&epoll_data.epoll.0),
349                         *epds,
350                         fd,
351                         Arc::downgrade(&dst_file),
352                     ));
353                     Self::ep_insert(&mut epoll_guard, dst_file, epitem)?;
354                 }
355                 EPollCtlOption::EpollCtlDel => {
356                     // 不存在则返回错误
357                     if ep_item.is_none() {
358                         return Err(SystemError::ENOENT);
359                     }
360                     // 删除
361                     Self::ep_remove(&mut epoll_guard, fd, Some(dst_file))?;
362                 }
363                 EPollCtlOption::EpollCtlMod => {
364                     // 不存在则返回错误
365                     if ep_item.is_none() {
366                         return Err(SystemError::ENOENT);
367                     }
368                     let ep_item = ep_item.unwrap().clone();
369                     if ep_item.event.read().events & EPollEventType::EPOLLEXCLUSIVE.bits() != 0 {
370                         epds.events |=
371                             EPollEventType::EPOLLERR.bits() | EPollEventType::EPOLLHUP.bits();
372 
373                         Self::ep_modify(&mut epoll_guard, ep_item, &epds)?;
374                     }
375                 }
376             }
377         }
378 
379         Ok(0)
380     }
381 
382     /// ## epoll_wait的具体实现
383     pub fn do_epoll_wait(
384         epfd: i32,
385         epoll_event: &mut [EPollEvent],
386         max_events: i32,
387         timespec: Option<TimeSpec>,
388     ) -> Result<usize, SystemError> {
389         let current_pcb = ProcessManager::current_pcb();
390         let fd_table = current_pcb.fd_table();
391         let fd_table_guard = fd_table.read();
392 
393         // 获取epoll文件
394         let ep_file = fd_table_guard
395             .get_file_by_fd(epfd)
396             .ok_or(SystemError::EBADF)?;
397 
398         drop(fd_table_guard);
399 
400         // 确保是epoll file
401         if !Self::is_epoll_file(&ep_file) {
402             return Err(SystemError::EINVAL);
403         }
404 
405         // 从epoll文件获取到epoll
406         let mut epolldata = None;
407         if let FilePrivateData::EPoll(epoll_data) = &ep_file.lock_irqsave().private_data {
408             epolldata = Some(epoll_data.clone())
409         }
410         if epolldata.is_some() {
411             let epoll_data = epolldata.unwrap();
412             let epoll = epoll_data.epoll.clone();
413             let epoll_guard = epoll.0.lock_irqsave();
414 
415             let mut timeout = false;
416             if timespec.is_some() {
417                 let timespec = timespec.unwrap();
418                 if !(timespec.tv_sec > 0 || timespec.tv_nsec > 0) {
419                     // 非阻塞情况
420                     timeout = true;
421                 }
422             }
423             // 判断epoll上有没有就绪事件
424             let mut available = epoll_guard.ep_events_available();
425             drop(epoll_guard);
426             loop {
427                 if available {
428                     // 如果有就绪的事件,则直接返回就绪事件
429                     return Self::ep_send_events(epoll.clone(), epoll_event, max_events);
430                 }
431 
432                 if epoll.0.lock_irqsave().shutdown.load(Ordering::SeqCst) {
433                     // 如果已经关闭
434                     return Err(SystemError::EBADF);
435                 }
436 
437                 // 如果超时
438                 if timeout {
439                     return Ok(0);
440                 }
441 
442                 // 自旋等待一段时间
443                 available = {
444                     let mut ret = false;
445                     for _ in 0..50 {
446                         if let Ok(guard) = epoll.0.try_lock_irqsave() {
447                             if guard.ep_events_available() {
448                                 ret = true;
449                                 break;
450                             }
451                         }
452                     }
453                     // 最后再次不使用try_lock尝试
454                     if !ret {
455                         ret = epoll.0.lock_irqsave().ep_events_available();
456                     }
457                     ret
458                 };
459 
460                 if available {
461                     continue;
462                 }
463 
464                 // 如果有未处理的信号则返回错误
465                 if current_pcb.sig_info().sig_pending().signal().bits() != 0 {
466                     return Err(SystemError::EINTR);
467                 }
468 
469                 // 还未等待到事件发生,则睡眠
470                 // 注册定时器
471                 let mut timer = None;
472                 if timespec.is_some() {
473                     let timespec = timespec.unwrap();
474                     let handle = WakeUpHelper::new(current_pcb.clone());
475                     let jiffies = next_n_us_timer_jiffies(
476                         (timespec.tv_sec * 1000000 + timespec.tv_nsec / 1000) as u64,
477                     );
478                     let inner = Timer::new(handle, jiffies);
479                     inner.activate();
480                     timer = Some(inner);
481                 }
482                 let guard = epoll.0.lock_irqsave();
483                 unsafe { guard.epoll_wq.sleep_without_schedule() };
484                 drop(guard);
485                 sched();
486                 // 被唤醒后,检查是否有事件可读
487                 available = epoll.0.lock_irqsave().ep_events_available();
488                 if timer.is_some() {
489                     if timer.as_ref().unwrap().timeout() {
490                         // 超时
491                         timeout = true;
492                     } else {
493                         // 未超时,则取消计时器
494                         timer.unwrap().cancel();
495                     }
496                 }
497             }
498         } else {
499             panic!("An epoll file does not have the corresponding private information");
500         }
501     }
502 
503     /// ## 将已经准备好的事件拷贝到用户空间
504     ///
505     /// ### 参数
506     /// - epoll: 对应的epoll
507     /// - user_event: 用户空间传入的epoll_event地址,因为内存对其问题,所以这里需要直接操作地址
508     /// - max_events: 处理的最大事件数量
509     fn ep_send_events(
510         epoll: LockedEventPoll,
511         user_event: &mut [EPollEvent],
512         max_events: i32,
513     ) -> Result<usize, SystemError> {
514         let mut ep_guard = epoll.0.lock_irqsave();
515         let mut res: usize = 0;
516 
517         // 在水平触发模式下,需要将epitem再次加入队列,在下次循环再次判断是否还有事件
518         // (所以边缘触发的效率会高于水平触发,但是水平触发某些情况下能够使得更迅速地向用户反馈)
519         let mut push_back = Vec::new();
520         while let Some(epitem) = ep_guard.ready_list.pop_front() {
521             if res >= max_events as usize {
522                 push_back.push(epitem);
523                 break;
524             }
525             let ep_events = EPollEventType::from_bits_truncate(epitem.event.read().events);
526 
527             // 再次poll获取事件(为了防止水平触发一直加入队列)
528             let revents = epitem.ep_item_poll();
529             if revents.is_empty() {
530                 continue;
531             }
532 
533             // 构建触发事件结构体
534             let event = EPollEvent {
535                 events: revents.bits,
536                 data: epitem.event.read().data,
537             };
538 
539             // 这里是需要判断下一个写入的位置是否为空指针
540 
541             // TODO:这里有可能会出现事件丢失的情况
542             // 如果用户传入的数组长度小于传入的max_event,到这里时如果已经到数组最大长度,但是未到max_event
543             // 会出现的问题是我们会把这个数据写入到后面的内存中,用户无法在传入的数组中拿到事件,而且写脏数据到了后面一片内存,导致事件丢失
544             // 出现这个问题的几率比较小,首先是因为用户的使用不规范,后因为前面地址校验是按照max_event来校验的,只会在两块内存连着分配时出现,但是也是需要考虑的
545 
546             // 以下的写法判断并无意义,只是记一下错误处理
547             // offset += core::mem::size_of::<EPollEvent>();
548             // if offset >= max_offset {
549             //     // 当前指向的地址已为空,则把epitem放回队列
550             //     ep_guard.ready_list.push_back(epitem.clone());
551             //     if res == 0 {
552             //         // 一个都未写入成功,表明用户传进的地址就是有问题的
553             //         return Err(SystemError::EFAULT);
554             //     }
555             // }
556 
557             // 拷贝到用户空间
558             user_event[res] = event;
559             // 记数加一
560             res += 1;
561 
562             // crate::kdebug!("ep send {event:?}");
563 
564             if ep_events.contains(EPollEventType::EPOLLONESHOT) {
565                 let mut event_writer = epitem.event.write();
566                 let new_event = event_writer.events & EPollEventType::EP_PRIVATE_BITS.bits;
567                 event_writer.set_events(new_event);
568             } else if !ep_events.contains(EPollEventType::EPOLLET) {
569                 push_back.push(epitem);
570             }
571         }
572 
573         for item in push_back {
574             ep_guard.ep_add_ready(item);
575         }
576 
577         Ok(res)
578     }
579 
580     // ### 查看文件是否为epoll文件
581     fn is_epoll_file(file: &Arc<SpinLock<File>>) -> bool {
582         if let FilePrivateData::EPoll(_) = file.lock_irqsave().private_data {
583             return true;
584         }
585         return false;
586     }
587 
588     fn ep_insert(
589         epoll_guard: &mut SpinLockGuard<EventPoll>,
590         dst_file: Arc<SpinLock<File>>,
591         epitem: Arc<EPollItem>,
592     ) -> Result<(), SystemError> {
593         if Self::is_epoll_file(&dst_file) {
594             return Err(SystemError::ENOSYS);
595             // TODO:现在的实现先不考虑嵌套其它类型的文件(暂时只针对socket),这里的嵌套指epoll/select/poll
596         }
597 
598         let test_poll = dst_file.lock_irqsave().poll();
599         if test_poll.is_err() {
600             if test_poll.unwrap_err() == SystemError::EOPNOTSUPP_OR_ENOTSUP {
601                 // 如果目标文件不支持poll
602                 return Err(SystemError::ENOSYS);
603             }
604         }
605 
606         epoll_guard.ep_items.insert(epitem.fd, epitem.clone());
607 
608         // 检查文件是否已经有事件发生
609         let event = epitem.ep_item_poll();
610         if !event.is_empty() {
611             // 加入到就绪队列
612             epoll_guard.ep_add_ready(epitem.clone());
613 
614             epoll_guard.ep_wake_one();
615         }
616 
617         // TODO: 嵌套epoll?
618 
619         // 这个标志是用与电源管理相关,暂时不支持
620         if epitem.event.read().events & EPollEventType::EPOLLWAKEUP.bits() != 0 {
621             return Err(SystemError::ENOSYS);
622         }
623 
624         dst_file.lock_irqsave().add_epoll(epitem.clone())?;
625         Ok(())
626     }
627 
628     pub fn ep_remove(
629         epoll: &mut SpinLockGuard<EventPoll>,
630         fd: i32,
631         dst_file: Option<Arc<SpinLock<File>>>,
632     ) -> Result<(), SystemError> {
633         if dst_file.is_some() {
634             let dst_file = dst_file.unwrap();
635             let mut file_guard = dst_file.lock_irqsave();
636 
637             file_guard.remove_epoll(epoll.self_ref.as_ref().unwrap())?;
638         }
639 
640         let epitem = epoll.ep_items.remove(&fd).unwrap();
641 
642         let _ = epoll
643             .ready_list
644             .extract_if(|item| Arc::ptr_eq(item, &epitem));
645 
646         Ok(())
647     }
648 
649     /// ## 修改已经注册的监听事件
650     ///
651     /// ### 参数
652     /// - epoll_guard: EventPoll的锁
653     /// - epitem: 需要修改的描述符对应的epitem
654     /// - event: 新的事件
655     fn ep_modify(
656         epoll_guard: &mut SpinLockGuard<EventPoll>,
657         epitem: Arc<EPollItem>,
658         event: &EPollEvent,
659     ) -> Result<(), SystemError> {
660         let mut epi_event_guard = epitem.event.write();
661 
662         // 修改epitem
663         epi_event_guard.events = event.events;
664         epi_event_guard.data = event.data;
665 
666         drop(epi_event_guard);
667         // 修改后检查文件是否已经有感兴趣事件发生
668         let event = epitem.ep_item_poll();
669         if !event.is_empty() {
670             epoll_guard.ep_add_ready(epitem.clone());
671 
672             epoll_guard.ep_wake_one();
673         }
674         // TODO:处理EPOLLWAKEUP,目前不支持
675 
676         Ok(())
677     }
678 
679     /// ### 判断epoll是否有就绪item
680     pub fn ep_events_available(&self) -> bool {
681         !self.ready_list.is_empty()
682     }
683 
684     /// ### 将epitem加入到就绪队列,如果为重复添加则忽略
685     pub fn ep_add_ready(&mut self, epitem: Arc<EPollItem>) {
686         let ret = self.ready_list.iter().find(|epi| Arc::ptr_eq(epi, &epitem));
687 
688         if ret.is_none() {
689             self.ready_list.push_back(epitem);
690         }
691     }
692 
693     /// ### 判断该epoll上是否有进程在等待
694     pub fn ep_has_waiter(&self) -> bool {
695         self.epoll_wq.len() != 0
696     }
697 
698     /// ### 唤醒所有在epoll上等待的进程
699     pub fn ep_wake_all(&self) {
700         self.epoll_wq.wakeup_all(None);
701     }
702 
703     /// ### 唤醒所有在epoll上等待的首个进程
704     pub fn ep_wake_one(&self) {
705         self.epoll_wq.wakeup(None);
706     }
707 
708     /// ### epoll的回调,支持epoll的文件有事件到来时直接调用该方法即可
709     pub fn wakeup_epoll(
710         epitems: &mut SpinLock<LinkedList<Arc<EPollItem>>>,
711         pollflags: EPollEventType,
712     ) -> Result<(), SystemError> {
713         let mut epitems_guard = epitems.try_lock_irqsave()?;
714         // 一次只取一个,因为一次也只有一个进程能拿到对应文件的��
715         if let Some(epitem) = epitems_guard.pop_front() {
716             let epoll = epitem.epoll().upgrade().unwrap();
717             let mut epoll_guard = epoll.try_lock()?;
718             let binding = epitem.clone();
719             let event_guard = binding.event().read();
720             let ep_events = EPollEventType::from_bits_truncate(event_guard.events());
721 
722             // 检查事件合理性以及是否有感兴趣的事件
723             if !(ep_events
724                 .difference(EPollEventType::EP_PRIVATE_BITS)
725                 .is_empty()
726                 || pollflags.difference(ep_events).is_empty())
727             {
728                 // TODO: 未处理pm相关
729 
730                 // 首先将就绪的epitem加入等待队列
731                 epoll_guard.ep_add_ready(epitem.clone());
732 
733                 if epoll_guard.ep_has_waiter() {
734                     if ep_events.contains(EPollEventType::EPOLLEXCLUSIVE)
735                         && !pollflags.contains(EPollEventType::POLLFREE)
736                     {
737                         // 避免惊群
738                         epoll_guard.ep_wake_one();
739                     } else {
740                         epoll_guard.ep_wake_all();
741                     }
742                 }
743             }
744 
745             epitems_guard.push_back(epitem);
746         }
747         Ok(())
748     }
749 }
750 
751 /// 与C兼容的Epoll事件结构体
752 #[derive(Copy, Clone, Default)]
753 #[repr(packed)]
754 pub struct EPollEvent {
755     /// 表示触发的事件
756     events: u32,
757     /// 内核态不使用该字段,该字段由用户态自由使用,在事件发生时内核将会原样返回
758     data: u64,
759 }
760 
761 impl Debug for EPollEvent {
762     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
763         let events = self.events;
764         let u64 = self.data;
765         f.debug_struct("epoll_event")
766             .field("events", &events)
767             .field("data", &u64)
768             .finish()
769     }
770 }
771 
772 impl EPollEvent {
773     pub fn set_events(&mut self, events: u32) {
774         self.events = events;
775     }
776 
777     pub fn events(&self) -> u32 {
778         self.events
779     }
780 }
781 
782 /// ## epoll_ctl函数的参数
783 #[derive(Debug, PartialEq)]
784 pub enum EPollCtlOption {
785     /// 注册新的文件描述符到epfd
786     EpollCtlAdd,
787     /// 将对应的文件描述符从epfd中删除
788     EpollCtlDel,
789     /// 修改已经注册的文件描述符的监听事件
790     EpollCtlMod,
791 }
792 
793 impl EPollCtlOption {
794     pub fn from_op_num(op: usize) -> Result<Self, SystemError> {
795         match op {
796             1 => Ok(Self::EpollCtlAdd),
797             2 => Ok(Self::EpollCtlDel),
798             3 => Ok(Self::EpollCtlMod),
799             _ => Err(SystemError::EINVAL),
800         }
801     }
802 }
803 
804 bitflags! {
805     #[allow(dead_code)]
806     pub struct EPollEventType: u32 {
807         /// 对应的描述符有新的数据可读时会触发
808         const EPOLLIN = 0x00000001;
809         /// 对应的描述符有紧急数据可读时会触发
810         const EPOLLPRI = 0x00000002;
811         /// 对应的描述符可以写入数据时会触发
812         const EPOLLOUT = 0x00000004;
813         /// 对应的描述符发生错误时会触发
814         const EPOLLERR = 0x00000008;
815         /// 对应的描述符被挂断(连接关闭)时会触发
816         const EPOLLHUP = 0x00000010;
817         /// 对应的描述符不是一个有效的文件描述符时会触发
818         const EPOLLNVAL = 0x00000020;
819         /// 普通数据可读,类似于`EPOLLIN`
820         const EPOLLRDNORM = 0x00000040;
821         /// 优先级带外数据可读
822         const EPOLLRDBAND = 0x00000080;
823         /// 普通数据可写,类似于'EPOLLOUT'
824         const EPOLLWRNORM = 0x00000100;
825         /// 优先级带外数据可写
826         const EPOLLWRBAND = 0x00000200;
827         /// 通过消息队列收到消息时会触
828         const EPOLLMSG = 0x00000400;
829         /// 对应的描述符被挂断(连接关闭)的一端发送了 FIN 时会触发(读关闭)
830         const EPOLLRDHUP = 0x00002000;
831 
832         /// 以下为额外选项
833         ///
834         /// 特定选项,用于异步 I/O,目前未实现
835         const EPOLL_URING_WAKE = 1u32 << 27;
836         /// 设置epoll为独占模式
837         const EPOLLEXCLUSIVE = 1u32 << 28;
838         ///  允许在系统挂起时唤醒 epoll,通常用于通过 eventfd 或 timerfd 唤醒 epoll,(通常与电源管理相关,未实现)
839         const EPOLLWAKEUP = 1u32 << 29;
840         /// 表示只监听一次事件,之后需要重新添加
841         const EPOLLONESHOT = 1u32 << 30;
842 
843         /// 启用边缘触发模式(即只有下次触发事件时才会通过epoll_wait返回),
844         /// 对应为水平触发(默认),水平触发模式下若这次未处理完数据,那epoll还会将其加入自己的就绪队列
845         const EPOLLET = 1u32 << 31;
846 
847         /// 以下为组合码
848         const EPOLLINOUT_BITS = Self::EPOLLIN.bits | Self::EPOLLOUT.bits;
849         const EPOLLEXCLUSIVE_OK_BITS =
850             Self::EPOLLINOUT_BITS.bits
851             | Self::EPOLLERR.bits
852             | Self::EPOLLHUP.bits
853             | Self::EPOLLWAKEUP.bits
854             | Self::EPOLLET.bits
855             | Self::EPOLLEXCLUSIVE.bits;
856 
857         const EP_PRIVATE_BITS =
858             Self::EPOLLWAKEUP.bits
859             | Self::EPOLLONESHOT.bits
860             | Self::EPOLLET.bits
861             | Self::EPOLLEXCLUSIVE.bits;
862 
863         /// 表示epoll已经被释放,但是在目前的设计中未用到
864         const POLLFREE = 0x4000;
865     }
866 }
867