diff --git a/ulib/axstarry/src/syscall_fs/ctype/eventfd.rs b/ulib/axstarry/src/syscall_fs/ctype/eventfd.rs index 0bbfd24b..dc4a0751 100644 --- a/ulib/axstarry/src/syscall_fs/ctype/eventfd.rs +++ b/ulib/axstarry/src/syscall_fs/ctype/eventfd.rs @@ -2,11 +2,20 @@ extern crate alloc; use alloc::sync::Arc; use core::mem::size_of; use axerrno::{AxError, AxResult}; -use axfs::api::{FileIO, FileIOType, SeekFrom}; +use axfs::api::{FileIO, OpenFlags, FileIOType, SeekFrom}; use axsync::Mutex; use axtask::yield_now; use axlog::error; +bitflags::bitflags! { + #[derive(Debug, Clone, Copy)] + pub struct EfdFlags: u32 { + const EFD_SEMAPHORE = 0o0000001; + const EFD_CLOEXEC = 0o2000000; + const EFD_NONBLOCK = 0o0004000; + } +} + pub struct EventfdFile { pub inner: Arc>, } @@ -42,11 +51,24 @@ impl EventfdFile { impl FileIO for EventfdFile { fn read(&self, buf: &mut [u8]) -> AxResult { error!(">>> eventfd read start"); + + if buf.len() < core::mem::size_of::() { + return Err(AxError::InvalidInput); + } + let mut cnt = 0; loop { let mut inner = self.inner.lock(); - if inner.ctx.count > 0 { - cnt = inner.ctx.count; // EFD_SEMAPHORE ? + let flags = EfdFlags::from_bits_truncate(inner.ctx.flags); + if inner.ctx.count > 0 || flags.contains(EfdFlags::EFD_NONBLOCK) { + if inner.ctx.count == 0 { + return Err(AxError::WouldBlock); + } + if flags.contains(EfdFlags::EFD_SEMAPHORE) { + cnt = 1; + } else { + cnt = inner.ctx.count; // EFD_SEMAPHORE ? + } inner.ctx.count -= cnt; break } @@ -64,8 +86,27 @@ impl FileIO for EventfdFile { fn write(&self, buf: &[u8]) -> AxResult { error!(">>> eventfd write start"); - let mut inner = self.inner.lock(); + if buf.len() < core::mem::size_of::() { + return Err(AxError::InvalidInput); + } + let ucnt: u64 = u64::from_ne_bytes(buf.try_into().unwrap()); + if ucnt == u64::MAX { + return Err(AxError::InvalidInput); + } + loop { + let inner = self.inner.lock(); + if u64::MAX - inner.ctx.count > ucnt { + break + } + let flags = EfdFlags::from_bits_truncate(inner.ctx.flags); + if flags.contains(EfdFlags::EFD_NONBLOCK) { + return Err(AxError::WouldBlock); + } + drop(inner); + yield_now(); + } + let mut inner = self.inner.lock(); inner.ctx.count += ucnt; error!(">>> eventfd write over"); @@ -93,11 +134,30 @@ impl FileIO for EventfdFile { } } fn ready_to_write(&self) -> bool { - true + let inner = self.inner.lock(); + if inner.ctx.count < u64::MAX { + true + } else { + false + } } fn executable(&self) -> bool { false } + fn get_status(&self) -> OpenFlags { + let mut status = OpenFlags::RDWR; + + let inner = self.inner.lock(); + let flags = EfdFlags::from_bits_truncate(inner.ctx.flags); + if flags.contains(EfdFlags::EFD_NONBLOCK) { + status.insert(OpenFlags::NON_BLOCK); + } + if flags.contains(EfdFlags::EFD_CLOEXEC) { + status.insert(OpenFlags::CLOEXEC); + } + + status + } fn get_type(&self) -> FileIOType { FileIOType::FileDesc } diff --git a/ulib/axstarry/src/syscall_fs/imp/io.rs b/ulib/axstarry/src/syscall_fs/imp/io.rs index 5f254c46..58daaec0 100644 --- a/ulib/axstarry/src/syscall_fs/imp/io.rs +++ b/ulib/axstarry/src/syscall_fs/imp/io.rs @@ -83,6 +83,7 @@ pub fn syscall_read(args: [usize; 6]) -> SyscallResult { match file.read(buf) { Ok(len) => Ok(len as isize), Err(AxError::WouldBlock) => Err(SyscallError::EAGAIN), + Err(AxError::InvalidInput) => Err(SyscallError::EINVAL), Err(_) => Err(SyscallError::EPERM), } } @@ -155,6 +156,8 @@ pub fn syscall_write(args: [usize; 6]) -> SyscallResult { // socket with send half closed // TODO: send a SIGPIPE signal to the process Err(axerrno::AxError::ConnectionReset) => Err(SyscallError::EPIPE), + Err(AxError::WouldBlock) => Err(SyscallError::EAGAIN), + Err(AxError::InvalidInput) => Err(SyscallError::EINVAL), Err(_) => Err(SyscallError::EPERM), } }