diff --git a/src/process/fd_table/select.rs b/src/process/fd_table/select.rs index 38036eb0..e5758e3b 100644 --- a/src/process/fd_table/select.rs +++ b/src/process/fd_table/select.rs @@ -1,10 +1,11 @@ use alloc::{boxed::Box, vec::Vec}; -use core::{future::poll_fn, iter, pin::pin, task::Poll, time::Duration}; +use core::{future::poll_fn, iter, pin::pin, task::Poll}; use libkernel::{ error::{KernelError, Result}, memory::address::TUA, }; +use super::Fd; use crate::{ clock::timespec::TimeSpec, drivers::timer::sleep, @@ -15,8 +16,6 @@ use crate::{ sched::syscall_ctx::ProcessCtx, }; -use super::Fd; - const SET_SIZE: usize = 1024; #[derive(Clone, Copy, Debug)] @@ -59,15 +58,15 @@ impl FdSet { unsafe impl UserCopyable for FdSet {} -// TODO: writefds, exceptfds, timeout. +// TODO: handle exceptfds pub async fn sys_pselect6( ctx: &ProcessCtx, max: i32, readfds: TUA, - _writefds: TUA, + writefds: TUA, _exceptfds: TUA, timeout: TUA, - _mask: TUA, + mask: TUA, ) -> Result { let task = ctx.shared(); @@ -75,10 +74,15 @@ pub async fn sys_pselect6( let mut read_fds = Vec::new(); - let timeout: Option = if timeout.is_null() { + let mut write_fd_set = copy_from_user(writefds).await?; + + let mut write_fds = Vec::new(); + + let mut timeout_fut = if timeout.is_null() { None } else { - Some(copy_from_user(timeout).await?.into()) + let duration = copy_from_user(timeout).await?.into(); + Some(pin!(sleep(duration))) }; for fd in read_fd_set.iter_fds(max) { @@ -98,7 +102,37 @@ pub async fn sys_pselect6( )); } + for fd in write_fd_set.iter_fds(max) { + let file = task + .fd_table + .lock_save_irq() + .get(fd) + .ok_or(KernelError::BadFd)?; + + write_fds.push(( + Box::pin(async move { + let (ops, _) = &mut *file.lock().await; + + ops.poll_write_ready().await + }), + fd, + )); + } + + let mask = if mask.is_null() { + None + } else { + Some(copy_from_user(mask).await?) + }; + let old_sigmask = task.sig_mask.load(); + if let Some(mask) = mask { + let mut new_sigmask = mask; + new_sigmask.remove(SigSet::UNMASKABLE_SIGNALS); + task.sig_mask.store(new_sigmask); + } + read_fd_set.zero(); + write_fd_set.zero(); let n = poll_fn(|cx| { let mut num_ready: usize = 0; @@ -112,15 +146,17 @@ pub async fn sys_pselect6( } } + for (fut, fd) in write_fds.iter_mut() { + if fut.as_mut().poll(cx).is_ready() { + write_fd_set.set_fd(*fd); + num_ready += 1; + } + } + if num_ready == 0 { - // Check for the case where both timeout fields are zero: - // - // If both fields of the timeval structure are zero, then select() - // returns immediately. - if let Some(timeout) = timeout - && timeout.is_zero() - { - Poll::Ready(0) + // Check if done + if let Some(ref mut timeout) = timeout_fut { + timeout.as_mut().poll(cx).map(|_| 0) } else { Poll::Pending } @@ -131,6 +167,10 @@ pub async fn sys_pselect6( .await; copy_to_user(readfds, read_fd_set).await?; + copy_to_user(writefds, write_fd_set).await?; + if mask.is_some() { + task.sig_mask.store(old_sigmask); + } Ok(n) } diff --git a/src/process/thread_group/signal.rs b/src/process/thread_group/signal.rs index c2289bee..bbf68e51 100644 --- a/src/process/thread_group/signal.rs +++ b/src/process/thread_group/signal.rs @@ -54,6 +54,7 @@ bitflags! { const SIGIO = 1 << 28; const SIGPWR = 1 << 29; const SIGUNUSED = 1 << 30; + const UNMASKABLE_SIGNALS = Self::SIGKILL.bits() | Self::SIGSTOP.bits(); } } @@ -213,9 +214,6 @@ impl Display for SigId { } } -// SIGKILL and SIGSTOP -const UNMASKABLE_SIGNALS: SigSet = SigSet::SIGKILL.union(SigSet::SIGSTOP); - #[derive(Clone, Copy, Debug)] pub enum SigActionState { Ignore, diff --git a/src/process/thread_group/signal/sigprocmask.rs b/src/process/thread_group/signal/sigprocmask.rs index c06d4a55..dc757f72 100644 --- a/src/process/thread_group/signal/sigprocmask.rs +++ b/src/process/thread_group/signal/sigprocmask.rs @@ -3,7 +3,7 @@ use crate::sched::syscall_ctx::ProcessCtx; use libkernel::error::{KernelError, Result}; use libkernel::memory::address::TUA; -use super::{SigSet, UNMASKABLE_SIGNALS}; +use super::SigSet; pub const SIG_BLOCK: u32 = 0; pub const SIG_UNBLOCK: u32 = 1; @@ -39,7 +39,7 @@ pub async fn sys_rt_sigprocmask( }; // SIGSTOP and SIGKILL can never be masked. - new_sigmask.remove(UNMASKABLE_SIGNALS); + new_sigmask.remove(SigSet::UNMASKABLE_SIGNALS); task.sig_mask.store(new_sigmask); }