mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 06:05:04 +00:00
refactor(epoll): epoll syscall refactor (#1180)
* feat(epoll): Move epoll functionality into filesystem module Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com> * refactor(epoll): refactor epoll syscall Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com> * feat(epoll): move do_epoll_wait into epoll_utils Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com> * fmt Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com> --------- Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>
This commit is contained in:
parent
e9d82983e1
commit
a951a88bee
@ -10,6 +10,7 @@ use crate::{
|
||||
},
|
||||
filesystem::{
|
||||
devpts::DevPtsFs,
|
||||
epoll::EPollEventType,
|
||||
vfs::{
|
||||
file::FileMode, syscall::ModeType, FilePrivateData, FileType, MountFS, ROOT_INODE,
|
||||
VFS_MAX_FOLLOW_SYMLINK_TIMES,
|
||||
@ -17,7 +18,6 @@ use crate::{
|
||||
},
|
||||
libs::spinlock::SpinLockGuard,
|
||||
mm::VirtAddr,
|
||||
net::event_poll::EPollEventType,
|
||||
syscall::user_access::UserBufferWriter,
|
||||
};
|
||||
|
||||
|
@ -12,13 +12,13 @@ use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
driver::{base::device::device_number::DeviceNumber, tty::pty::ptm_driver},
|
||||
filesystem::epoll::{EPollEventType, EPollItem},
|
||||
libs::{
|
||||
rwlock::{RwLock, RwLockReadGuard, RwLockUpgradableGuard, RwLockWriteGuard},
|
||||
spinlock::{SpinLock, SpinLockGuard},
|
||||
wait_queue::EventWaitQueue,
|
||||
},
|
||||
mm::VirtAddr,
|
||||
net::event_poll::{EPollEventType, EPollItem},
|
||||
process::{process_group::Pgid, session::Sid, ProcessControlBlock},
|
||||
syscall::user_access::{UserBufferReader, UserBufferWriter},
|
||||
};
|
||||
|
@ -25,6 +25,7 @@ use crate::{
|
||||
},
|
||||
filesystem::{
|
||||
devfs::{devfs_register, DevFS, DeviceINode},
|
||||
epoll::EPollItem,
|
||||
kernfs::KernFSInode,
|
||||
vfs::{
|
||||
file::FileMode, syscall::ModeType, FilePrivateData, FileType, IndexNode, Metadata,
|
||||
@ -37,7 +38,6 @@ use crate::{
|
||||
spinlock::SpinLockGuard,
|
||||
},
|
||||
mm::VirtAddr,
|
||||
net::event_poll::EPollItem,
|
||||
process::ProcessManager,
|
||||
syscall::user_access::{UserBufferReader, UserBufferWriter},
|
||||
};
|
||||
|
@ -15,13 +15,12 @@ use crate::{
|
||||
tty_driver::{TtyDriverFlag, TtyOperation},
|
||||
tty_job_control::TtyJobCtrlManager,
|
||||
},
|
||||
filesystem::vfs::file::FileMode,
|
||||
filesystem::{epoll::EPollEventType, vfs::file::FileMode},
|
||||
libs::{
|
||||
rwlock::RwLockReadGuard,
|
||||
spinlock::{SpinLock, SpinLockGuard},
|
||||
},
|
||||
mm::VirtAddr,
|
||||
net::event_poll::EPollEventType,
|
||||
process::{ProcessFlags, ProcessManager},
|
||||
syscall::{user_access::UserBufferWriter, Syscall},
|
||||
};
|
||||
|
@ -5,8 +5,8 @@ use kdepends::thingbuf::mpsc;
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
filesystem::epoll::{event_poll::EventPoll, EPollEventType},
|
||||
libs::spinlock::{SpinLock, SpinLockGuard},
|
||||
net::event_poll::{EPollEventType, EventPoll},
|
||||
};
|
||||
|
||||
use super::tty_core::TtyCore;
|
||||
|
@ -3,21 +3,13 @@ use core::{
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
|
||||
use alloc::{
|
||||
collections::LinkedList,
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
};
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
filesystem::vfs::{
|
||||
file::{File, FileMode},
|
||||
FilePrivateData, IndexNode, Metadata,
|
||||
FilePrivateData,
|
||||
},
|
||||
libs::{
|
||||
rbtree::RBTree,
|
||||
rwlock::RwLock,
|
||||
spinlock::{SpinLock, SpinLockGuard},
|
||||
wait_queue::WaitQueue,
|
||||
},
|
||||
@ -29,10 +21,14 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
pub mod syscall;
|
||||
use alloc::{
|
||||
collections::LinkedList,
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
};
|
||||
use system_error::SystemError;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LockedEventPoll(Arc<SpinLock<EventPoll>>);
|
||||
use super::{fs::EPollInode, EPollCtlOption, EPollEvent, EPollEventType, EPollItem};
|
||||
|
||||
/// 内核的Epoll对象结构体,当用户创建一个Epoll时,内核就会创建一个该类型对象
|
||||
/// 它对应一个epfd
|
||||
@ -49,138 +45,6 @@ pub struct EventPoll {
|
||||
self_ref: Option<Weak<SpinLock<EventPoll>>>,
|
||||
}
|
||||
|
||||
/// EpollItem表示的是Epoll所真正管理的对象
|
||||
/// 每当用户向Epoll添加描述符时都会注册一个新的EpollItem,EpollItem携带了一些被监听的描述符的必要信息
|
||||
#[derive(Debug)]
|
||||
pub struct EPollItem {
|
||||
/// 对应的Epoll
|
||||
epoll: Weak<SpinLock<EventPoll>>,
|
||||
/// 用户注册的事件
|
||||
event: RwLock<EPollEvent>,
|
||||
/// 监听的描述符
|
||||
fd: i32,
|
||||
/// 对应的文件
|
||||
file: Weak<File>,
|
||||
}
|
||||
|
||||
impl EPollItem {
|
||||
pub fn new(
|
||||
epoll: Weak<SpinLock<EventPoll>>,
|
||||
events: EPollEvent,
|
||||
fd: i32,
|
||||
file: Weak<File>,
|
||||
) -> Self {
|
||||
Self {
|
||||
epoll,
|
||||
event: RwLock::new(events),
|
||||
fd,
|
||||
file,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn epoll(&self) -> Weak<SpinLock<EventPoll>> {
|
||||
self.epoll.clone()
|
||||
}
|
||||
|
||||
pub fn event(&self) -> &RwLock<EPollEvent> {
|
||||
&self.event
|
||||
}
|
||||
|
||||
pub fn file(&self) -> Weak<File> {
|
||||
self.file.clone()
|
||||
}
|
||||
|
||||
pub fn fd(&self) -> i32 {
|
||||
self.fd
|
||||
}
|
||||
|
||||
/// ## 通过epoll_item来执行绑定文件的poll方法,并获取到感兴趣的事件
|
||||
fn ep_item_poll(&self) -> EPollEventType {
|
||||
let file = self.file.upgrade();
|
||||
if file.is_none() {
|
||||
return EPollEventType::empty();
|
||||
}
|
||||
if let Ok(events) = file.unwrap().poll() {
|
||||
let events = events as u32 & self.event.read().events;
|
||||
return EPollEventType::from_bits_truncate(events);
|
||||
}
|
||||
return EPollEventType::empty();
|
||||
}
|
||||
}
|
||||
|
||||
/// ### Epoll文件的私有信息
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EPollPrivateData {
|
||||
epoll: LockedEventPoll,
|
||||
}
|
||||
|
||||
/// ### 该结构体将Epoll加入文件系统
|
||||
#[derive(Debug)]
|
||||
pub struct EPollInode {
|
||||
epoll: LockedEventPoll,
|
||||
}
|
||||
|
||||
impl EPollInode {
|
||||
pub fn new(epoll: LockedEventPoll) -> Arc<Self> {
|
||||
Arc::new(Self { epoll })
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexNode for EPollInode {
|
||||
fn read_at(
|
||||
&self,
|
||||
_offset: usize,
|
||||
_len: usize,
|
||||
_buf: &mut [u8],
|
||||
_data: SpinLockGuard<FilePrivateData>,
|
||||
) -> Result<usize, SystemError> {
|
||||
Err(SystemError::ENOSYS)
|
||||
}
|
||||
|
||||
fn write_at(
|
||||
&self,
|
||||
_offset: usize,
|
||||
_len: usize,
|
||||
_buf: &[u8],
|
||||
_data: SpinLockGuard<FilePrivateData>,
|
||||
) -> Result<usize, SystemError> {
|
||||
Err(SystemError::ENOSYS)
|
||||
}
|
||||
|
||||
fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn as_any_ref(&self) -> &dyn core::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn list(&self) -> Result<Vec<alloc::string::String>, SystemError> {
|
||||
Err(SystemError::ENOSYS)
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, SystemError> {
|
||||
Ok(Metadata::default())
|
||||
}
|
||||
|
||||
fn close(&self, _data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> {
|
||||
// 释放资源
|
||||
let mut epoll = self.epoll.0.lock_irqsave();
|
||||
|
||||
epoll.close()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn open(
|
||||
&self,
|
||||
_data: SpinLockGuard<FilePrivateData>,
|
||||
_mode: &FileMode,
|
||||
) -> Result<(), SystemError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl EventPoll {
|
||||
pub const EP_MAX_EVENTS: u32 = u32::MAX / (core::mem::size_of::<EPollEvent>() as u32);
|
||||
/// 用于获取inode中的epitem队列
|
||||
@ -196,7 +60,7 @@ impl EventPoll {
|
||||
}
|
||||
|
||||
/// 关闭epoll时,执行的逻辑
|
||||
fn close(&mut self) -> Result<(), SystemError> {
|
||||
pub(super) fn close(&mut self) -> Result<(), SystemError> {
|
||||
// 唤醒epoll上面等待的所有进程
|
||||
self.shutdown.store(true, Ordering::SeqCst);
|
||||
self.ep_wake_all();
|
||||
@ -812,131 +676,11 @@ impl EventPoll {
|
||||
}
|
||||
}
|
||||
|
||||
/// 与C兼容的Epoll事件结构体
|
||||
#[derive(Copy, Clone, Default)]
|
||||
#[repr(packed)]
|
||||
#[repr(C)]
|
||||
pub struct EPollEvent {
|
||||
/// 表示触发的事件
|
||||
events: u32,
|
||||
/// 内核态不使用该字段,该字段由用户态自由使用,在事件发生时内核将会原样返回
|
||||
data: u64,
|
||||
}
|
||||
|
||||
impl Debug for EPollEvent {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let events = self.events;
|
||||
let u64 = self.data;
|
||||
f.debug_struct("epoll_event")
|
||||
.field("events", &events)
|
||||
.field("data", &u64)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl EPollEvent {
|
||||
pub fn set_events(&mut self, events: u32) {
|
||||
self.events = events;
|
||||
}
|
||||
|
||||
pub fn events(&self) -> u32 {
|
||||
self.events
|
||||
}
|
||||
|
||||
pub fn set_data(&mut self, data: u64) {
|
||||
self.data = data;
|
||||
}
|
||||
|
||||
pub fn data(&self) -> u64 {
|
||||
self.data
|
||||
}
|
||||
}
|
||||
|
||||
/// ## epoll_ctl函数的参数
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum EPollCtlOption {
|
||||
/// 注册新的文件描述符到epfd
|
||||
Add,
|
||||
/// 将对应的文件描述符从epfd中删除
|
||||
Del,
|
||||
/// 修改已经注册的文件描述符的监听事件
|
||||
Mod,
|
||||
}
|
||||
|
||||
impl EPollCtlOption {
|
||||
pub fn from_op_num(op: usize) -> Result<Self, SystemError> {
|
||||
match op {
|
||||
1 => Ok(Self::Add),
|
||||
2 => Ok(Self::Del),
|
||||
3 => Ok(Self::Mod),
|
||||
_ => Err(SystemError::EINVAL),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[allow(dead_code)]
|
||||
pub struct EPollEventType: u32 {
|
||||
/// 对应的描述符有新的数据可读时会触发
|
||||
const EPOLLIN = 0x00000001;
|
||||
/// 对应的描述符有紧急数据可读时会触发
|
||||
const EPOLLPRI = 0x00000002;
|
||||
/// 对应的描述符可以写入数据时会触发
|
||||
const EPOLLOUT = 0x00000004;
|
||||
/// 对应的描述符发生错误时会触发
|
||||
const EPOLLERR = 0x00000008;
|
||||
/// 对应的描述符被挂断(连接关闭)时会触发
|
||||
const EPOLLHUP = 0x00000010;
|
||||
/// 对应的描述符不是一个有效的文件描述符时会触发
|
||||
const EPOLLNVAL = 0x00000020;
|
||||
/// 普通数据可读,类似于`EPOLLIN`
|
||||
const EPOLLRDNORM = 0x00000040;
|
||||
/// 优先级带外数据可读
|
||||
const EPOLLRDBAND = 0x00000080;
|
||||
/// 普通数据可写,类似于'EPOLLOUT'
|
||||
const EPOLLWRNORM = 0x00000100;
|
||||
/// 优先级带外数据可写
|
||||
const EPOLLWRBAND = 0x00000200;
|
||||
/// 通过消息队列收到消息时会触
|
||||
const EPOLLMSG = 0x00000400;
|
||||
/// 对应的描述符被挂断(连接关闭)的一端发送了 FIN 时会触发(读关闭)
|
||||
const EPOLLRDHUP = 0x00002000;
|
||||
|
||||
/// 以下为额外选项
|
||||
///
|
||||
/// 特定选项,用于异步 I/O,目前未实现
|
||||
const EPOLL_URING_WAKE = 1u32 << 27;
|
||||
/// 设置epoll为独占模式
|
||||
const EPOLLEXCLUSIVE = 1u32 << 28;
|
||||
/// 允许在系统挂起时唤醒 epoll,通常用于通过 eventfd 或 timerfd 唤醒 epoll,(通常与电源管理相关,未实现)
|
||||
const EPOLLWAKEUP = 1u32 << 29;
|
||||
/// 表示只监听一次事件,之后需要重新添加
|
||||
const EPOLLONESHOT = 1u32 << 30;
|
||||
|
||||
/// 启用边缘触发模式(即只有下次触发事件时才会通过epoll_wait返回),
|
||||
/// 对应为水平触发(默认),水平触发模式下若这次未处理完数据,那epoll还会将其加入自己的就绪队列
|
||||
const EPOLLET = 1u32 << 31;
|
||||
|
||||
/// 以下为组合码
|
||||
const EPOLLINOUT_BITS = Self::EPOLLIN.bits | Self::EPOLLOUT.bits;
|
||||
const EPOLLEXCLUSIVE_OK_BITS =
|
||||
Self::EPOLLINOUT_BITS.bits
|
||||
| Self::EPOLLERR.bits
|
||||
| Self::EPOLLHUP.bits
|
||||
| Self::EPOLLWAKEUP.bits
|
||||
| Self::EPOLLET.bits
|
||||
| Self::EPOLLEXCLUSIVE.bits;
|
||||
|
||||
const EP_PRIVATE_BITS =
|
||||
Self::EPOLLWAKEUP.bits
|
||||
| Self::EPOLLONESHOT.bits
|
||||
| Self::EPOLLET.bits
|
||||
| Self::EPOLLEXCLUSIVE.bits;
|
||||
|
||||
/// 表示epoll已经被释放,但是在目前的设计中未用到
|
||||
const POLLFREE = 0x4000;
|
||||
|
||||
/// listen状态的socket可以接受连接
|
||||
const EPOLL_LISTEN_CAN_ACCEPT = Self::EPOLLIN.bits | Self::EPOLLRDNORM.bits;
|
||||
}
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LockedEventPoll(pub(super) Arc<SpinLock<EventPoll>>);
|
||||
|
||||
/// ### Epoll文件的私有信息
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EPollPrivateData {
|
||||
pub(super) epoll: LockedEventPoll,
|
||||
}
|
77
kernel/src/filesystem/epoll/fs.rs
Normal file
77
kernel/src/filesystem/epoll/fs.rs
Normal file
@ -0,0 +1,77 @@
|
||||
use crate::{
|
||||
filesystem::vfs::{file::FileMode, FilePrivateData, IndexNode, Metadata},
|
||||
libs::spinlock::SpinLockGuard,
|
||||
};
|
||||
|
||||
use alloc::sync::Arc;
|
||||
use alloc::vec::Vec;
|
||||
use system_error::SystemError;
|
||||
|
||||
use super::event_poll::LockedEventPoll;
|
||||
|
||||
/// ### 该结构体将Epoll加入文件系统
|
||||
#[derive(Debug)]
|
||||
pub struct EPollInode {
|
||||
pub epoll: LockedEventPoll,
|
||||
}
|
||||
|
||||
impl EPollInode {
|
||||
pub fn new(epoll: LockedEventPoll) -> Arc<Self> {
|
||||
Arc::new(Self { epoll })
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexNode for EPollInode {
|
||||
fn read_at(
|
||||
&self,
|
||||
_offset: usize,
|
||||
_len: usize,
|
||||
_buf: &mut [u8],
|
||||
_data: SpinLockGuard<FilePrivateData>,
|
||||
) -> Result<usize, SystemError> {
|
||||
Err(SystemError::ENOSYS)
|
||||
}
|
||||
|
||||
fn write_at(
|
||||
&self,
|
||||
_offset: usize,
|
||||
_len: usize,
|
||||
_buf: &[u8],
|
||||
_data: SpinLockGuard<FilePrivateData>,
|
||||
) -> Result<usize, SystemError> {
|
||||
Err(SystemError::ENOSYS)
|
||||
}
|
||||
|
||||
fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn as_any_ref(&self) -> &dyn core::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn list(&self) -> Result<Vec<alloc::string::String>, SystemError> {
|
||||
Err(SystemError::ENOSYS)
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Result<Metadata, SystemError> {
|
||||
Ok(Metadata::default())
|
||||
}
|
||||
|
||||
fn close(&self, _data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> {
|
||||
// 释放资源
|
||||
let mut epoll = self.epoll.0.lock_irqsave();
|
||||
|
||||
epoll.close()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn open(
|
||||
&self,
|
||||
_data: SpinLockGuard<FilePrivateData>,
|
||||
_mode: &FileMode,
|
||||
) -> Result<(), SystemError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
197
kernel/src/filesystem/epoll/mod.rs
Normal file
197
kernel/src/filesystem/epoll/mod.rs
Normal file
@ -0,0 +1,197 @@
|
||||
use super::vfs::file::File;
|
||||
use crate::libs::{rwlock::RwLock, spinlock::SpinLock};
|
||||
use alloc::sync::Weak;
|
||||
use core::fmt::Debug;
|
||||
use event_poll::EventPoll;
|
||||
use system_error::SystemError;
|
||||
|
||||
pub mod event_poll;
|
||||
pub mod fs;
|
||||
|
||||
/// 与C兼容的Epoll事件结构体
|
||||
#[derive(Copy, Clone, Default)]
|
||||
#[repr(packed)]
|
||||
#[repr(C)]
|
||||
pub struct EPollEvent {
|
||||
/// 表示触发的事件
|
||||
events: u32,
|
||||
/// 内核态不使用该字段,该字段由用户态自由使用,在事件发生时内核将会原样返回
|
||||
data: u64,
|
||||
}
|
||||
|
||||
impl Debug for EPollEvent {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let events = self.events;
|
||||
let u64 = self.data;
|
||||
f.debug_struct("epoll_event")
|
||||
.field("events", &events)
|
||||
.field("data", &u64)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl EPollEvent {
|
||||
pub fn set_events(&mut self, events: u32) {
|
||||
self.events = events;
|
||||
}
|
||||
|
||||
pub fn events(&self) -> u32 {
|
||||
self.events
|
||||
}
|
||||
|
||||
pub fn set_data(&mut self, data: u64) {
|
||||
self.data = data;
|
||||
}
|
||||
|
||||
pub fn data(&self) -> u64 {
|
||||
self.data
|
||||
}
|
||||
}
|
||||
|
||||
/// EpollItem表示的是Epoll所真正管理的对象
|
||||
/// 每当用户向Epoll添加描述符时都会注册一个新的EpollItem,EpollItem携带了一些被监听的描述符的必要信息
|
||||
#[derive(Debug)]
|
||||
pub struct EPollItem {
|
||||
/// 对应的Epoll
|
||||
epoll: Weak<SpinLock<EventPoll>>,
|
||||
/// 用户注册的事件
|
||||
event: RwLock<EPollEvent>,
|
||||
/// 监听的描述符
|
||||
fd: i32,
|
||||
/// 对应的文件
|
||||
file: Weak<File>,
|
||||
}
|
||||
|
||||
impl EPollItem {
|
||||
pub fn new(
|
||||
epoll: Weak<SpinLock<EventPoll>>,
|
||||
events: EPollEvent,
|
||||
fd: i32,
|
||||
file: Weak<File>,
|
||||
) -> Self {
|
||||
Self {
|
||||
epoll,
|
||||
event: RwLock::new(events),
|
||||
fd,
|
||||
file,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn epoll(&self) -> Weak<SpinLock<EventPoll>> {
|
||||
self.epoll.clone()
|
||||
}
|
||||
|
||||
pub fn event(&self) -> &RwLock<EPollEvent> {
|
||||
&self.event
|
||||
}
|
||||
|
||||
pub fn file(&self) -> Weak<File> {
|
||||
self.file.clone()
|
||||
}
|
||||
|
||||
pub fn fd(&self) -> i32 {
|
||||
self.fd
|
||||
}
|
||||
|
||||
/// ## 通过epoll_item来执行绑定文件的poll方法,并获取到感兴趣的事件
|
||||
fn ep_item_poll(&self) -> EPollEventType {
|
||||
let file = self.file.upgrade();
|
||||
if file.is_none() {
|
||||
return EPollEventType::empty();
|
||||
}
|
||||
if let Ok(events) = file.unwrap().poll() {
|
||||
let events = events as u32 & self.event.read().events;
|
||||
return EPollEventType::from_bits_truncate(events);
|
||||
}
|
||||
return EPollEventType::empty();
|
||||
}
|
||||
}
|
||||
|
||||
/// ## epoll_ctl函数的参数
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum EPollCtlOption {
|
||||
/// 注册新的文件描述符到epfd
|
||||
Add,
|
||||
/// 将对应的文件描述符从epfd中删除
|
||||
Del,
|
||||
/// 修改已经注册的文件描述符的监听事件
|
||||
Mod,
|
||||
}
|
||||
|
||||
impl EPollCtlOption {
|
||||
pub fn from_op_num(op: usize) -> Result<Self, SystemError> {
|
||||
match op {
|
||||
1 => Ok(Self::Add),
|
||||
2 => Ok(Self::Del),
|
||||
3 => Ok(Self::Mod),
|
||||
_ => Err(SystemError::EINVAL),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[allow(dead_code)]
|
||||
pub struct EPollEventType: u32 {
|
||||
/// 对应的描述符有新的数据可读时会触发
|
||||
const EPOLLIN = 0x00000001;
|
||||
/// 对应的描述符有紧急数据可读时会触发
|
||||
const EPOLLPRI = 0x00000002;
|
||||
/// 对应的描述符可以写入数据时会触发
|
||||
const EPOLLOUT = 0x00000004;
|
||||
/// 对应的描述符发生错误时会触发
|
||||
const EPOLLERR = 0x00000008;
|
||||
/// 对应的描述符被挂断(连接关闭)时会触发
|
||||
const EPOLLHUP = 0x00000010;
|
||||
/// 对应的描述符不是一个有效的文件描述符时会触发
|
||||
const EPOLLNVAL = 0x00000020;
|
||||
/// 普通数据可读,类似于`EPOLLIN`
|
||||
const EPOLLRDNORM = 0x00000040;
|
||||
/// 优先级带外数据可读
|
||||
const EPOLLRDBAND = 0x00000080;
|
||||
/// 普通数据可写,类似于'EPOLLOUT'
|
||||
const EPOLLWRNORM = 0x00000100;
|
||||
/// 优先级带外数据可写
|
||||
const EPOLLWRBAND = 0x00000200;
|
||||
/// 通过消息队列收到消息时会触
|
||||
const EPOLLMSG = 0x00000400;
|
||||
/// 对应的描述符被挂断(连接关闭)的一端发送了 FIN 时会触发(读关闭)
|
||||
const EPOLLRDHUP = 0x00002000;
|
||||
|
||||
/// 以下为额外选项
|
||||
///
|
||||
/// 特定选项,用于异步 I/O,目前未实现
|
||||
const EPOLL_URING_WAKE = 1u32 << 27;
|
||||
/// 设置epoll为独占模式
|
||||
const EPOLLEXCLUSIVE = 1u32 << 28;
|
||||
/// 允许在系统挂起时唤醒 epoll,通常用于通过 eventfd 或 timerfd 唤醒 epoll,(通常与电源管理相关,未实现)
|
||||
const EPOLLWAKEUP = 1u32 << 29;
|
||||
/// 表示只监听一次事件,之后需要重新添加
|
||||
const EPOLLONESHOT = 1u32 << 30;
|
||||
|
||||
/// 启用边缘触发模式(即只有下次触发事件时才会通过epoll_wait返回),
|
||||
/// 对应为水平触发(默认),水平触发模式下若这次未处理完数据,那epoll还会将其加入自己的就绪队列
|
||||
const EPOLLET = 1u32 << 31;
|
||||
|
||||
/// 以下为组合码
|
||||
const EPOLLINOUT_BITS = Self::EPOLLIN.bits | Self::EPOLLOUT.bits;
|
||||
const EPOLLEXCLUSIVE_OK_BITS =
|
||||
Self::EPOLLINOUT_BITS.bits
|
||||
| Self::EPOLLERR.bits
|
||||
| Self::EPOLLHUP.bits
|
||||
| Self::EPOLLWAKEUP.bits
|
||||
| Self::EPOLLET.bits
|
||||
| Self::EPOLLEXCLUSIVE.bits;
|
||||
|
||||
const EP_PRIVATE_BITS =
|
||||
Self::EPOLLWAKEUP.bits
|
||||
| Self::EPOLLONESHOT.bits
|
||||
| Self::EPOLLET.bits
|
||||
| Self::EPOLLEXCLUSIVE.bits;
|
||||
|
||||
/// 表示epoll已经被释放,但是在目前的设计中未用到
|
||||
const POLLFREE = 0x4000;
|
||||
|
||||
/// listen状态的socket可以接受连接
|
||||
const EPOLL_LISTEN_CAN_ACCEPT = Self::EPOLLIN.bits | Self::EPOLLRDNORM.bits;
|
||||
}
|
||||
}
|
@ -1,10 +1,12 @@
|
||||
use super::vfs::PollableInode;
|
||||
use crate::filesystem::vfs::file::{File, FileMode};
|
||||
use crate::filesystem::vfs::syscall::ModeType;
|
||||
use crate::filesystem::vfs::{FilePrivateData, FileSystem, FileType, IndexNode, Metadata};
|
||||
use crate::filesystem::{
|
||||
epoll::{event_poll::EventPoll, EPollEventType, EPollItem},
|
||||
vfs::{FilePrivateData, FileSystem, FileType, IndexNode, Metadata},
|
||||
};
|
||||
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
|
||||
use crate::libs::wait_queue::WaitQueue;
|
||||
use crate::net::event_poll::{EPollEventType, EPollItem, EventPoll};
|
||||
use crate::process::{ProcessFlags, ProcessManager};
|
||||
use crate::sched::SchedMode;
|
||||
use crate::syscall::Syscall;
|
||||
|
@ -1,5 +1,6 @@
|
||||
pub mod devfs;
|
||||
pub mod devpts;
|
||||
pub mod epoll;
|
||||
pub mod eventfd;
|
||||
pub mod fat;
|
||||
pub mod kernfs;
|
||||
|
@ -2,11 +2,11 @@ use core::ffi::c_int;
|
||||
|
||||
use crate::{
|
||||
arch::ipc::signal::SigSet,
|
||||
filesystem::epoll::{event_poll::EventPoll, EPollCtlOption, EPollEvent, EPollEventType},
|
||||
ipc::signal::{
|
||||
restore_saved_sigmask_unless, set_user_sigmask, RestartBlock, RestartBlockData, RestartFn,
|
||||
},
|
||||
mm::VirtAddr,
|
||||
net::event_poll::{EPollCtlOption, EPollEvent, EPollEventType, EventPoll},
|
||||
process::ProcessManager,
|
||||
syscall::{
|
||||
user_access::{UserBufferReader, UserBufferWriter},
|
||||
|
@ -10,10 +10,12 @@ use crate::{
|
||||
base::{block::SeekFrom, device::DevicePrivateData},
|
||||
tty::tty_device::TtyFilePrivateData,
|
||||
},
|
||||
filesystem::procfs::ProcfsFilePrivateData,
|
||||
filesystem::{
|
||||
epoll::{event_poll::EPollPrivateData, EPollItem},
|
||||
procfs::ProcfsFilePrivateData,
|
||||
},
|
||||
ipc::pipe::PipeFsPrivateData,
|
||||
libs::{rwlock::RwLock, spinlock::SpinLock},
|
||||
net::event_poll::{EPollItem, EPollPrivateData},
|
||||
process::{cred::Cred, ProcessManager},
|
||||
};
|
||||
|
||||
|
@ -18,13 +18,13 @@ use crate::{
|
||||
driver::base::{
|
||||
block::block_device::BlockDevice, char::CharDevice, device::device_number::DeviceNumber,
|
||||
},
|
||||
filesystem::epoll::EPollItem,
|
||||
ipc::pipe::LockedPipeInode,
|
||||
libs::{
|
||||
casting::DowncastArc,
|
||||
spinlock::{SpinLock, SpinLockGuard},
|
||||
},
|
||||
mm::{fault::PageFaultMessage, VmFaultReason},
|
||||
net::event_poll::EPollItem,
|
||||
time::PosixTimeSpec,
|
||||
};
|
||||
|
||||
|
49
kernel/src/filesystem/vfs/syscall/epoll_utils.rs
Normal file
49
kernel/src/filesystem/vfs/syscall/epoll_utils.rs
Normal file
@ -0,0 +1,49 @@
|
||||
use crate::filesystem::epoll::event_poll::EventPoll;
|
||||
use crate::filesystem::epoll::EPollEvent;
|
||||
use crate::mm::VirtAddr;
|
||||
use crate::syscall::user_access::UserBufferWriter;
|
||||
use crate::time::PosixTimeSpec;
|
||||
use system_error::SystemError;
|
||||
|
||||
/// System call handler for epoll_wait.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `epfd` - File descriptor of the epoll instance
|
||||
/// * `events` - User space address to store the events
|
||||
/// * `max_events` - Maximum number of events to return
|
||||
/// * `timeout` - Timeout in milliseconds, 0 for no wait, negative for infinite wait
|
||||
///
|
||||
/// # Returns
|
||||
/// Returns the number of events ready or an error if the operation fails.
|
||||
pub(super) fn do_epoll_wait(
|
||||
epfd: i32,
|
||||
events: VirtAddr,
|
||||
max_events: i32,
|
||||
timeout: i32,
|
||||
) -> Result<usize, SystemError> {
|
||||
if max_events <= 0 || max_events as u32 > EventPoll::EP_MAX_EVENTS {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
|
||||
let mut timespec = None;
|
||||
if timeout == 0 {
|
||||
timespec = Some(PosixTimeSpec::new(0, 0));
|
||||
}
|
||||
|
||||
if timeout > 0 {
|
||||
let sec: i64 = timeout as i64 / 1000;
|
||||
let nsec: i64 = 1000000 * (timeout as i64 % 1000);
|
||||
|
||||
timespec = Some(PosixTimeSpec::new(sec, nsec))
|
||||
}
|
||||
|
||||
// 从用户传入的地址中拿到epoll_events
|
||||
let mut epds_writer = UserBufferWriter::new(
|
||||
events.as_ptr::<EPollEvent>(),
|
||||
max_events as usize * core::mem::size_of::<EPollEvent>(),
|
||||
true,
|
||||
)?;
|
||||
|
||||
let epoll_events = epds_writer.buffer::<EPollEvent>(0)?;
|
||||
return EventPoll::epoll_wait(epfd, epoll_events, max_events, timespec);
|
||||
}
|
@ -52,6 +52,15 @@ mod sys_stat;
|
||||
mod sys_write;
|
||||
mod sys_writev;
|
||||
|
||||
mod epoll_utils;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod sys_epoll_create;
|
||||
mod sys_epoll_create1;
|
||||
mod sys_epoll_ctl;
|
||||
mod sys_epoll_pwait;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod sys_epoll_wait;
|
||||
|
||||
pub const SEEK_SET: u32 = 0;
|
||||
pub const SEEK_CUR: u32 = 1;
|
||||
pub const SEEK_END: u32 = 2;
|
||||
|
41
kernel/src/filesystem/vfs/syscall/sys_epoll_create.rs
Normal file
41
kernel/src/filesystem/vfs/syscall/sys_epoll_create.rs
Normal file
@ -0,0 +1,41 @@
|
||||
//! System call handler for epoll creation.
|
||||
|
||||
use crate::arch::syscall::nr::SYS_EPOLL_CREATE;
|
||||
use crate::filesystem::epoll::event_poll::EventPoll;
|
||||
use crate::filesystem::vfs::file::FileMode;
|
||||
use crate::syscall::table::FormattedSyscallParam;
|
||||
use crate::syscall::table::Syscall;
|
||||
use alloc::vec::Vec;
|
||||
use system_error::SystemError;
|
||||
|
||||
pub struct SysEpollCreateHandle;
|
||||
|
||||
impl Syscall for SysEpollCreateHandle {
|
||||
fn num_args(&self) -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
fn handle(&self, args: &[usize], _from_user: bool) -> Result<usize, SystemError> {
|
||||
let max_size = Self::max_size(args);
|
||||
if max_size < 0 {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
|
||||
return EventPoll::create_epoll(FileMode::empty());
|
||||
}
|
||||
|
||||
fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
|
||||
vec![FormattedSyscallParam::new(
|
||||
"max_size",
|
||||
format!("{:#x}", Self::max_size(args) as usize),
|
||||
)]
|
||||
}
|
||||
}
|
||||
|
||||
impl SysEpollCreateHandle {
|
||||
fn max_size(args: &[usize]) -> i32 {
|
||||
args[0] as i32
|
||||
}
|
||||
}
|
||||
|
||||
syscall_table_macros::declare_syscall!(SYS_EPOLL_CREATE, SysEpollCreateHandle);
|
36
kernel/src/filesystem/vfs/syscall/sys_epoll_create1.rs
Normal file
36
kernel/src/filesystem/vfs/syscall/sys_epoll_create1.rs
Normal file
@ -0,0 +1,36 @@
|
||||
//! System call handler for epoll_create1.
|
||||
|
||||
use crate::arch::syscall::nr::SYS_EPOLL_CREATE1;
|
||||
use crate::filesystem::epoll::event_poll::EventPoll;
|
||||
use crate::filesystem::vfs::file::FileMode;
|
||||
use crate::syscall::table::FormattedSyscallParam;
|
||||
use crate::syscall::table::Syscall;
|
||||
use alloc::vec::Vec;
|
||||
use system_error::SystemError;
|
||||
|
||||
pub struct SysEpollCreate1Handle;
|
||||
|
||||
impl Syscall for SysEpollCreate1Handle {
|
||||
fn num_args(&self) -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
fn handle(&self, args: &[usize], _from_user: bool) -> Result<usize, SystemError> {
|
||||
return EventPoll::create_epoll(Self::flags(args));
|
||||
}
|
||||
|
||||
fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
|
||||
vec![FormattedSyscallParam::new(
|
||||
"flags",
|
||||
format!("{:#x}", Self::flags(args)),
|
||||
)]
|
||||
}
|
||||
}
|
||||
|
||||
impl SysEpollCreate1Handle {
|
||||
fn flags(args: &[usize]) -> FileMode {
|
||||
FileMode::from_bits_truncate(args[0] as u32)
|
||||
}
|
||||
}
|
||||
|
||||
syscall_table_macros::declare_syscall!(SYS_EPOLL_CREATE1, SysEpollCreate1Handle);
|
74
kernel/src/filesystem/vfs/syscall/sys_epoll_ctl.rs
Normal file
74
kernel/src/filesystem/vfs/syscall/sys_epoll_ctl.rs
Normal file
@ -0,0 +1,74 @@
|
||||
//! System call handler for epoll_ctl.
|
||||
|
||||
use crate::arch::syscall::nr::SYS_EPOLL_CTL;
|
||||
use crate::filesystem::epoll::event_poll::EventPoll;
|
||||
use crate::filesystem::epoll::EPollCtlOption;
|
||||
use crate::filesystem::epoll::EPollEvent;
|
||||
use crate::mm::VirtAddr;
|
||||
use crate::syscall::table::FormattedSyscallParam;
|
||||
use crate::syscall::table::Syscall;
|
||||
use crate::syscall::user_access::UserBufferReader;
|
||||
use alloc::vec::Vec;
|
||||
use system_error::SystemError;
|
||||
|
||||
pub struct SysEpollCtlHandle;
|
||||
|
||||
impl Syscall for SysEpollCtlHandle {
|
||||
fn num_args(&self) -> usize {
|
||||
4
|
||||
}
|
||||
|
||||
fn handle(&self, args: &[usize], _from_user: bool) -> Result<usize, SystemError> {
|
||||
let op = EPollCtlOption::from_op_num(Self::op(args))?;
|
||||
let mut epds = EPollEvent::default();
|
||||
let event = Self::event(args);
|
||||
let epfd = Self::epfd(args);
|
||||
let fd = Self::fd(args);
|
||||
|
||||
if op != EPollCtlOption::Del {
|
||||
// 不为EpollCtlDel时不允许传入空指针
|
||||
if event.is_null() {
|
||||
return Err(SystemError::EFAULT);
|
||||
}
|
||||
|
||||
// 还是一样的问题,C标准的epoll_event大小为12字节,而内核实现的epoll_event内存对齐后为16字节
|
||||
// 这样分别拷贝其实和整体拷贝差别不大,内核使用内存对其版本甚至可能提升性能
|
||||
let epds_reader = UserBufferReader::new(
|
||||
event.as_ptr::<EPollEvent>(),
|
||||
core::mem::size_of::<EPollEvent>(),
|
||||
true,
|
||||
)?;
|
||||
|
||||
// 拷贝到内核
|
||||
epds_reader.copy_one_from_user(&mut epds, 0)?;
|
||||
}
|
||||
|
||||
return EventPoll::epoll_ctl_with_epfd(epfd, op, fd, epds, false);
|
||||
}
|
||||
|
||||
fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
|
||||
vec![
|
||||
FormattedSyscallParam::new("epfd", format!("{:#x}", Self::epfd(args) as usize)),
|
||||
FormattedSyscallParam::new("op", format!("{:#x}", Self::op(args))),
|
||||
FormattedSyscallParam::new("fd", format!("{:#x}", Self::fd(args) as usize)),
|
||||
FormattedSyscallParam::new("event", format!("{:#x}", Self::event(args).data())),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl SysEpollCtlHandle {
|
||||
fn epfd(args: &[usize]) -> i32 {
|
||||
args[0] as i32
|
||||
}
|
||||
fn op(args: &[usize]) -> usize {
|
||||
args[1]
|
||||
}
|
||||
fn fd(args: &[usize]) -> i32 {
|
||||
args[2] as i32
|
||||
}
|
||||
fn event(args: &[usize]) -> VirtAddr {
|
||||
VirtAddr::new(args[3])
|
||||
}
|
||||
}
|
||||
|
||||
syscall_table_macros::declare_syscall!(SYS_EPOLL_CTL, SysEpollCtlHandle);
|
79
kernel/src/filesystem/vfs/syscall/sys_epoll_pwait.rs
Normal file
79
kernel/src/filesystem/vfs/syscall/sys_epoll_pwait.rs
Normal file
@ -0,0 +1,79 @@
|
||||
//! System call handler for epoll_pwait.
|
||||
|
||||
use crate::arch::ipc::signal::SigSet;
|
||||
use crate::arch::syscall::nr::SYS_EPOLL_PWAIT;
|
||||
use crate::ipc::signal::restore_saved_sigmask;
|
||||
use crate::ipc::signal::set_user_sigmask;
|
||||
use crate::mm::VirtAddr;
|
||||
use crate::syscall::table::FormattedSyscallParam;
|
||||
use crate::syscall::table::Syscall;
|
||||
use crate::syscall::user_access::UserBufferReader;
|
||||
use alloc::vec::Vec;
|
||||
use system_error::SystemError;
|
||||
|
||||
use super::epoll_utils::do_epoll_wait;
|
||||
|
||||
pub struct SysEpollPwaitHandle;
|
||||
|
||||
impl Syscall for SysEpollPwaitHandle {
|
||||
fn num_args(&self) -> usize {
|
||||
5
|
||||
}
|
||||
|
||||
fn handle(&self, args: &[usize], _from_user: bool) -> Result<usize, SystemError> {
|
||||
let epfd = Self::epfd(args);
|
||||
let epoll_event = Self::epoll_event(args);
|
||||
let max_events = Self::max_events(args);
|
||||
let timespec = Self::timespec(args);
|
||||
let sigmask_addr = Self::sigmask_addr(args);
|
||||
|
||||
if sigmask_addr.is_null() {
|
||||
return do_epoll_wait(epfd, epoll_event, max_events, timespec);
|
||||
}
|
||||
let sigmask_reader =
|
||||
UserBufferReader::new(sigmask_addr, core::mem::size_of::<SigSet>(), true)?;
|
||||
let mut sigmask = *sigmask_reader.read_one_from_user::<SigSet>(0)?;
|
||||
|
||||
set_user_sigmask(&mut sigmask);
|
||||
|
||||
let wait_ret = do_epoll_wait(epfd, epoll_event, max_events, timespec);
|
||||
|
||||
if wait_ret.is_err() && *wait_ret.as_ref().unwrap_err() != SystemError::EINTR {
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
wait_ret
|
||||
}
|
||||
|
||||
fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
|
||||
vec![
|
||||
FormattedSyscallParam::new("epfd", format!("{:#x}", Self::epfd(args) as usize)),
|
||||
FormattedSyscallParam::new("event", format!("{:#x}", Self::epoll_event(args).data())),
|
||||
FormattedSyscallParam::new("max_events", format!("{:#x}", Self::max_events(args))),
|
||||
FormattedSyscallParam::new("timespec", format!("{:#x}", Self::timespec(args))),
|
||||
FormattedSyscallParam::new(
|
||||
"sigmask_addr",
|
||||
format!("{:#x}", Self::sigmask_addr(args) as usize),
|
||||
),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl SysEpollPwaitHandle {
|
||||
fn epfd(args: &[usize]) -> i32 {
|
||||
args[0] as i32
|
||||
}
|
||||
fn epoll_event(args: &[usize]) -> VirtAddr {
|
||||
VirtAddr::new(args[1])
|
||||
}
|
||||
fn max_events(args: &[usize]) -> i32 {
|
||||
args[2] as i32
|
||||
}
|
||||
fn timespec(args: &[usize]) -> i32 {
|
||||
args[3] as i32
|
||||
}
|
||||
fn sigmask_addr(args: &[usize]) -> *mut SigSet {
|
||||
args[4] as *mut SigSet
|
||||
}
|
||||
}
|
||||
|
||||
syscall_table_macros::declare_syscall!(SYS_EPOLL_PWAIT, SysEpollPwaitHandle);
|
52
kernel/src/filesystem/vfs/syscall/sys_epoll_wait.rs
Normal file
52
kernel/src/filesystem/vfs/syscall/sys_epoll_wait.rs
Normal file
@ -0,0 +1,52 @@
|
||||
//! System call handler for epoll_wait.
|
||||
|
||||
use super::epoll_utils::do_epoll_wait;
|
||||
use crate::arch::syscall::nr::SYS_EPOLL_WAIT;
|
||||
use crate::mm::VirtAddr;
|
||||
use crate::syscall::table::FormattedSyscallParam;
|
||||
use crate::syscall::table::Syscall;
|
||||
use alloc::vec::Vec;
|
||||
use system_error::SystemError;
|
||||
|
||||
pub struct SysEpollWaitHandle;
|
||||
|
||||
impl Syscall for SysEpollWaitHandle {
|
||||
fn num_args(&self) -> usize {
|
||||
4
|
||||
}
|
||||
|
||||
fn handle(&self, args: &[usize], _from_user: bool) -> Result<usize, SystemError> {
|
||||
let epfd = Self::epfd(args);
|
||||
let max_events = Self::max_events(args);
|
||||
let timeout = Self::timeout(args);
|
||||
let events = Self::events(args);
|
||||
|
||||
do_epoll_wait(epfd, events, max_events, timeout)
|
||||
}
|
||||
|
||||
fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
|
||||
vec![
|
||||
FormattedSyscallParam::new("epfd", format!("{:#x}", Self::epfd(args) as usize)),
|
||||
FormattedSyscallParam::new("events", format!("{:#x}", Self::events(args).data())),
|
||||
FormattedSyscallParam::new("max_events", format!("{:#x}", Self::max_events(args))),
|
||||
FormattedSyscallParam::new("timeout", format!("{:#x}", Self::timeout(args))),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl SysEpollWaitHandle {
|
||||
fn epfd(args: &[usize]) -> i32 {
|
||||
args[0] as i32
|
||||
}
|
||||
fn events(args: &[usize]) -> VirtAddr {
|
||||
VirtAddr::new(args[1])
|
||||
}
|
||||
fn max_events(args: &[usize]) -> i32 {
|
||||
args[2] as i32
|
||||
}
|
||||
fn timeout(args: &[usize]) -> i32 {
|
||||
args[3] as i32
|
||||
}
|
||||
}
|
||||
|
||||
syscall_table_macros::declare_syscall!(SYS_EPOLL_WAIT, SysEpollWaitHandle);
|
@ -2,15 +2,17 @@ use core::sync::atomic::compiler_fence;
|
||||
|
||||
use crate::{
|
||||
arch::ipc::signal::{SigCode, Signal},
|
||||
filesystem::vfs::{
|
||||
file::FileMode, syscall::ModeType, vcore::generate_inode_id, FilePrivateData, FileSystem,
|
||||
FileType, IndexNode, Metadata, PollableInode,
|
||||
filesystem::{
|
||||
epoll::{event_poll::EventPoll, EPollEventType, EPollItem},
|
||||
vfs::{
|
||||
file::FileMode, syscall::ModeType, vcore::generate_inode_id, FilePrivateData,
|
||||
FileSystem, FileType, IndexNode, Metadata, PollableInode,
|
||||
},
|
||||
},
|
||||
libs::{
|
||||
spinlock::{SpinLock, SpinLockGuard},
|
||||
wait_queue::WaitQueue,
|
||||
},
|
||||
net::event_poll::{EPollEventType, EPollItem, EventPoll},
|
||||
process::{ProcessFlags, ProcessManager, ProcessState},
|
||||
sched::SchedMode,
|
||||
time::PosixTimeSpec,
|
||||
|
@ -1,108 +0,0 @@
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
arch::ipc::signal::SigSet,
|
||||
filesystem::vfs::file::FileMode,
|
||||
ipc::signal::{restore_saved_sigmask, set_user_sigmask},
|
||||
mm::VirtAddr,
|
||||
syscall::{
|
||||
user_access::{UserBufferReader, UserBufferWriter},
|
||||
Syscall,
|
||||
},
|
||||
time::PosixTimeSpec,
|
||||
};
|
||||
|
||||
use super::{EPollCtlOption, EPollEvent, EventPoll};
|
||||
|
||||
impl Syscall {
|
||||
pub fn epoll_create(max_size: i32) -> Result<usize, SystemError> {
|
||||
if max_size < 0 {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
|
||||
return EventPoll::create_epoll(FileMode::empty());
|
||||
}
|
||||
|
||||
pub fn epoll_create1(flag: usize) -> Result<usize, SystemError> {
|
||||
let flags = FileMode::from_bits_truncate(flag as u32);
|
||||
|
||||
let ret = EventPoll::create_epoll(flags);
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn epoll_wait(
|
||||
epfd: i32,
|
||||
events: VirtAddr,
|
||||
max_events: i32,
|
||||
timeout: i32,
|
||||
) -> Result<usize, SystemError> {
|
||||
if max_events <= 0 || max_events as u32 > EventPoll::EP_MAX_EVENTS {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
|
||||
let mut timespec = None;
|
||||
if timeout == 0 {
|
||||
timespec = Some(PosixTimeSpec::new(0, 0));
|
||||
}
|
||||
|
||||
if timeout > 0 {
|
||||
let sec: i64 = timeout as i64 / 1000;
|
||||
let nsec: i64 = 1000000 * (timeout as i64 % 1000);
|
||||
|
||||
timespec = Some(PosixTimeSpec::new(sec, nsec))
|
||||
}
|
||||
|
||||
// 从用户传入的地址中拿到epoll_events
|
||||
let mut epds_writer = UserBufferWriter::new(
|
||||
events.as_ptr::<EPollEvent>(),
|
||||
max_events as usize * core::mem::size_of::<EPollEvent>(),
|
||||
true,
|
||||
)?;
|
||||
|
||||
let epoll_events = epds_writer.buffer::<EPollEvent>(0)?;
|
||||
return EventPoll::epoll_wait(epfd, epoll_events, max_events, timespec);
|
||||
}
|
||||
|
||||
pub fn epoll_ctl(epfd: i32, op: usize, fd: i32, event: VirtAddr) -> Result<usize, SystemError> {
|
||||
let op = EPollCtlOption::from_op_num(op)?;
|
||||
let mut epds = EPollEvent::default();
|
||||
if op != EPollCtlOption::Del {
|
||||
// 不为EpollCtlDel时不允许传入空指针
|
||||
if event.is_null() {
|
||||
return Err(SystemError::EFAULT);
|
||||
}
|
||||
|
||||
// 还是一样的问题,C标准的epoll_event大小为12字节,而内核实现的epoll_event内存对齐后为16字节
|
||||
// 这样分别拷贝其实和整体拷贝差别不大,内核使用内存对其版本甚至可能提升性能
|
||||
let epds_reader = UserBufferReader::new(
|
||||
event.as_ptr::<EPollEvent>(),
|
||||
core::mem::size_of::<EPollEvent>(),
|
||||
true,
|
||||
)?;
|
||||
|
||||
// 拷贝到内核
|
||||
epds_reader.copy_one_from_user(&mut epds, 0)?;
|
||||
}
|
||||
|
||||
return EventPoll::epoll_ctl_with_epfd(epfd, op, fd, epds, false);
|
||||
}
|
||||
|
||||
/// ## 在epoll_wait时屏蔽某些信号
|
||||
pub fn epoll_pwait(
|
||||
epfd: i32,
|
||||
epoll_event: VirtAddr,
|
||||
max_events: i32,
|
||||
timespec: i32,
|
||||
sigmask: &mut SigSet,
|
||||
) -> Result<usize, SystemError> {
|
||||
// 设置屏蔽的信号
|
||||
set_user_sigmask(sigmask);
|
||||
|
||||
let wait_ret = Self::epoll_wait(epfd, epoll_event, max_events, timespec);
|
||||
|
||||
if wait_ret.is_err() && *wait_ret.as_ref().unwrap_err() != SystemError::EINTR {
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
wait_ret
|
||||
}
|
||||
}
|
@ -10,7 +10,6 @@ use smoltcp::wire::IpEndpoint;
|
||||
|
||||
use self::socket::SocketInode;
|
||||
|
||||
pub mod event_poll;
|
||||
pub mod net_core;
|
||||
pub mod socket;
|
||||
pub mod syscall;
|
||||
|
@ -3,8 +3,10 @@ use log::{debug, info, warn};
|
||||
use smoltcp::{socket::dhcpv4, wire};
|
||||
use system_error::SystemError;
|
||||
|
||||
use super::socket::{handle::GlobalSocketHandle, inet::TcpSocket, HANDLE_MAP, SOCKET_SET};
|
||||
use crate::{
|
||||
driver::net::{NetDevice, Operstate},
|
||||
filesystem::epoll::{event_poll::EventPoll, EPollEventType},
|
||||
libs::rwlock::RwLockReadGuard,
|
||||
net::{socket::SocketPollMethod, NET_DEVICES},
|
||||
time::{
|
||||
@ -14,11 +16,6 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
use super::{
|
||||
event_poll::{EPollEventType, EventPoll},
|
||||
socket::{handle::GlobalSocketHandle, inet::TcpSocket, HANDLE_MAP, SOCKET_SET},
|
||||
};
|
||||
|
||||
/// The network poll function, which will be called by timer.
|
||||
///
|
||||
/// The main purpose of this function is to poll all network interfaces.
|
||||
|
@ -8,11 +8,9 @@ use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
driver::net::NetDevice,
|
||||
filesystem::epoll::EPollEventType,
|
||||
libs::rwlock::RwLock,
|
||||
net::{
|
||||
event_poll::EPollEventType, net_core::poll_ifaces, Endpoint, Protocol, ShutdownType,
|
||||
NET_DEVICES,
|
||||
},
|
||||
net::{net_core::poll_ifaces, Endpoint, Protocol, ShutdownType, NET_DEVICES},
|
||||
};
|
||||
|
||||
use super::{
|
||||
|
@ -17,9 +17,12 @@ use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
arch::rand::rand,
|
||||
filesystem::vfs::{
|
||||
file::FileMode, syscall::ModeType, FilePrivateData, FileSystem, FileType, IndexNode,
|
||||
Metadata, PollableInode,
|
||||
filesystem::{
|
||||
epoll::{EPollEventType, EPollItem},
|
||||
vfs::{
|
||||
file::FileMode, syscall::ModeType, FilePrivateData, FileSystem, FileType, IndexNode,
|
||||
Metadata, PollableInode,
|
||||
},
|
||||
},
|
||||
libs::{
|
||||
rwlock::{RwLock, RwLockWriteGuard},
|
||||
@ -36,10 +39,7 @@ use self::{
|
||||
unix::{SeqpacketSocket, StreamSocket},
|
||||
};
|
||||
|
||||
use super::{
|
||||
event_poll::{EPollEventType, EPollItem},
|
||||
Endpoint, Protocol, ShutdownType,
|
||||
};
|
||||
use super::{Endpoint, Protocol, ShutdownType};
|
||||
|
||||
pub mod handle;
|
||||
pub mod inet;
|
||||
|
@ -2,6 +2,7 @@ mod bpf;
|
||||
mod kprobe;
|
||||
mod util;
|
||||
|
||||
use crate::filesystem::epoll::{event_poll::EventPoll, EPollEventType, EPollItem};
|
||||
use crate::filesystem::page_cache::PageCache;
|
||||
use crate::filesystem::vfs::file::{File, FileMode};
|
||||
use crate::filesystem::vfs::syscall::ModeType;
|
||||
@ -15,7 +16,6 @@ use crate::libs::casting::DowncastArc;
|
||||
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
|
||||
use crate::mm::fault::{PageFaultHandler, PageFaultMessage};
|
||||
use crate::mm::VmFaultReason;
|
||||
use crate::net::event_poll::{EPollEventType, EPollItem, EventPoll};
|
||||
use crate::perf::bpf::BpfPerfEvent;
|
||||
use crate::perf::util::{PerfEventIoc, PerfEventOpenFlags, PerfProbeArgs};
|
||||
use crate::process::ProcessManager;
|
||||
|
@ -4,7 +4,7 @@ use core::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
arch::{ipc::signal::SigSet, syscall::nr::*},
|
||||
arch::syscall::nr::*,
|
||||
filesystem::vfs::syscall::PosixStatfs,
|
||||
ipc::shm::{ShmCtlCmd, ShmFlags, ShmId, ShmKey},
|
||||
libs::{futex::constant::FutexFlag, rand::GRandFlags},
|
||||
@ -762,48 +762,6 @@ impl Syscall {
|
||||
args[4],
|
||||
),
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
SYS_EPOLL_CREATE => Self::epoll_create(args[0] as i32),
|
||||
SYS_EPOLL_CREATE1 => Self::epoll_create1(args[0]),
|
||||
|
||||
SYS_EPOLL_CTL => Self::epoll_ctl(
|
||||
args[0] as i32,
|
||||
args[1],
|
||||
args[2] as i32,
|
||||
VirtAddr::new(args[3]),
|
||||
),
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
SYS_EPOLL_WAIT => Self::epoll_wait(
|
||||
args[0] as i32,
|
||||
VirtAddr::new(args[1]),
|
||||
args[2] as i32,
|
||||
args[3] as i32,
|
||||
),
|
||||
|
||||
SYS_EPOLL_PWAIT => {
|
||||
let epfd = args[0] as i32;
|
||||
let epoll_event = VirtAddr::new(args[1]);
|
||||
let max_events = args[2] as i32;
|
||||
let timespec = args[3] as i32;
|
||||
let sigmask_addr = args[4] as *mut SigSet;
|
||||
|
||||
if sigmask_addr.is_null() {
|
||||
return Self::epoll_wait(epfd, epoll_event, max_events, timespec);
|
||||
}
|
||||
let sigmask_reader =
|
||||
UserBufferReader::new(sigmask_addr, core::mem::size_of::<SigSet>(), true)?;
|
||||
let mut sigmask = *sigmask_reader.read_one_from_user::<SigSet>(0)?;
|
||||
|
||||
Self::epoll_pwait(
|
||||
args[0] as i32,
|
||||
VirtAddr::new(args[1]),
|
||||
args[2] as i32,
|
||||
args[3] as i32,
|
||||
&mut sigmask,
|
||||
)
|
||||
}
|
||||
|
||||
// 目前为了适配musl-libc,以下系统调用先这样写着
|
||||
SYS_GETRANDOM => {
|
||||
let flags = GRandFlags::from_bits(args[2] as u8).ok_or(SystemError::EINVAL)?;
|
||||
|
Loading…
x
Reference in New Issue
Block a user