//! libc syscalls supporting `rustix::event`. use crate::backend::c; use crate::backend::conv::ret_c_int; #[cfg(any(apple, netbsdlike, target_os = "dragonfly", target_os = "solaris"))] use crate::backend::conv::ret_owned_fd; use crate::event::PollFd; #[cfg(any(linux_kernel, bsd, solarish, target_os = "espidf"))] use crate::fd::OwnedFd; use crate::io; #[cfg(any(bsd, solarish))] use {crate::backend::conv::borrowed_fd, crate::fd::BorrowedFd, core::mem::MaybeUninit}; #[cfg(solarish)] use { crate::backend::conv::ret, crate::event::port::Event, crate::utils::as_mut_ptr, core::ptr::null_mut, }; #[cfg(any( linux_kernel, target_os = "freebsd", target_os = "illumos", target_os = "espidf" ))] use {crate::backend::conv::ret_owned_fd, crate::event::EventfdFlags}; #[cfg(all(feature = "alloc", bsd))] use {crate::event::kqueue::Event, crate::utils::as_ptr, core::ptr::null}; #[cfg(any( linux_kernel, target_os = "freebsd", target_os = "illumos", target_os = "espidf" ))] pub(crate) fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result { #[cfg(linux_kernel)] unsafe { syscall! { fn eventfd2( initval: c::c_uint, flags: c::c_int ) via SYS_eventfd2 -> c::c_int } ret_owned_fd(eventfd2(initval, bitflags_bits!(flags))) } // `eventfd` was added in FreeBSD 13, so it isn't available on FreeBSD 12. #[cfg(target_os = "freebsd")] unsafe { weakcall! { fn eventfd( initval: c::c_uint, flags: c::c_int ) -> c::c_int } ret_owned_fd(eventfd(initval, bitflags_bits!(flags))) } #[cfg(any(target_os = "illumos", target_os = "espidf"))] unsafe { ret_owned_fd(c::eventfd(initval, bitflags_bits!(flags))) } } #[cfg(all(feature = "alloc", bsd))] pub(crate) fn kqueue() -> io::Result { unsafe { ret_owned_fd(c::kqueue()) } } #[cfg(all(feature = "alloc", bsd))] pub(crate) unsafe fn kevent( kq: BorrowedFd<'_>, changelist: &[Event], eventlist: &mut [MaybeUninit], timeout: Option<&c::timespec>, ) -> io::Result { ret_c_int(c::kevent( borrowed_fd(kq), changelist.as_ptr().cast(), changelist .len() .try_into() .map_err(|_| io::Errno::OVERFLOW)?, eventlist.as_mut_ptr().cast(), eventlist .len() .try_into() .map_err(|_| io::Errno::OVERFLOW)?, timeout.map_or(null(), as_ptr), )) } #[inline] pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result { let nfds = fds .len() .try_into() .map_err(|_convert_err| io::Errno::INVAL)?; ret_c_int(unsafe { c::poll(fds.as_mut_ptr().cast(), nfds, timeout) }) .map(|nready| nready as usize) } #[cfg(solarish)] pub(crate) fn port_create() -> io::Result { unsafe { ret_owned_fd(c::port_create()) } } #[cfg(solarish)] pub(crate) unsafe fn port_associate( port: BorrowedFd<'_>, source: c::c_int, object: c::uintptr_t, events: c::c_int, user: *mut c::c_void, ) -> io::Result<()> { ret(c::port_associate( borrowed_fd(port), source, object, events, user, )) } #[cfg(solarish)] pub(crate) unsafe fn port_dissociate( port: BorrowedFd<'_>, source: c::c_int, object: c::uintptr_t, ) -> io::Result<()> { ret(c::port_dissociate(borrowed_fd(port), source, object)) } #[cfg(solarish)] pub(crate) fn port_get( port: BorrowedFd<'_>, timeout: Option<&mut c::timespec>, ) -> io::Result { let mut event = MaybeUninit::::uninit(); let timeout = timeout.map_or(null_mut(), as_mut_ptr); unsafe { ret(c::port_get(borrowed_fd(port), event.as_mut_ptr(), timeout))?; } // If we're done, initialize the event and return it. Ok(Event(unsafe { event.assume_init() })) } #[cfg(all(feature = "alloc", solarish))] pub(crate) fn port_getn( port: BorrowedFd<'_>, timeout: Option<&mut c::timespec>, events: &mut Vec, mut nget: u32, ) -> io::Result<()> { let timeout = timeout.map_or(null_mut(), as_mut_ptr); unsafe { ret(c::port_getn( borrowed_fd(port), events.as_mut_ptr().cast(), events.len().try_into().unwrap(), &mut nget, timeout, ))?; } // Update the vector length. unsafe { events.set_len(nget.try_into().unwrap()); } Ok(()) } #[cfg(solarish)] pub(crate) fn port_send( port: BorrowedFd<'_>, events: c::c_int, userdata: *mut c::c_void, ) -> io::Result<()> { unsafe { ret(c::port_send(borrowed_fd(port), events, userdata)) } } #[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))] pub(crate) fn pause() { let r = unsafe { libc::pause() }; let errno = libc_errno::errno().0; debug_assert_eq!(r, -1); debug_assert_eq!(errno, libc::EINTR); }