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