Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 56 additions & 16 deletions src/process/fd_table/select.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -15,8 +16,6 @@ use crate::{
sched::syscall_ctx::ProcessCtx,
};

use super::Fd;

const SET_SIZE: usize = 1024;

#[derive(Clone, Copy, Debug)]
Expand Down Expand Up @@ -59,26 +58,31 @@ 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<FdSet>,
_writefds: TUA<FdSet>,
writefds: TUA<FdSet>,
_exceptfds: TUA<FdSet>,
timeout: TUA<TimeSpec>,
_mask: TUA<SigSet>,
mask: TUA<SigSet>,
) -> Result<usize> {
let task = ctx.shared();

let mut read_fd_set = copy_from_user(readfds).await?;

let mut read_fds = Vec::new();

let timeout: Option<Duration> = 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) {
Expand All @@ -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;
Expand All @@ -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
}
Expand All @@ -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)
}
Expand Down
4 changes: 1 addition & 3 deletions src/process/thread_group/signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}

Expand Down Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions src/process/thread_group/signal/sigprocmask.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down
Loading