mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 14:16:47 +00:00
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:
parent
cd3289e4b4
commit
7486ad438c
@ -6,7 +6,7 @@ use system_error::SystemError;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
libs::spinlock::{SpinLock, SpinLockGuard},
|
libs::spinlock::{SpinLock, SpinLockGuard},
|
||||||
net::event_poll::EventPoll,
|
net::event_poll::{EPollEventType, EventPoll},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::tty_core::TtyCore;
|
use super::tty_core::TtyCore;
|
||||||
@ -80,17 +80,14 @@ pub trait TtyPort: Sync + Send + Debug {
|
|||||||
/// 作为客户端的tty ports接收数据
|
/// 作为客户端的tty ports接收数据
|
||||||
fn receive_buf(&self, buf: &[u8], _flags: &[u8], count: usize) -> Result<usize, SystemError> {
|
fn receive_buf(&self, buf: &[u8], _flags: &[u8], count: usize) -> Result<usize, SystemError> {
|
||||||
let tty = self.port_data().internal_tty().unwrap();
|
let tty = self.port_data().internal_tty().unwrap();
|
||||||
|
|
||||||
let ld = tty.ldisc();
|
let ld = tty.ldisc();
|
||||||
|
|
||||||
let ret = ld.receive_buf2(tty.clone(), buf, None, count);
|
let ret = ld.receive_buf2(tty.clone(), buf, None, count);
|
||||||
|
|
||||||
if let Err(SystemError::ENOSYS) = ret {
|
if let Err(SystemError::ENOSYS) = ret {
|
||||||
return ld.receive_buf(tty, buf, None, count);
|
return ld.receive_buf(tty, buf, None, count);
|
||||||
}
|
}
|
||||||
|
let event: usize = ld.poll(tty.clone())?;
|
||||||
EventPoll::wakeup_epoll(tty.core().eptiems(), None)?;
|
let pollflag = EPollEventType::from_bits_truncate(event as u32);
|
||||||
|
EventPoll::wakeup_epoll(tty.core().eptiems(), pollflag)?;
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,7 +186,7 @@ impl IndexNode for EventFdInode {
|
|||||||
drop(eventfd);
|
drop(eventfd);
|
||||||
|
|
||||||
// 唤醒epoll中等待的进程
|
// 唤醒epoll中等待的进程
|
||||||
EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))?;
|
EventPoll::wakeup_epoll(&self.epitems, pollflag)?;
|
||||||
|
|
||||||
return Ok(8);
|
return Ok(8);
|
||||||
}
|
}
|
||||||
@ -240,7 +240,7 @@ impl IndexNode for EventFdInode {
|
|||||||
drop(eventfd);
|
drop(eventfd);
|
||||||
|
|
||||||
// 唤醒epoll中等待的进程
|
// 唤醒epoll中等待的进程
|
||||||
EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))?;
|
EventPoll::wakeup_epoll(&self.epitems, pollflag)?;
|
||||||
return Ok(8);
|
return Ok(8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,9 +64,11 @@ impl<'a> PollAdapter<'a> {
|
|||||||
fn poll_all_fds(&mut self, timeout: Option<Instant>) -> Result<usize, SystemError> {
|
fn poll_all_fds(&mut self, timeout: Option<Instant>) -> Result<usize, SystemError> {
|
||||||
let mut epoll_events = vec![EPollEvent::default(); self.poll_fds.len()];
|
let mut epoll_events = vec![EPollEvent::default(); self.poll_fds.len()];
|
||||||
let len = epoll_events.len() as i32;
|
let len = epoll_events.len() as i32;
|
||||||
let remain_timeout = timeout
|
let remain_timeout = timeout.map(|t| {
|
||||||
.and_then(|t| t.duration_since(Instant::now()))
|
t.duration_since(Instant::now())
|
||||||
.map(|t| t.into());
|
.unwrap_or(Duration::ZERO)
|
||||||
|
.into()
|
||||||
|
});
|
||||||
let events = EventPoll::epoll_wait_with_file(
|
let events = EventPoll::epoll_wait_with_file(
|
||||||
self.ep_file.clone(),
|
self.ep_file.clone(),
|
||||||
&mut epoll_events,
|
&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> {
|
fn poll_select_set_timeout(timeout_ms: u64) -> Option<Instant> {
|
||||||
if timeout_ms == 0 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(Instant::now() + Duration::from_millis(timeout_ms))
|
Some(Instant::now() + Duration::from_millis(timeout_ms))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,7 +288,7 @@ impl IndexNode for LockedPipeInode {
|
|||||||
let pollflag = EPollEventType::from_bits_truncate(inner_guard.poll(&data)? as u32);
|
let pollflag = EPollEventType::from_bits_truncate(inner_guard.poll(&data)? as u32);
|
||||||
drop(inner_guard);
|
drop(inner_guard);
|
||||||
// 唤醒epoll中等待的进程
|
// 唤醒epoll中等待的进程
|
||||||
EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))?;
|
EventPoll::wakeup_epoll(&self.epitems, pollflag)?;
|
||||||
|
|
||||||
//返回读取的字节数
|
//返回读取的字节数
|
||||||
return Ok(num);
|
return Ok(num);
|
||||||
@ -477,7 +477,7 @@ impl IndexNode for LockedPipeInode {
|
|||||||
|
|
||||||
drop(inner_guard);
|
drop(inner_guard);
|
||||||
// 唤醒epoll中等待的进程
|
// 唤醒epoll中等待的进程
|
||||||
EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))?;
|
EventPoll::wakeup_epoll(&self.epitems, pollflag)?;
|
||||||
|
|
||||||
// 返回写入的字节数
|
// 返回写入的字节数
|
||||||
return Ok(len);
|
return Ok(len);
|
||||||
|
@ -479,7 +479,7 @@ impl EventPoll {
|
|||||||
}
|
}
|
||||||
} else if timespec.is_none() {
|
} else if timespec.is_none() {
|
||||||
// 非阻塞情况
|
// 非阻塞情况
|
||||||
timeout = true;
|
timeout = false;
|
||||||
}
|
}
|
||||||
// 判断epoll上有没有就绪事件
|
// 判断epoll上有没有就绪事件
|
||||||
let mut available = epoll_guard.ep_events_available();
|
let mut available = epoll_guard.ep_events_available();
|
||||||
@ -775,52 +775,37 @@ impl EventPoll {
|
|||||||
/// ### epoll的回调,支持epoll的文件有事件到来时直接调用该方法即可
|
/// ### epoll的回调,支持epoll的文件有事件到来时直接调用该方法即可
|
||||||
pub fn wakeup_epoll(
|
pub fn wakeup_epoll(
|
||||||
epitems: &SpinLock<LinkedList<Arc<EPollItem>>>,
|
epitems: &SpinLock<LinkedList<Arc<EPollItem>>>,
|
||||||
pollflags: Option<EPollEventType>,
|
pollflags: EPollEventType,
|
||||||
) -> Result<(), SystemError> {
|
) -> Result<(), SystemError> {
|
||||||
let mut epitems_guard = epitems.try_lock_irqsave()?;
|
let epitems_guard = epitems.try_lock_irqsave()?;
|
||||||
// 一次只取一个,因为一次也只有一个进程能拿到对应文件的🔓
|
for epitem in epitems_guard.iter() {
|
||||||
if let Some(epitem) = epitems_guard.pop_front() {
|
// The upgrade is safe because EventPoll always exists when the epitem is in the list
|
||||||
let pollflags = match pollflags {
|
let epoll = epitem.epoll().upgrade().unwrap();
|
||||||
Some(flags) => flags,
|
let mut epoll_guard = epoll.try_lock()?;
|
||||||
None => {
|
let binding = epitem.clone();
|
||||||
if let Some(file) = epitem.file.upgrade() {
|
let event_guard = binding.event().read();
|
||||||
// warning: deadlock will happen if poll() is called when pollflags is None
|
let ep_events = EPollEventType::from_bits_truncate(event_guard.events());
|
||||||
EPollEventType::from_bits_truncate(file.poll()? as u32)
|
// 检查事件合理性以及是否有感兴趣的事件
|
||||||
|
if !(ep_events
|
||||||
|
.difference(EPollEventType::EP_PRIVATE_BITS)
|
||||||
|
.is_empty()
|
||||||
|
|| pollflags.difference(ep_events).is_empty())
|
||||||
|
{
|
||||||
|
// TODO: 未处理pm相关
|
||||||
|
|
||||||
|
// 首先将就绪的epitem加入等待队列
|
||||||
|
epoll_guard.ep_add_ready(epitem.clone());
|
||||||
|
|
||||||
|
if epoll_guard.ep_has_waiter() {
|
||||||
|
if ep_events.contains(EPollEventType::EPOLLEXCLUSIVE)
|
||||||
|
&& !pollflags.contains(EPollEventType::POLLFREE)
|
||||||
|
{
|
||||||
|
// 避免惊群
|
||||||
|
epoll_guard.ep_wake_one();
|
||||||
} else {
|
} else {
|
||||||
EPollEventType::empty()
|
epoll_guard.ep_wake_all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(epoll) = epitem.epoll().upgrade() {
|
|
||||||
let mut epoll_guard = epoll.try_lock()?;
|
|
||||||
let binding = epitem.clone();
|
|
||||||
let event_guard = binding.event().read();
|
|
||||||
let ep_events = EPollEventType::from_bits_truncate(event_guard.events());
|
|
||||||
// 检查事件合理性以及是否有感兴趣的事件
|
|
||||||
if !(ep_events
|
|
||||||
.difference(EPollEventType::EP_PRIVATE_BITS)
|
|
||||||
.is_empty()
|
|
||||||
|| pollflags.difference(ep_events).is_empty())
|
|
||||||
{
|
|
||||||
// TODO: 未处理pm相关
|
|
||||||
|
|
||||||
// 首先将就绪的epitem加入等待队列
|
|
||||||
epoll_guard.ep_add_ready(epitem.clone());
|
|
||||||
|
|
||||||
if epoll_guard.ep_has_waiter() {
|
|
||||||
if ep_events.contains(EPollEventType::EPOLLEXCLUSIVE)
|
|
||||||
&& !pollflags.contains(EPollEventType::POLLFREE)
|
|
||||||
{
|
|
||||||
// 避免惊群
|
|
||||||
epoll_guard.ep_wake_one();
|
|
||||||
} else {
|
|
||||||
epoll_guard.ep_wake_all();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
epitems_guard.push_back(epitem);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -245,7 +245,7 @@ fn send_event(sockets: &smoltcp::iface::SocketSet) -> Result<(), SystemError> {
|
|||||||
}
|
}
|
||||||
EventPoll::wakeup_epoll(
|
EventPoll::wakeup_epoll(
|
||||||
&posix_item.epitems,
|
&posix_item.epitems,
|
||||||
Some(EPollEventType::from_bits_truncate(events as u32)),
|
EPollEventType::from_bits_truncate(events as u32),
|
||||||
)?;
|
)?;
|
||||||
drop(handle_guard);
|
drop(handle_guard);
|
||||||
// crate::debug!(
|
// crate::debug!(
|
||||||
|
@ -77,7 +77,7 @@ impl PerfEventInode {
|
|||||||
fn epoll_callback(&self) -> Result<()> {
|
fn epoll_callback(&self) -> Result<()> {
|
||||||
let pollflag = EPollEventType::from_bits_truncate(self.do_poll()? as u32);
|
let pollflag = EPollEventType::from_bits_truncate(self.do_poll()? as u32);
|
||||||
// 唤醒epoll中等待的进程
|
// 唤醒epoll中等待的进程
|
||||||
EventPoll::wakeup_epoll(&self.epitems, Some(pollflag))
|
EventPoll::wakeup_epoll(&self.epitems, pollflag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,19 +98,26 @@ int main() {
|
|||||||
printf("主线程:epoll_wait 返回,事件数量 = %d\n", nfds);
|
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++) {
|
for (int i = 0; i < nfds; i++) {
|
||||||
// if (events[i].data.fd == efd || events[i].data.fd == efd2) {
|
if (events[i].data.fd == efd || events[i].data.fd == efd2) {
|
||||||
// uint64_t count;
|
uint64_t count;
|
||||||
// int fd = events[i].data.fd;
|
int fd = events[i].data.fd;
|
||||||
// printf("主线程:事件发生在 fd = %d\n", fd);
|
printf("主线程:事件发生在 fd = %d\n", fd);
|
||||||
// if (read(fd, &count, sizeof(count)) != sizeof(count)) {
|
if (read(fd, &count, sizeof(count)) != sizeof(count)) {
|
||||||
// perror("从 eventfd 读取失败");
|
perror("从 eventfd 读取失败");
|
||||||
// exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
// }
|
}
|
||||||
// printf("主线程:接收到 eventfd 事件,计数值 = %lu\n", count);
|
printf("主线程:接收到 eventfd 事件,计数值 = %lu\n", count);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// 等待工作线程结束
|
// 等待工作线程结束
|
||||||
pthread_join(tid, NULL);
|
pthread_join(tid, NULL);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user