修正pipe逻辑,将pipe接入epoll。 (#478)

This commit is contained in:
GnoCiYeH
2023-12-27 15:02:29 +08:00
committed by GitHub
parent 0d6cf65aa1
commit 5e948c5650
8 changed files with 201 additions and 89 deletions

View File

@ -161,7 +161,7 @@ impl IndexNode for EPollInode {
Err(SystemError::ENOSYS)
}
fn poll(&self) -> Result<usize, SystemError> {
fn poll(&self, _private_data: &FilePrivateData) -> Result<usize, SystemError> {
// 需要实现epoll嵌套epoll时需要实现这里
todo!()
}
@ -704,6 +704,48 @@ impl EventPoll {
pub fn ep_wake_one(&self) {
self.epoll_wq.wakeup(None);
}
/// ### epoll的回调支持epoll的文件有事件到来时直接调用该方法即可
pub fn wakeup_epoll(
epitems: &mut SpinLock<LinkedList<Arc<EPollItem>>>,
pollflags: EPollEventType,
) -> Result<(), SystemError> {
let mut epitems_guard = epitems.try_lock_irqsave()?;
// 一次只取一个,因为一次也只有一个进程能拿到对应文件的🔓
if let Some(epitem) = epitems_guard.pop_front() {
let epoll = epitem.epoll().upgrade().unwrap();
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(())
}
}
/// 与C兼容的Epoll事件结构体

View File

@ -231,11 +231,13 @@ pub trait Socket: Sync + Send + Debug {
for epitem in handle_item.epitems.lock_irqsave().iter() {
let epoll = epitem.epoll();
let _ = EventPoll::ep_remove(
&mut epoll.upgrade().unwrap().lock_irqsave(),
epitem.fd(),
None,
);
if epoll.upgrade().is_some() {
let _ = EventPoll::ep_remove(
&mut epoll.upgrade().unwrap().lock_irqsave(),
epitem.fd(),
None,
);
}
}
Ok(())

View File

@ -1,5 +1,5 @@
use alloc::{boxed::Box, collections::BTreeMap, sync::Arc};
use smoltcp::{iface::SocketHandle, socket::dhcpv4, wire};
use smoltcp::{socket::dhcpv4, wire};
use system_error::SystemError;
use crate::{
@ -11,7 +11,7 @@ use crate::{
};
use super::{
event_poll::EPollEventType,
event_poll::{EPollEventType, EventPoll},
socket::{TcpSocket, HANDLE_MAP, SOCKET_SET},
};
@ -228,7 +228,12 @@ fn send_event(sockets: &smoltcp::iface::SocketSet) -> Result<(), SystemError> {
smoltcp::socket::Socket::Dns(_) => unimplemented!("Dns socket hasn't unimplemented"),
}
drop(handle_guard);
wakeup_epoll(handle, events as u32)?;
let mut handle_guard = HANDLE_MAP.write_irqsave();
let handle_item = handle_guard.get_mut(&handle).unwrap();
EventPoll::wakeup_epoll(
&mut handle_item.epitems,
EPollEventType::from_bits_truncate(events as u32),
)?;
// crate::kdebug!(
// "{} send_event {:?}",
// handle,
@ -237,48 +242,3 @@ fn send_event(sockets: &smoltcp::iface::SocketSet) -> Result<(), SystemError> {
}
Ok(())
}
/// ### 处理epoll
fn wakeup_epoll(handle: SocketHandle, events: u32) -> Result<(), SystemError> {
let mut handle_guard = HANDLE_MAP.write_irqsave();
let handle_item = handle_guard.get_mut(&handle).unwrap();
let mut epitems_guard = handle_item.epitems.try_lock_irqsave()?;
// 从events拿到epoll相关事件
let pollflags = EPollEventType::from_bits_truncate(events);
// 一次只取一个,因为一次也只有一个进程能拿到对应文件的🔓
if let Some(epitem) = epitems_guard.pop_front() {
let epoll = epitem.epoll().upgrade().unwrap();
let mut epoll_guard = epoll.try_lock_irqsave()?;
let binding = epitem.clone();
let event_guard = binding.event().read_irqsave();
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(())
}

View File

@ -20,7 +20,7 @@ use system_error::SystemError;
use crate::{
arch::{rand::rand, sched::sched},
driver::net::NetDriver,
filesystem::vfs::{syscall::ModeType, FileType, IndexNode, Metadata},
filesystem::vfs::{syscall::ModeType, FilePrivateData, FileType, IndexNode, Metadata},
kerror, kwarn,
libs::{
rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
@ -1351,7 +1351,7 @@ impl IndexNode for SocketInode {
return self.0.lock_no_preempt().write(&buf[0..len], None);
}
fn poll(&self) -> Result<usize, SystemError> {
fn poll(&self, _private_data: &FilePrivateData) -> Result<usize, SystemError> {
let events = self.0.lock_irqsave().poll();
return Ok(events.bits() as usize);
}