fix bugs in poll and epoll (#1135)

* fix bugs in poll and epoll

Signed-off-by: Godones <chenlinfeng25@outlook.com>

* fix: wakeup all epitems instead of the first

Signed-off-by: Godones <chenlinfeng25@outlook.com>

* Fix wakeup_epoll error

Signed-off-by: Godones <chenlinfeng25@outlook.com>

* Make test_epoll pass

Signed-off-by: Godones <chenlinfeng25@outlook.com>

---------

Signed-off-by: Godones <chenlinfeng25@outlook.com>
This commit is contained in:
linfeng 2025-05-09 23:08:50 +08:00 committed by GitHub
parent cd3289e4b4
commit 7486ad438c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 62 additions and 75 deletions

View File

@ -6,7 +6,7 @@ use system_error::SystemError;
use crate::{
libs::spinlock::{SpinLock, SpinLockGuard},
net::event_poll::EventPoll,
net::event_poll::{EPollEventType, EventPoll},
};
use super::tty_core::TtyCore;
@ -80,17 +80,14 @@ pub trait TtyPort: Sync + Send + Debug {
/// 作为客户端的tty ports接收数据
fn receive_buf(&self, buf: &[u8], _flags: &[u8], count: usize) -> Result<usize, SystemError> {
let tty = self.port_data().internal_tty().unwrap();
let ld = tty.ldisc();
let ret = ld.receive_buf2(tty.clone(), buf, None, count);
if let Err(SystemError::ENOSYS) = ret {
return ld.receive_buf(tty, buf, None, count);
}
EventPoll::wakeup_epoll(tty.core().eptiems(), None)?;
let event: usize = ld.poll(tty.clone())?;
let pollflag = EPollEventType::from_bits_truncate(event as u32);
EventPoll::wakeup_epoll(tty.core().eptiems(), pollflag)?;
ret
}
}

View File

@ -186,7 +186,7 @@ impl IndexNode for EventFdInode {
drop(eventfd);
// 唤醒epoll中等待的进程
EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))?;
EventPoll::wakeup_epoll(&self.epitems, pollflag)?;
return Ok(8);
}
@ -240,7 +240,7 @@ impl IndexNode for EventFdInode {
drop(eventfd);
// 唤醒epoll中等待的进程
EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))?;
EventPoll::wakeup_epoll(&self.epitems, pollflag)?;
return Ok(8);
}

View File

