123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- use crate::filesystem::vfs::file::{File, FileMode};
- use crate::filesystem::vfs::syscall::ModeType;
- use crate::filesystem::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, KernelIoctlData};
- use crate::process::ProcessManager;
- use crate::syscall::Syscall;
- use alloc::collections::LinkedList;
- use alloc::string::String;
- use alloc::sync::Arc;
- use alloc::sync::Weak;
- use alloc::vec::Vec;
- use core::any::Any;
- use ida::IdAllocator;
- use system_error::SystemError;
- static EVENTFD_ID_ALLOCATOR: SpinLock<IdAllocator> =
- SpinLock::new(IdAllocator::new(0, u32::MAX as usize).unwrap());
- bitflags! {
- pub struct EventFdFlags: u32{
- /// Provide semaphore-like semantics for reads from the new
- /// file descriptor.
- const EFD_SEMAPHORE = 0o1;
- /// Set the close-on-exec (FD_CLOEXEC) flag on the new file
- /// descriptor
- const EFD_CLOEXEC = 0o2000000;
- /// Set the O_NONBLOCK file status flag on the open file
- /// description (see open(2)) referred to by the new file
- /// descriptor
- const EFD_NONBLOCK = 0o0004000;
- }
- }
- #[derive(Debug)]
- pub struct EventFd {
- count: u64,
- flags: EventFdFlags,
- #[allow(unused)]
- id: u32,
- }
- impl EventFd {
- pub fn new(count: u64, flags: EventFdFlags, id: u32) -> Self {
- EventFd { count, flags, id }
- }
- }
- #[derive(Debug)]
- pub struct EventFdInode {
- eventfd: SpinLock<EventFd>,
- wait_queue: WaitQueue,
- epitems: SpinLock<LinkedList<Arc<EPollItem>>>,
- }
- impl EventFdInode {
- pub fn new(eventfd: EventFd) -> Self {
- EventFdInode {
- eventfd: SpinLock::new(eventfd),
- wait_queue: WaitQueue::default(),
- epitems: SpinLock::new(LinkedList::new()),
- }
- }
- pub fn remove_epoll(&self, epoll: &Weak<SpinLock<EventPoll>>) -> Result<(), SystemError> {
- let is_remove = !self
- .epitems
- .lock_irqsave()
- .extract_if(|x| x.epoll().ptr_eq(epoll))
- .collect::<Vec<_>>()
- .is_empty();
- if is_remove {
- return Ok(());
- }
- Err(SystemError::ENOENT)
- }
- }
- impl IndexNode for EventFdInode {
- fn open(
- &self,
- _data: SpinLockGuard<FilePrivateData>,
- _mode: &FileMode,
- ) -> Result<(), SystemError> {
- Ok(())
- }
- fn close(&self, _data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> {
- Ok(())
- }
- /// # 从 counter 里读取一个 8 字节的int值
- ///
- /// 1. counter !=0
- /// - EFD_SEMAPHORE 如果没有被设置,从 eventfd read,会得到 counter,并将它归0
- /// - EFD_SEMAPHORE 如果被设置,从 eventfd read,会得到值 1,并将 counter - 1
- /// 2. counter == 0
- /// - EFD_NONBLOCK 如果被设置,那么会以 EAGAIN 的错失败
- /// - 否则 read 会被阻塞,直到为非0。
- fn read_at(
- &self,
- _offset: usize,
- len: usize,
- buf: &mut [u8],
- data: SpinLockGuard<FilePrivateData>,
- ) -> Result<usize, SystemError> {
- if len < 8 {
- return Err(SystemError::EINVAL);
- }
- let mut val = loop {
- let val = self.eventfd.lock().count;
- if val != 0 {
- break val;
- }
- if self
- .eventfd
- .lock()
- .flags
- .contains(EventFdFlags::EFD_NONBLOCK)
- {
- return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
- }
- self.wait_queue.sleep();
- };
- let mut eventfd = self.eventfd.lock();
- if eventfd.flags.contains(EventFdFlags::EFD_SEMAPHORE) {
- eventfd.count -= 1;
- val = 1;
- } else {
- eventfd.count = 0;
- }
- let val_bytes = val.to_ne_bytes();
- buf[..8].copy_from_slice(&val_bytes);
- let pollflag = EPollEventType::from_bits_truncate(self.poll(&data)? as u32);
- // 唤醒epoll中等待的进程
- EventPoll::wakeup_epoll(&self.epitems, pollflag)?;
- return Ok(8);
- }
- /// # 把一个 8 字节的int值写入到 counter 里
- ///
- /// - counter 最大值是 2^64 - 1
- /// - 如果写入时会发生溢出,则write会被阻塞
- /// - 如果 EFD_NONBLOCK 被设置,那么以 EAGAIN 失败
- /// - 以不合法的值写入时,会以 EINVAL 失败
- /// - 比如 0xffffffffffffffff 不合法
- /// - 比如 写入的值 size 小于8字节
- fn write_at(
- &self,
- _offset: usize,
- len: usize,
- buf: &[u8],
- data: SpinLockGuard<FilePrivateData>,
- ) -> Result<usize, SystemError> {
- if len < 8 {
- return Err(SystemError::EINVAL);
- }
- let val = u64::from_ne_bytes(buf[..8].try_into().unwrap());
- if val == u64::MAX {
- return Err(SystemError::EINVAL);
- }
- loop {
- let eventfd = self.eventfd.lock();
- if u64::MAX - eventfd.count > val {
- break;
- }
- // block until a read() is performed on the
- // file descriptor, or fails with the error EAGAIN if the
- // file descriptor has been made nonblocking.
- if eventfd.flags.contains(EventFdFlags::EFD_NONBLOCK) {
- return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
- }
- drop(eventfd);
- self.wait_queue.sleep();
- }
- let mut eventfd = self.eventfd.lock();
- eventfd.count += val;
- self.wait_queue.wakeup_all(None);
- let pollflag = EPollEventType::from_bits_truncate(self.poll(&data)? as u32);
- // 唤醒epoll中等待的进程
- EventPoll::wakeup_epoll(&self.epitems, pollflag)?;
- return Ok(8);
- }
- /// # 检查 eventfd 的状态
- ///
- /// - 如果 counter 的值大于 0 ,那么 fd 的状态就是可读的
- /// - 如果能无阻塞地写入一个至少为 1 的值,那么 fd 的状态就是可写的
- fn poll(&self, _private_data: &FilePrivateData) -> Result<usize, SystemError> {
- let mut events = EPollEventType::empty();
- if self.eventfd.lock().count != 0 {
- events |= EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM;
- }
- if self.eventfd.lock().count != u64::MAX {
- events |= EPollEventType::EPOLLOUT | EPollEventType::EPOLLWRNORM;
- }
- return Ok(events.bits() as usize);
- }
- fn metadata(&self) -> Result<Metadata, SystemError> {
- let meta = Metadata {
- mode: ModeType::from_bits_truncate(0o755),
- file_type: FileType::File,
- ..Default::default()
- };
- Ok(meta)
- }
- fn resize(&self, _len: usize) -> Result<(), SystemError> {
- Ok(())
- }
- fn kernel_ioctl(
- &self,
- arg: Arc<dyn KernelIoctlData>,
- _data: &FilePrivateData,
- ) -> Result<usize, SystemError> {
- let epitem = arg
- .arc_any()
- .downcast::<EPollItem>()
- .map_err(|_| SystemError::EFAULT)?;
- self.epitems.lock().push_back(epitem);
- Ok(0)
- }
- fn fs(&self) -> Arc<dyn FileSystem> {
- panic!("EventFd does not have a filesystem")
- }
- fn as_any_ref(&self) -> &dyn Any {
- self
- }
- fn list(&self) -> Result<Vec<String>, SystemError> {
- Err(SystemError::EINVAL)
- }
- }
- impl Syscall {
- /// # 创建一个 eventfd 文件描述符
- ///
- /// ## 参数
- /// - `init_val`: u32: eventfd 的初始值
- /// - `flags`: u32: eventfd 的标志
- ///
- /// ## 返回值
- /// - `Ok(usize)`: 成功创建的文件描述符
- /// - `Err(SystemError)`: 创建失败
- ///
- /// See: https://man7.org/linux/man-pages/man2/eventfd2.2.html
- pub fn sys_eventfd(init_val: u32, flags: u32) -> Result<usize, SystemError> {
- let flags = EventFdFlags::from_bits(flags).ok_or(SystemError::EINVAL)?;
- let id = EVENTFD_ID_ALLOCATOR
- .lock()
- .alloc()
- .ok_or(SystemError::ENOMEM)? as u32;
- let eventfd = EventFd::new(init_val as u64, flags, id);
- let inode = Arc::new(EventFdInode::new(eventfd));
- let filemode = if flags.contains(EventFdFlags::EFD_CLOEXEC) {
- FileMode::O_RDWR | FileMode::O_CLOEXEC
- } else {
- FileMode::O_RDWR
- };
- let file = File::new(inode, filemode)?;
- let binding = ProcessManager::current_pcb().fd_table();
- let mut fd_table_guard = binding.write();
- let fd = fd_table_guard.alloc_fd(file, None).map(|x| x as usize);
- return fd;
- }
- }
|