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