mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-22 08:53:29 +00:00
Add syscall ppoll
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
1fe0fef410
commit
8815ca384f
@ -73,6 +73,7 @@ use crate::syscall::{
|
||||
pause::sys_pause,
|
||||
pipe::{sys_pipe, sys_pipe2},
|
||||
poll::sys_poll,
|
||||
ppoll::sys_ppoll,
|
||||
prctl::sys_prctl,
|
||||
pread64::sys_pread64,
|
||||
preadv::{sys_preadv, sys_preadv2, sys_readv},
|
||||
@ -336,6 +337,7 @@ impl_syscall_nums_and_dispatch_fn! {
|
||||
SYS_FCHMODAT = 268 => sys_fchmodat(args[..3]);
|
||||
SYS_FACCESSAT = 269 => sys_faccessat(args[..3]);
|
||||
SYS_PSELECT6 = 270 => sys_pselect6(args[..6]);
|
||||
SYS_PPOLL = 271 => sys_ppoll(args[..5]);
|
||||
SYS_SET_ROBUST_LIST = 273 => sys_set_robust_list(args[..2]);
|
||||
SYS_UTIMENSAT = 280 => sys_utimensat(args[..4]);
|
||||
SYS_EPOLL_PWAIT = 281 => sys_epoll_pwait(args[..6]);
|
||||
|
@ -80,6 +80,7 @@ mod open;
|
||||
mod pause;
|
||||
mod pipe;
|
||||
mod poll;
|
||||
mod ppoll;
|
||||
mod prctl;
|
||||
mod pread64;
|
||||
mod preadv;
|
||||
|
@ -10,10 +10,38 @@ use crate::{
|
||||
file_table::{FileDesc, FileTable},
|
||||
},
|
||||
prelude::*,
|
||||
process::signal::Poller,
|
||||
process::{signal::Poller, ResourceType},
|
||||
};
|
||||
|
||||
pub fn sys_poll(fds: Vaddr, nfds: u64, timeout: i32, ctx: &Context) -> Result<SyscallReturn> {
|
||||
pub fn sys_poll(fds: Vaddr, nfds: u32, timeout: i32, ctx: &Context) -> Result<SyscallReturn> {
|
||||
let timeout = if timeout >= 0 {
|
||||
Some(Duration::from_millis(timeout as _))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
do_sys_poll(fds, nfds, timeout, ctx)
|
||||
}
|
||||
|
||||
pub fn do_sys_poll(
|
||||
fds: Vaddr,
|
||||
nfds: u32,
|
||||
timeout: Option<Duration>,
|
||||
ctx: &Context,
|
||||
) -> Result<SyscallReturn> {
|
||||
if nfds as u64
|
||||
> ctx
|
||||
.process
|
||||
.resource_limits()
|
||||
.get_rlimit(ResourceType::RLIMIT_NOFILE)
|
||||
.get_cur()
|
||||
{
|
||||
return_errno_with_message!(
|
||||
Errno::EINVAL,
|
||||
"the `nfds` value exceeds the `RLIMIT_NOFILE` value"
|
||||
)
|
||||
}
|
||||
|
||||
let user_space = ctx.user_space();
|
||||
|
||||
let poll_fds = {
|
||||
@ -33,12 +61,6 @@ pub fn sys_poll(fds: Vaddr, nfds: u64, timeout: i32, ctx: &Context) -> Result<Sy
|
||||
poll_fds
|
||||
};
|
||||
|
||||
let timeout = if timeout >= 0 {
|
||||
Some(Duration::from_millis(timeout as _))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
debug!(
|
||||
"poll_fds = {:?}, nfds = {}, timeout = {:?}",
|
||||
poll_fds, nfds, timeout
|
||||
|
48
kernel/src/syscall/ppoll.rs
Normal file
48
kernel/src/syscall/ppoll.rs
Normal file
@ -0,0 +1,48 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use core::time::Duration;
|
||||
|
||||
use super::{poll::do_sys_poll, SyscallReturn};
|
||||
use crate::{
|
||||
prelude::*,
|
||||
process::signal::{sig_mask::SigMask, with_sigmask_changed},
|
||||
time::timespec_t,
|
||||
};
|
||||
|
||||
pub fn sys_ppoll(
|
||||
fds: Vaddr,
|
||||
nfds: u32,
|
||||
timespec_addr: Vaddr,
|
||||
sigmask_addr: Vaddr,
|
||||
sigmask_size: usize,
|
||||
ctx: &Context,
|
||||
) -> Result<SyscallReturn> {
|
||||
let user_space = ctx.user_space();
|
||||
|
||||
let timeout = if timespec_addr != 0 {
|
||||
let time_spec = user_space.read_val::<timespec_t>(timespec_addr)?;
|
||||
Some(Duration::try_from(time_spec)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if sigmask_addr != 0 {
|
||||
if sigmask_size != size_of::<SigMask>() {
|
||||
return_errno_with_message!(Errno::EINVAL, "invalid sigmask size");
|
||||
}
|
||||
|
||||
let sigmask = user_space.read_val::<SigMask>(sigmask_addr)?;
|
||||
with_sigmask_changed(ctx, |_| sigmask, || do_sys_poll(fds, nfds, timeout, ctx))
|
||||
} else {
|
||||
do_sys_poll(fds, nfds, timeout, ctx)
|
||||
}
|
||||
|
||||
// TODO: Write back the remaining time to `timespec_addr`.
|
||||
//
|
||||
// The ppoll system call should write back the remaining time,
|
||||
// yet the function counterpart in libc hides this behavior to
|
||||
// make the API more portable across different UNIX-like OSes.
|
||||
// For the maximized Linux compatibility, we should follow Linux's behavior.
|
||||
// But this cannot be readily achieved given how our internal synchronization primitives
|
||||
// such as `Pause` and `WaitTimeout` work.
|
||||
}
|
@ -1,10 +1,13 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use core::{sync::atomic::Ordering, time::Duration};
|
||||
use core::time::Duration;
|
||||
|
||||
use super::{select::do_sys_select, SyscallReturn};
|
||||
use crate::{
|
||||
fs::file_table::FileDesc, prelude::*, process::signal::sig_mask::SigMask, time::timespec_t,
|
||||
fs::file_table::FileDesc,
|
||||
prelude::*,
|
||||
process::signal::{sig_mask::SigMask, with_sigmask_changed},
|
||||
time::timespec_t,
|
||||
};
|
||||
|
||||
pub fn sys_pselect6(
|
||||
@ -17,45 +20,34 @@ pub fn sys_pselect6(
|
||||
ctx: &Context,
|
||||
) -> Result<SyscallReturn> {
|
||||
let user_space = ctx.user_space();
|
||||
let old_simask = if sigmask_addr != 0 {
|
||||
let sigmask_with_size: SigMaskWithSize = user_space.read_val(sigmask_addr)?;
|
||||
|
||||
if !sigmask_with_size.is_valid() {
|
||||
return_errno_with_message!(Errno::EINVAL, "sigmask size is invalid")
|
||||
}
|
||||
let old_sigmask = ctx
|
||||
.posix_thread
|
||||
.sig_mask()
|
||||
.swap(sigmask_with_size.sigmask, Ordering::Relaxed);
|
||||
|
||||
Some(old_sigmask)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let timeout = if timespec_addr != 0 {
|
||||
let time_spec: timespec_t = user_space.read_val(timespec_addr)?;
|
||||
let time_spec = user_space.read_val::<timespec_t>(timespec_addr)?;
|
||||
Some(Duration::try_from(time_spec)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let res = do_sys_select(
|
||||
nfds,
|
||||
readfds_addr,
|
||||
writefds_addr,
|
||||
exceptfds_addr,
|
||||
timeout,
|
||||
ctx,
|
||||
);
|
||||
let operate = || {
|
||||
do_sys_select(
|
||||
nfds,
|
||||
readfds_addr,
|
||||
writefds_addr,
|
||||
exceptfds_addr,
|
||||
timeout,
|
||||
ctx,
|
||||
)
|
||||
};
|
||||
|
||||
if let Some(old_mask) = old_simask {
|
||||
ctx.posix_thread
|
||||
.sig_mask()
|
||||
.store(old_mask, Ordering::Relaxed);
|
||||
if sigmask_addr != 0 {
|
||||
let sigmask_with_size = user_space.read_val::<SigMaskWithSize>(sigmask_addr)?;
|
||||
if !sigmask_with_size.is_valid() {
|
||||
return_errno_with_message!(Errno::EINVAL, "sigmask size is invalid")
|
||||
}
|
||||
with_sigmask_changed(ctx, |_: SigMask| sigmask_with_size.sigmask, operate)
|
||||
} else {
|
||||
operate()
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
||||
process::signal::{
|
||||
constants::{SIGKILL, SIGSTOP},
|
||||
sig_mask::SigMask,
|
||||
with_signal_blocked,
|
||||
with_sigmask_changed,
|
||||
},
|
||||
};
|
||||
|
||||
@ -37,7 +37,11 @@ pub fn sys_rt_sigsuspend(
|
||||
|
||||
// Wait until receiving any signal
|
||||
let waiter = Waiter::new_pair().0;
|
||||
with_signal_blocked(ctx, sigmask, || waiter.pause_until(|| None::<()>))?;
|
||||
with_sigmask_changed(
|
||||
ctx,
|
||||
|old_mask| old_mask + sigmask,
|
||||
|| waiter.pause_until(|| None::<()>),
|
||||
)?;
|
||||
|
||||
// This syscall should always return `Err(EINTR)`. This path should never be reached.
|
||||
unreachable!("rt_sigsuspend always return EINTR");
|
||||
|
Reference in New Issue
Block a user