@ -64,9 +64,11 @@ impl<'a> PollAdapter<'a> {
fn poll_all_fds(&mut self, timeout: Option<Instant>) -> Result<usize, SystemError> {
let mut epoll_events = vec![EPollEvent::default(); self.poll_fds.len()];
let len = epoll_events.len() as i32;
let remain_timeout = timeout
.and_then(|t| t.duration_since(Instant::now()))
.map(|t| t.into());
let remain_timeout = timeout.map(|t| {
t.duration_since(Instant::now())
.unwrap_or(Duration::ZERO)
.into()
});
let events = EventPoll::epoll_wait_with_file(
self.ep_file.clone(),
&mut epoll_events,
@ -176,10 +178,6 @@ fn do_sys_poll(poll_fds: &mut [PollFd], timeout: Option<Instant>) -> Result<usiz
/// 计算超时的时刻
fn poll_select_set_timeout(timeout_ms: u64) -> Option<Instant> {
if timeout_ms == 0 {
return None;
}
Some(Instant::now() + Duration::from_millis(timeout_ms))
}

View File

@ -288,7 +288,7 @@ impl IndexNode for LockedPipeInode {
let pollflag = EPollEventType::from_bits_truncate(inner_guard.poll(&data)? as u32);
drop(inner_guard);
// 唤醒epoll中等待的进程
EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))?;
EventPoll::wakeup_epoll(&self.epitems, pollflag)?;
//返回读取的字节数
return Ok(num);
@ -477,7 +477,7 @@ impl IndexNode for LockedPipeInode {
drop(inner_guard);
// 唤醒epoll中等待的进程
EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))?;
EventPoll::wakeup_epoll(&self.epitems, pollflag)?;
// 返回写入的字节数
return Ok(len);

View File

@ -479,7 +479,7 @@ impl EventPoll {
}
} else if timespec.is_none() {
// 非阻塞情况
timeout = true;
timeout = false;
}
// 判断epoll上有没有就绪事件
let mut available = epoll_guard.ep_events_available();
@ -775,24 +775,12 @@ impl EventPoll {
/// ### epoll的回调支持epoll的文件有事件到来时直接调用该方法即可
pub fn wakeup_epoll(
epitems: &SpinLock<LinkedList<Arc<EPollItem>>>,
pollflags: Option<EPollEventType>,
pollflags: EPollEventType,
) -> Result<(), SystemError> {
let mut epitems_guard = epitems.try_lock_irqsave()?;
// 一次只取一个,因为一次也只有一个进程能拿到对应文件的🔓
if let Some(epitem) = epitems_guard.pop_front() {
let pollflags = match pollflags {
Some(flags) => flags,
None => {
if let Some(file) = epitem.file.upgrade() {
// warning: deadlock will happen if poll() is called when pollflags is None
EPollEventType::from_bits_truncate(file.poll()? as u32)
} else {
EPollEventType::empty()
}
}
};
if let Some(epoll) = epitem.epoll().upgrade() {
let epitems_guard = epitems.try_lock_irqsave()?;
for epitem in epitems_guard.iter() {
// The upgrade is safe because EventPoll always exists when the epitem is in the list
let epoll = epitem.epoll().upgrade().unwrap();
let mut epoll_guard = epoll.try_lock()?;
let binding = epitem.clone();
let event_guard = binding.event().read();
@ -819,9 +807,6 @@ impl EventPoll {
}
}
}
epitems_guard.push_back(epitem);
}
}
Ok(())
}

View File

@ -245,7 +245,7 @@ fn send_event(sockets: &smoltcp::iface::SocketSet) -> Result<(), SystemError> {
}
EventPoll::wakeup_epoll(
&posix_item.epitems,
Some(EPollEventType::from_bits_truncate(events as u32)),
EPollEventType::from_bits_truncate(events as u32),
)?;
drop(handle_guard);
// crate::debug!(

View File

@ -77,7 +77,7 @@ impl PerfEventInode {
fn epoll_callback(&self) -> Result<()> {
let pollflag = EPollEventType::from_bits_truncate(self.do_poll()? as u32);
// 唤醒epoll中等待的进程
EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))
EventPoll::wakeup_epoll(&self.epitems, pollflag)
}
}

View File

@ -98,19 +98,26 @@ int main() {
printf("主线程epoll_wait 返回,事件数量 = %d\n", nfds);
}
if (nfds != 2) {
printf("主线程:事件数量不匹配,预期 2实际 %d\n", nfds);
exit(EXIT_FAILURE);
}
// 由于dup复制了 eventfd 描述符,所以 只需要处理一个就行
nfds -= 1;
// 处理就绪事件
// for (int i = 0; i < nfds; i++) {
// if (events[i].data.fd == efd || events[i].data.fd == efd2) {
// uint64_t count;
// int fd = events[i].data.fd;
// printf("主线程:事件发生在 fd = %d\n", fd);
// if (read(fd, &count, sizeof(count)) != sizeof(count)) {
// perror("从 eventfd 读取失败");
// exit(EXIT_FAILURE);
// }
// printf("主线程:接收到 eventfd 事件,计数值 = %lu\n", count);
// }
// }
for (int i = 0; i < nfds; i++) {
if (events[i].data.fd == efd || events[i].data.fd == efd2) {
uint64_t count;
int fd = events[i].data.fd;
printf("主线程:事件发生在 fd = %d\n", fd);
if (read(fd, &count, sizeof(count)) != sizeof(count)) {
perror("从 eventfd 读取失败");
exit(EXIT_FAILURE);
}
printf("主线程:接收到 eventfd 事件,计数值 = %lu\n", count);
}
}
// 等待工作线程结束
pthread_join(tid, NULL);