xref: /DragonOS/kernel/src/net/event_poll/mod.rs (revision 911132c4b8ea0e9c49a4e84b9fa1db114102acbb)
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     /// 用于获取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<SpinLock<File>>,
86 }
87 
88 impl EPollItem {
89     pub fn new(
90         epoll: Weak<SpinLock<EventPoll>>,
91         events: EPollEvent,
92         fd: i32,
93         file: Weak<SpinLock<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<SpinLock<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().lock_irqsave().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: &mut crate::filesystem::vfs::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: &mut crate::filesystem::vfs::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: &mut 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()
212                     .lock_irqsave()
213                     .remove_epoll(&Arc::downgrade(&self.epoll.0))?;
214             }
215 
216             epoll.ep_items.remove(&fd);
217         }
218 
219         Ok(())
220     }
221 
222     fn open(&self, _data: &mut FilePrivateData, _mode: &FileMode) -> Result<(), SystemError> {
223         Ok(())
224     }
225 }
226 
227 impl EventPoll {
228     /// ## 创建epoll对象
229     ///
230     /// ### 参数
231     /// - flags: 创建的epoll文件的FileMode
232     ///
233     /// ### 返回值
234     /// - 成功则返回Ok(fd),否则返回Err
235     pub fn do_create_epoll(flags: FileMode) -> Result<usize, SystemError> {
236         if !flags.difference(FileMode::O_CLOEXEC).is_empty() {
237             return Err(SystemError::EINVAL);
238         }
239 
240         // 创建epoll
241         let epoll = LockedEventPoll(Arc::new(SpinLock::new(EventPoll::new())));
242         epoll.0.lock_irqsave().self_ref = Some(Arc::downgrade(&epoll.0));
243 
244         // 创建epoll的inode对象
245         let epoll_inode = EPollInode::new(epoll.clone());
246 
247         let mut ep_file = File::new(
248             epoll_inode,
249             FileMode::O_RDWR | (flags & FileMode::O_CLOEXEC),
250         )?;
251 
252         // 设置ep_file的FilePrivateData
253         ep_file.private_data = FilePrivateData::EPoll(EPollPrivateData { epoll });
254 
255         let current_pcb = ProcessManager::current_pcb();
256         let fd_table = current_pcb.fd_table();
257         let mut fd_table_guard = fd_table.write();
258 
259         let fd = fd_table_guard.alloc_fd(ep_file, None)?;
260 
261         Ok(fd as usize)
262     }
263 
264     /// ## epoll_ctl的具体实现
265     ///
266     /// 根据不同的op对epoll文件进行增删改
267     ///
268     /// ### 参数
269     /// - epfd: 操作的epoll文件描述符
270     /// - op: 对应的操作
271     /// - fd: 操作对应的文件描述符
272     /// - epds: 从用户态传入的event,若op为EpollCtlAdd,则对应注册的监听事件,若op为EPollCtlMod,则对应更新的事件,删除操作不涉及此字段
273     /// - nonblock: 定义这次操作是否为非阻塞(有可能其他地方占有EPoll的锁)
274     pub fn do_epoll_ctl(
275         epfd: i32,
276         op: EPollCtlOption,
277         fd: i32,
278         epds: &mut EPollEvent,
279         nonblock: bool,
280     ) -> Result<usize, SystemError> {
281         let current_pcb = ProcessManager::current_pcb();
282         let fd_table = current_pcb.fd_table();
283         let fd_table_guard = fd_table.read();
284 
285         // 获取epoll和对应fd指向的文件
286         let ep_file = fd_table_guard
287             .get_file_by_fd(epfd)
288             .ok_or(SystemError::EBADF)?;
289         let dst_file = fd_table_guard
290             .get_file_by_fd(fd)
291             .ok_or(SystemError::EBADF)?;
292 
293         // 检查是否允许 EPOLLWAKEUP
294         if op != EPollCtlOption::Del {
295             epds.events &= !EPollEventType::EPOLLWAKEUP.bits();
296         }
297 
298         let events = EPollEventType::from_bits_truncate(epds.events);
299 
300         // 检查获取到的两个文件的正确性
301         // 首先是不能自己嵌套自己
302         // 然后ep_file必须是epoll文件
303         if Arc::ptr_eq(&ep_file, &dst_file) || !Self::is_epoll_file(&ep_file) {
304             return Err(SystemError::EINVAL);
305         }
306 
307         if op != EPollCtlOption::Del && events.contains(EPollEventType::EPOLLEXCLUSIVE) {
308             // epoll独占模式下不允许EpollCtlMod
309             if op == EPollCtlOption::Mod {
310                 return Err(SystemError::EINVAL);
311             }
312 
313             // 不支持嵌套的独占唤醒
314             if op == EPollCtlOption::Add && Self::is_epoll_file(&dst_file)
315                 || !events
316                     .difference(EPollEventType::EPOLLEXCLUSIVE_OK_BITS)
317                     .is_empty()
318             {
319                 return Err(SystemError::EINVAL);
320             }
321         }
322 
323         // 从FilePrivateData获取到epoll
324         if let FilePrivateData::EPoll(epoll_data) = &ep_file.lock_irqsave().private_data {
325             let mut epoll_guard = {
326                 if nonblock {
327                     // 如果设置非阻塞,则尝试获取一次锁
328                     if let Ok(guard) = epoll_data.epoll.0.try_lock_irqsave() {
329                         guard
330                     } else {
331                         return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
332                     }
333                 } else {
334                     epoll_data.epoll.0.lock_irqsave()
335                 }
336             };
337 
338             if op == EPollCtlOption::Add {
339                 // TODO: 循环检查是否为epoll嵌套epoll的情况,如果是则需要检测其深度
340                 // 这里是需要一种检测算法的,但是目前未考虑epoll嵌套epoll的情况,所以暂时未实现
341                 // Linux算法:https://code.dragonos.org.cn/xref/linux-6.1.9/fs/eventpoll.c?r=&mo=56953&fi=2057#2133
342                 if Self::is_epoll_file(&dst_file) {
343                     todo!();
344                 }
345             }
346 
347             let ep_item = epoll_guard.ep_items.get(&fd);
348             match op {
349                 EPollCtlOption::Add => {
350                     // 如果已经存在,则返回错误
351                     if ep_item.is_some() {
352                         return Err(SystemError::EEXIST);
353                     }
354                     // 设置epoll
355                     let epitem = Arc::new(EPollItem::new(
356                         Arc::downgrade(&epoll_data.epoll.0),
357                         *epds,
358                         fd,
359                         Arc::downgrade(&dst_file),
360                     ));
361                     Self::ep_insert(&mut epoll_guard, dst_file, epitem)?;
362                 }
363                 EPollCtlOption::Del => {
364                     // 不存在则返回错误
365                     if ep_item.is_none() {
366                         return Err(SystemError::ENOENT);
367                     }
368                     // 删除
369                     Self::ep_remove(&mut epoll_guard, fd, Some(dst_file))?;
370                 }
371                 EPollCtlOption::Mod => {
372                     // 不存在则返回错误
373                     if ep_item.is_none() {
374                         return Err(SystemError::ENOENT);
375                     }
376                     let ep_item = ep_item.unwrap().clone();
377                     if ep_item.event.read().events & EPollEventType::EPOLLEXCLUSIVE.bits() != 0 {
378                         epds.events |=
379                             EPollEventType::EPOLLERR.bits() | EPollEventType::EPOLLHUP.bits();
380 
381                         Self::ep_modify(&mut epoll_guard, ep_item, epds)?;
382                     }
383                 }
384             }
385         }
386 
387         Ok(0)
388     }
389 
390     /// ## epoll_wait的具体实现
391     pub fn do_epoll_wait(
392         epfd: i32,
393         epoll_event: &mut [EPollEvent],
394         max_events: i32,
395         timespec: Option<TimeSpec>,
396     ) -> Result<usize, SystemError> {
397         let current_pcb = ProcessManager::current_pcb();
398         let fd_table = current_pcb.fd_table();
399         let fd_table_guard = fd_table.read();
400 
401         // 获取epoll文件
402         let ep_file = fd_table_guard
403             .get_file_by_fd(epfd)
404             .ok_or(SystemError::EBADF)?;
405 
406         drop(fd_table_guard);
407 
408         // 确保是epoll file
409         if !Self::is_epoll_file(&ep_file) {
410             return Err(SystemError::EINVAL);
411         }
412 
413         // 从epoll文件获取到epoll
414         let mut epolldata = None;
415         if let FilePrivateData::EPoll(epoll_data) = &ep_file.lock_irqsave().private_data {
416             epolldata = Some(epoll_data.clone())
417         }
418         if let Some(epoll_data) = epolldata {
419             let epoll = epoll_data.epoll.clone();
420             let epoll_guard = epoll.0.lock_irqsave();
421 
422             let mut timeout = false;
423             if let Some(timespec) = timespec {
424                 if !(timespec.tv_sec > 0 || timespec.tv_nsec > 0) {
425                     // 非阻塞情况
426                     timeout = true;
427                 }
428             }
429             // 判断epoll上有没有就绪事件
430             let mut available = epoll_guard.ep_events_available();
431             drop(epoll_guard);
432             loop {
433                 if available {
434                     // 如果有就绪的事件,则直接返回就绪事件
435                     return Self::ep_send_events(epoll.clone(), epoll_event, max_events);
436                 }
437 
438                 if epoll.0.lock_irqsave().shutdown.load(Ordering::SeqCst) {
439                     // 如果已经关闭
440                     return Err(SystemError::EBADF);
441                 }
442 
443                 // 如果超时
444                 if timeout {
445                     return Ok(0);
446                 }
447 
448                 // 自旋等待一段时间
449                 available = {
450                     let mut ret = false;
451                     for _ in 0..50 {
452                         if let Ok(guard) = epoll.0.try_lock_irqsave() {
453                             if guard.ep_events_available() {
454                                 ret = true;
455                                 break;
456                             }
457                         }
458                     }
459                     // 最后再次不使用try_lock尝试
460                     if !ret {
461                         ret = epoll.0.lock_irqsave().ep_events_available();
462                     }
463                     ret
464                 };
465 
466                 if available {
467                     continue;
468                 }
469 
470                 // 如果有未处理的信号则返回错误
471                 if current_pcb.sig_info_irqsave().sig_pending().signal().bits() != 0 {
472                     return Err(SystemError::EINTR);
473                 }
474 
475                 // 还未等待到事件发生,则睡眠
476                 // 注册定时器
477                 let mut timer = None;
478                 if let Some(timespec) = timespec {
479                     let handle = WakeUpHelper::new(current_pcb.clone());
480                     let jiffies = next_n_us_timer_jiffies(
481                         (timespec.tv_sec * 1000000 + timespec.tv_nsec / 1000) as u64,
482                     );
483                     let inner = Timer::new(handle, jiffies);
484                     inner.activate();
485                     timer = Some(inner);
486                 }
487                 let guard = epoll.0.lock_irqsave();
488                 unsafe { guard.epoll_wq.sleep_without_schedule() };
489                 drop(guard);
490                 sched();
491                 // 被唤醒后,检查是否有事件可读
492                 available = epoll.0.lock_irqsave().ep_events_available();
493                 if let Some(timer) = timer {
494                     if timer.as_ref().timeout() {
495                         // 超时
496                         timeout = true;
497                     } else {
498                         // 未超时,则取消计时器
499                         timer.cancel();
500                     }
501                 }
502             }
503         } else {
504             panic!("An epoll file does not have the corresponding private information");
505         }
506     }
507 
508     /// ## 将已经准备好的事件拷贝到用户空间
509     ///
510     /// ### 参数
511     /// - epoll: 对应的epoll
512     /// - user_event: 用户空间传入的epoll_event地址,因为内存对其问题,所以这里需要直接操作地址
513     /// - max_events: 处理的最大事件数量
514     fn ep_send_events(
515         epoll: LockedEventPoll,
516         user_event: &mut [EPollEvent],
517         max_events: i32,
518     ) -> Result<usize, SystemError> {
519         let mut ep_guard = epoll.0.lock_irqsave();
520         let mut res: usize = 0;
521 
522         // 在水平触发模式下,需要将epitem再次加入队列,在下次循环再次判断是否还有事件
523         // (所以边缘触发的效率会高于水平触发,但是水平触发某些情况下能够使得更迅速地向用户反馈)
524         let mut push_back = Vec::new();
525         while let Some(epitem) = ep_guard.ready_list.pop_front() {
526             if res >= max_events as usize {
527                 push_back.push(epitem);
528                 break;
529             }
530             let ep_events = EPollEventType::from_bits_truncate(epitem.event.read().events);
531 
532             // 再次poll获取事件(为了防止水平触发一直加入队列)
533             let revents = epitem.ep_item_poll();
534             if revents.is_empty() {
535                 continue;
536             }
537 
538             // 构建触发事件结构体
539             let event = EPollEvent {
540                 events: revents.bits,
541                 data: epitem.event.read().data,
542             };
543 
544             // 这里是需要判断下一个写入的位置是否为空指针
545 
546             // TODO:这里有可能会出现事件丢失的情况
547             // 如果用户传入的数组长度小于传入的max_event,到这里时如果已经到数组最大长度,但是未到max_event
548             // 会出现的问题是我们会把这个数据写入到后面的内存中,用户无法在传入的数组中拿到事件,而且写脏数据到了后面一片内存,导致事件丢失
549             // 出现这个问题的几率比较小,首先是因为用户的使用不规范,后因为前面地址校验是按照max_event来校验的,只会在两块内存连着分配时出现,但是也是需要考虑的
550 
551             // 以下的写法判断并无意义,只是记一下错误处理
552             // offset += core::mem::size_of::<EPollEvent>();
553             // if offset >= max_offset {
554             //     // 当前指向的地址已为空,则把epitem放回队列
555             //     ep_guard.ready_list.push_back(epitem.clone());
556             //     if res == 0 {
557             //         // 一个都未写入成功,表明用户传进的地址就是有问题的
558             //         return Err(SystemError::EFAULT);
559             //     }
560             // }
561 
562             // 拷贝到用户空间
563             user_event[res] = event;
564             // 记数加一
565             res += 1;
566 
567             // crate::kdebug!("ep send {event:?}");
568 
569             if ep_events.contains(EPollEventType::EPOLLONESHOT) {
570                 let mut event_writer = epitem.event.write();
571                 let new_event = event_writer.events & EPollEventType::EP_PRIVATE_BITS.bits;
572                 event_writer.set_events(new_event);
573             } else if !ep_events.contains(EPollEventType::EPOLLET) {
574                 push_back.push(epitem);
575             }
576         }
577 
578         for item in push_back {
579             ep_guard.ep_add_ready(item);
580         }
581 
582         Ok(res)
583     }
584 
585     // ### 查看文件是否为epoll文件
586     fn is_epoll_file(file: &Arc<SpinLock<File>>) -> bool {
587         if let FilePrivateData::EPoll(_) = file.lock_irqsave().private_data {
588             return true;
589         }
590         return false;
591     }
592 
593     fn ep_insert(
594         epoll_guard: &mut SpinLockGuard<EventPoll>,
595         dst_file: Arc<SpinLock<File>>,
596         epitem: Arc<EPollItem>,
597     ) -> Result<(), SystemError> {
598         if Self::is_epoll_file(&dst_file) {
599             return Err(SystemError::ENOSYS);
600             // TODO:现在的实现先不考虑嵌套其它类型的文件(暂时只针对socket),这里的嵌套指epoll/select/poll
601         }
602 
603         let test_poll = dst_file.lock_irqsave().poll();
604         if test_poll.is_err() && test_poll.unwrap_err() == SystemError::EOPNOTSUPP_OR_ENOTSUP {
605             // 如果目标文件不支持poll
606             return Err(SystemError::ENOSYS);
607         }
608 
609         epoll_guard.ep_items.insert(epitem.fd, epitem.clone());
610 
611         // 检查文件是否已经有事件发生
612         let event = epitem.ep_item_poll();
613         if !event.is_empty() {
614             // 加入到就绪队列
615             epoll_guard.ep_add_ready(epitem.clone());
616 
617             epoll_guard.ep_wake_one();
618         }
619 
620         // TODO: 嵌套epoll?
621 
622         // 这个标志是用与电源管理相关,暂时不支持
623         if epitem.event.read().events & EPollEventType::EPOLLWAKEUP.bits() != 0 {
624             return Err(SystemError::ENOSYS);
625         }
626 
627         dst_file.lock_irqsave().add_epoll(epitem.clone())?;
628         Ok(())
629     }
630 
631     pub fn ep_remove(
632         epoll: &mut SpinLockGuard<EventPoll>,
633         fd: i32,
634         dst_file: Option<Arc<SpinLock<File>>>,
635     ) -> Result<(), SystemError> {
636         if let Some(dst_file) = dst_file {
637             let mut file_guard = dst_file.lock_irqsave();
638 
639             file_guard.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