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