Skip to content

Commit 9289553

Browse files
authored
fix(epoll): 修复epoll超时唤醒机制,确保定时器通过Waker唤醒等待队列 (#1492)
- 重构定时器创建逻辑,使用EpollTimeoutWaker结构体实现TimerFunction - 将超时唤醒方式从直接唤醒PCB改为通过Waker::wake()触发 Signed-off-by: longjin <longjin@DragonOS.org>
1 parent 6ec1dd5 commit 9289553

File tree

1 file changed

+34
-15
lines changed

1 file changed

+34
-15
lines changed

kernel/src/filesystem/epoll/event_poll.rs

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
use core::{
2-
fmt::Debug,
3-
sync::atomic::{AtomicBool, Ordering},
4-
};
5-
61
use crate::{
72
filesystem::vfs::{
83
file::{File, FileFlags},
@@ -11,14 +6,18 @@ use crate::{
116
libs::{
127
rbtree::RBTree,
138
spinlock::{SpinLock, SpinLockGuard},
14-
wait_queue::{WaitQueue, Waiter},
9+
wait_queue::{WaitQueue, Waiter, Waker},
1510
},
1611
process::ProcessManager,
1712
time::{
18-
timer::{next_n_us_timer_jiffies, Timer, WakeUpHelper},
13+
timer::{next_n_us_timer_jiffies, Timer, TimerFunction},
1914
PosixTimeSpec,
2015
},
2116
};
17+
use core::{
18+
fmt::Debug,
19+
sync::atomic::{AtomicBool, Ordering},
20+
};
2221

2322
use alloc::{
2423
collections::LinkedList,
@@ -29,6 +28,22 @@ use system_error::SystemError;
2928

3029
use super::{fs::EPollInode, EPollCtlOption, EPollEvent, EPollEventType, EPollItem};
3130

31+
use alloc::boxed::Box;
32+
33+
#[derive(Debug)]
34+
struct EpollTimeoutWaker {
35+
waker: Arc<Waker>,
36+
}
37+
38+
impl TimerFunction for EpollTimeoutWaker {
39+
fn run(&mut self) -> Result<(), SystemError> {
40+
// Wake the waiter (and thus the process) in a way Waiter::wait can observe.
41+
// NOTE: Timer-based wakeup must go through Waker::wake(); waking PCB alone is insufficient.
42+
self.waker.wake();
43+
Ok(())
44+
}
45+
}
46+
3247
/// 内核的Epoll对象结构体,当用户创建一个Epoll时,内核就会创建一个该类型对象
3348
/// 它对应一个epfd
3449
#[derive(Debug)]
@@ -329,6 +344,7 @@ impl EventPoll {
329344
}
330345
if let Some(epoll_data) = epolldata {
331346
let epoll = epoll_data.epoll.clone();
347+
332348
let epoll_guard = epoll.0.lock_irqsave();
333349

334350
let mut timeout = false;
@@ -391,19 +407,22 @@ impl EventPoll {
391407
}
392408

393409
// 还未等待到事件发生,则睡眠
394-
// 注册定时器
410+
// 构造一次等待(先构造 Waiter/Waker,超时需要通过 Waker::wake 触发)
411+
let (waiter, waker) = Waiter::new_pair();
412+
413+
// 注册定时器:用 waker.wake() 来触发 waiter 退出等待(而不是仅唤醒 PCB)
395414
let mut timer = None;
396415
if let Some(timespec) = timespec {
397-
let handle = WakeUpHelper::new(current_pcb.clone());
398-
let jiffies = next_n_us_timer_jiffies(
399-
(timespec.tv_sec * 1000000 + timespec.tv_nsec / 1000) as u64,
416+
let us = (timespec.tv_sec * 1_000_000 + timespec.tv_nsec / 1_000) as u64;
417+
let jiffies = next_n_us_timer_jiffies(us);
418+
let inner: Arc<Timer> = Timer::new(
419+
Box::new(EpollTimeoutWaker {
420+
waker: waker.clone(),
421+
}),
422+
jiffies,
400423
);
401-
let inner: Arc<Timer> = Timer::new(handle, jiffies);
402-
inner.activate();
403424
timer = Some(inner);
404425
}
405-
// 构造一次等待
406-
let (waiter, waker) = Waiter::new_pair();
407426
{
408427
let guard = epoll.0.lock_irqsave();
409428
// 注册前再次检查,避免错过事件

0 commit comments

Comments
 (0)