1//! linux_raw syscalls supporting `rustix::event`.
2//!
3//! # Safety
4//!
5//! See the `rustix::backend` module documentation for details.
6#![allow(unsafe_code, clippy::undocumented_unsafe_blocks)]
7
8use crate::backend::c;
9#[cfg(feature = "alloc")]
10use crate::backend::conv::pass_usize;
11use crate::backend::conv::{
12 by_ref, c_int, c_uint, raw_fd, ret, ret_error, ret_owned_fd, ret_usize, slice_mut, zero,
13};
14use crate::event::{epoll, EventfdFlags, PollFd};
15use crate::fd::{BorrowedFd, OwnedFd};
16use crate::io;
17use linux_raw_sys::general::{EPOLL_CTL_ADD, EPOLL_CTL_DEL, EPOLL_CTL_MOD};
18#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
19use {
20 crate::backend::conv::{opt_ref, size_of},
21 linux_raw_sys::general::{__kernel_timespec, kernel_sigset_t},
22};
23
24#[inline]
25pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result<usize> {
26 let (fds_addr_mut, fds_len) = slice_mut(fds);
27
28 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
29 unsafe {
30 let timeout = if timeout >= 0 {
31 Some(__kernel_timespec {
32 tv_sec: (timeout as i64) / 1000,
33 tv_nsec: (timeout as i64) % 1000 * 1_000_000,
34 })
35 } else {
36 None
37 };
38 ret_usize(syscall!(
39 __NR_ppoll,
40 fds_addr_mut,
41 fds_len,
42 opt_ref(timeout.as_ref()),
43 zero(),
44 size_of::<kernel_sigset_t, _>()
45 ))
46 }
47 #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
48 unsafe {
49 ret_usize(syscall!(__NR_poll, fds_addr_mut, fds_len, c_int(timeout)))
50 }
51}
52
53#[inline]
54pub(crate) fn epoll_create(flags: epoll::CreateFlags) -> io::Result<OwnedFd> {
55 unsafe { ret_owned_fd(raw:syscall_readonly!(__NR_epoll_create1, flags)) }
56}
57
58#[inline]
59pub(crate) unsafe fn epoll_add(
60 epfd: BorrowedFd<'_>,
61 fd: c::c_int,
62 event: &epoll::Event,
63) -> io::Result<()> {
64 ret(raw:syscall_readonly!(
65 __NR_epoll_ctl,
66 epfd,
67 c_uint(EPOLL_CTL_ADD),
68 raw_fd(fd),
69 by_ref(event)
70 ))
71}
72
73#[inline]
74pub(crate) unsafe fn epoll_mod(
75 epfd: BorrowedFd<'_>,
76 fd: c::c_int,
77 event: &epoll::Event,
78) -> io::Result<()> {
79 ret(raw:syscall_readonly!(
80 __NR_epoll_ctl,
81 epfd,
82 c_uint(EPOLL_CTL_MOD),
83 raw_fd(fd),
84 by_ref(event)
85 ))
86}
87
88#[inline]
89pub(crate) unsafe fn epoll_del(epfd: BorrowedFd<'_>, fd: c::c_int) -> io::Result<()> {
90 ret(raw:syscall_readonly!(
91 __NR_epoll_ctl,
92 epfd,
93 c_uint(EPOLL_CTL_DEL),
94 raw_fd(fd),
95 zero()
96 ))
97}
98
99#[cfg(feature = "alloc")]
100#[inline]
101pub(crate) fn epoll_wait(
102 epfd: BorrowedFd<'_>,
103 events: *mut epoll::Event,
104 num_events: usize,
105 timeout: c::c_int,
106) -> io::Result<usize> {
107 #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
108 unsafe {
109 ret_usize(raw:syscall!(
110 __NR_epoll_wait,
111 epfd,
112 events,
113 pass_usize(num_events),
114 c_int(timeout)
115 ))
116 }
117 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
118 unsafe {
119 ret_usize(syscall!(
120 __NR_epoll_pwait,
121 epfd,
122 events,
123 pass_usize(num_events),
124 c_int(timeout),
125 zero()
126 ))
127 }
128}
129
130#[inline]
131pub(crate) fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result<OwnedFd> {
132 unsafe { ret_owned_fd(raw:syscall_readonly!(__NR_eventfd2, c_uint(initval), flags)) }
133}
134
135#[inline]
136pub(crate) fn pause() {
137 unsafe {
138 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
139 let error = ret_error(syscall_readonly!(
140 __NR_ppoll,
141 zero(),
142 zero(),
143 zero(),
144 zero()
145 ));
146
147 #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
148 let error: Errno = ret_error(raw:syscall_readonly!(__NR_pause));
149
150 debug_assert_eq!(error, io::Errno::INTR);
151 }
152}
153