Implement pselect and write test

This commit is contained in:
Wildan M
2026-05-22 03:29:57 +07:00
parent 0f216b2fa0
commit 0f03bff838
10 changed files with 229 additions and 12 deletions
+64 -8
View File
@@ -9,13 +9,15 @@ use cbitset::BitSet;
use crate::{
fs::File,
header::{
bits_sigset_t::sigset_t,
errno,
sys_epoll::{
EPOLL_CLOEXEC, EPOLL_CTL_ADD, EPOLLERR, EPOLLIN, EPOLLOUT, epoll_create1, epoll_ctl,
epoll_data, epoll_event, epoll_wait,
epoll_data, epoll_event, epoll_pwait,
},
time::timespec,
},
platform::{self, types::c_int},
platform::types::{c_int, suseconds_t},
};
pub use crate::header::bits_timeval::timeval;
@@ -42,9 +44,10 @@ pub fn select_epoll(
writefds: Option<&mut fd_set>,
exceptfds: Option<&mut fd_set>,
timeout: Option<&mut timeval>,
sigmask: *const sigset_t,
) -> c_int {
if nfds < 0 || nfds > FD_SETSIZE as i32 {
platform::ERRNO.set(errno::EINVAL);
crate::platform::ERRNO.set(errno::EINVAL);
return -1;
};
@@ -55,7 +58,6 @@ pub fn select_epoll(
}
File::new(epfd)
};
let mut read_bitset: Option<&mut FdBitSet> = readfds.map(|fd_set| &mut fd_set.fds_bits);
let mut write_bitset: Option<&mut FdBitSet> = writefds.map(|fd_set| &mut fd_set.fds_bits);
let mut except_bitset: Option<&mut FdBitSet> = exceptfds.map(|fd_set| &mut fd_set.fds_bits);
@@ -90,7 +92,7 @@ pub fn select_epoll(
..Default::default() // clippy lint, _pad field on redox but not linux
};
if unsafe { epoll_ctl(*ep, EPOLL_CTL_ADD, fd, &raw mut event) } < 0 {
if platform::ERRNO.get() == errno::EPERM {
if crate::platform::ERRNO.get() == errno::EPERM {
not_epoll += 1;
} else {
return -1;
@@ -134,12 +136,14 @@ pub fn select_epoll(
None => -1,
}
};
let res = unsafe {
epoll_wait(
epoll_pwait(
*ep,
events.as_mut_ptr(),
events.len() as c_int,
epoll_timeout,
sigmask,
)
};
if res < 0 {
@@ -174,7 +178,7 @@ pub fn select_epoll(
count
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pselect.html>.
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/select.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn select(
nfds: c_int,
@@ -205,7 +209,8 @@ pub unsafe extern "C" fn select(
None
} else {
Some(unsafe { &mut *timeout })
}
},
core::ptr::null(),
),
"select({}, {:p}, {:p}, {:p}, {:p})",
nfds,
@@ -215,3 +220,54 @@ pub unsafe extern "C" fn select(
timeout
)
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pselect.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn pselect(
nfds: c_int,
readfds: *mut fd_set,
writefds: *mut fd_set,
exceptfds: *mut fd_set,
timeout: *const timespec,
sigmask: *const sigset_t,
) -> c_int {
let mut micro_timeout = if timeout.is_null() {
None
} else {
unsafe {
Some(timeval {
tv_sec: (*timeout).tv_sec,
tv_usec: ((*timeout).tv_nsec / 1000) as suseconds_t,
})
}
};
trace_expr!(
select_epoll(
nfds,
if readfds.is_null() {
None
} else {
Some(unsafe { &mut *readfds })
},
if writefds.is_null() {
None
} else {
Some(unsafe { &mut *writefds })
},
if exceptfds.is_null() {
None
} else {
Some(unsafe { &mut *exceptfds })
},
micro_timeout.as_mut(),
sigmask
),
"pselect({}, {:p}, {:p}, {:p}, {:p}, {:p})",
nfds,
readfds,
writefds,
exceptfds,
timeout,
sigmask,
)
}