use core::ffi::c_int;
use ax_errno::LinuxError;
use ax_hal::time::wall_time;
use crate::{ctypes, imp::fd_ops::get_file_like};
#[cfg(feature = "use-hermit-types")]
const POLLIN_EVENT: i16 = ctypes::POLLIN;
#[cfg(not(feature = "use-hermit-types"))]
const POLLIN_EVENT: i16 = ctypes::POLLIN as i16;
#[cfg(feature = "use-hermit-types")]
const POLLOUT_EVENT: i16 = ctypes::POLLOUT;
#[cfg(not(feature = "use-hermit-types"))]
const POLLOUT_EVENT: i16 = ctypes::POLLOUT as i16;
#[cfg(feature = "use-hermit-types")]
const POLLERR_EVENT: i16 = ctypes::POLLERR;
#[cfg(not(feature = "use-hermit-types"))]
const POLLERR_EVENT: i16 = ctypes::POLLERR as i16;
#[cfg(feature = "use-hermit-types")]
const POLLNVAL_EVENT: i16 = ctypes::POLLNVAL;
#[cfg(not(feature = "use-hermit-types"))]
const POLLNVAL_EVENT: i16 = ctypes::POLLNVAL as i16;
pub fn sys_poll(fds: *mut ctypes::pollfd, nfds: ctypes::nfds_t, timeout: c_int) -> c_int {
debug!(
"sys_poll <= fds:{:#x} nfds:{} timeout:{}",
fds as usize, nfds, timeout
);
syscall_body!(sys_poll, {
if fds.is_null() && nfds > 0 {
return Err(LinuxError::EFAULT);
}
let fds_slice = if nfds > 0 {
unsafe { core::slice::from_raw_parts_mut(fds, nfds as _) }
} else {
&mut []
};
for pfd in fds_slice.iter_mut() {
pfd.revents = 0;
}
let deadline = if timeout < 0 {
None } else if timeout == 0 {
Some(wall_time()) } else {
Some(wall_time() + core::time::Duration::from_millis(timeout as u64))
};
loop {
#[cfg(feature = "net")]
ax_net::poll_interfaces();
let mut ready_count: usize = 0;
for pfd in fds_slice.iter_mut() {
if pfd.fd < 0 {
continue;
}
match get_file_like(pfd.fd) {
Ok(file) => match file.poll() {
Ok(state) => {
let mut revents = 0;
if state.readable && (pfd.events & POLLIN_EVENT) != 0 {
revents |= POLLIN_EVENT;
}
if state.writable && (pfd.events & POLLOUT_EVENT) != 0 {
revents |= POLLOUT_EVENT;
}
if revents != 0 {
pfd.revents = revents;
ready_count += 1;
}
}
Err(_) => {
pfd.revents = POLLERR_EVENT;
ready_count += 1;
}
},
Err(_) => {
pfd.revents = POLLNVAL_EVENT;
ready_count += 1;
}
}
}
if ready_count > 0 {
return Ok(ready_count);
}
if deadline.is_some_and(|ddl| wall_time() >= ddl) {
debug!(" poll timeout!");
return Ok(0);
}
crate::sys_sched_yield();
}
})
}