rustix/backend/linux_raw/event/
syscalls.rs
1#![allow(unsafe_code, clippy::undocumented_unsafe_blocks)]
7
8use crate::backend::c;
9use crate::backend::conv::{
10 by_ref, c_int, c_uint, ret, ret_c_int, ret_error, ret_owned_fd, ret_usize, slice_mut, zero,
11};
12use crate::event::{epoll, EventfdFlags, FdSetElement, PollFd};
13use crate::fd::{BorrowedFd, OwnedFd};
14use crate::io;
15use crate::utils::as_mut_ptr;
16#[cfg(feature = "alloc")]
17use core::mem::MaybeUninit;
18use core::ptr::null_mut;
19use linux_raw_sys::general::{EPOLL_CTL_ADD, EPOLL_CTL_DEL, EPOLL_CTL_MOD};
20#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
21use {
22 crate::backend::conv::{opt_ref, size_of},
23 linux_raw_sys::general::{__kernel_timespec, kernel_sigset_t},
24};
25
26#[inline]
27pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result<usize> {
28 let (fds_addr_mut, fds_len) = slice_mut(fds);
29
30 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
31 unsafe {
32 let timeout = if timeout >= 0 {
33 Some(__kernel_timespec {
34 tv_sec: (timeout as i64) / 1000,
35 tv_nsec: (timeout as i64) % 1000 * 1_000_000,
36 })
37 } else {
38 None
39 };
40 ret_usize(syscall!(
41 __NR_ppoll,
42 fds_addr_mut,
43 fds_len,
44 opt_ref(timeout.as_ref()),
45 zero(),
46 size_of::<kernel_sigset_t, _>()
47 ))
48 }
49 #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
50 unsafe {
51 ret_usize(syscall!(__NR_poll, fds_addr_mut, fds_len, c_int(timeout)))
52 }
53}
54
55pub(crate) unsafe fn select(
56 nfds: i32,
57 readfds: Option<&mut [FdSetElement]>,
58 writefds: Option<&mut [FdSetElement]>,
59 exceptfds: Option<&mut [FdSetElement]>,
60 timeout: Option<&crate::timespec::Timespec>,
61) -> io::Result<i32> {
62 let len = crate::event::fd_set_num_elements_for_bitvector(nfds);
63
64 let readfds = match readfds {
65 Some(readfds) => {
66 assert!(readfds.len() >= len);
67 readfds.as_mut_ptr()
68 }
69 None => null_mut(),
70 };
71 let writefds = match writefds {
72 Some(writefds) => {
73 assert!(writefds.len() >= len);
74 writefds.as_mut_ptr()
75 }
76 None => null_mut(),
77 };
78 let exceptfds = match exceptfds {
79 Some(exceptfds) => {
80 assert!(exceptfds.len() >= len);
81 exceptfds.as_mut_ptr()
82 }
83 None => null_mut(),
84 };
85
86 let mut timeout_data;
90 let timeout_ptr = match timeout {
91 Some(timeout) => {
92 timeout_data = *timeout;
93 as_mut_ptr(&mut timeout_data)
94 }
95 None => null_mut(),
96 };
97
98 #[cfg(any(
99 target_arch = "arm",
100 target_arch = "powerpc",
101 target_arch = "sparc",
102 target_arch = "csky",
103 target_arch = "x86",
104 target_arch = "mips32r6",
105 target_arch = "riscv32",
106 target_arch = "mips"
107 ))]
108 {
109 ret_c_int(syscall!(
110 __NR_pselect6_time64,
111 c_int(nfds),
112 readfds,
113 writefds,
114 exceptfds,
115 timeout_ptr,
116 zero()
117 ))
118 }
119
120 #[cfg(target_pointer_width = "64")]
121 {
122 ret_c_int(syscall!(
123 __NR_pselect6,
124 c_int(nfds),
125 readfds,
126 writefds,
127 exceptfds,
128 timeout_ptr,
129 zero()
130 ))
131 }
132}
133
134#[inline]
135pub(crate) fn epoll_create(flags: epoll::CreateFlags) -> io::Result<OwnedFd> {
136 unsafe { ret_owned_fd(syscall_readonly!(__NR_epoll_create1, flags)) }
138}
139
140#[inline]
141pub(crate) fn epoll_add(
142 epfd: BorrowedFd<'_>,
143 fd: BorrowedFd<'_>,
144 event: &epoll::Event,
145) -> io::Result<()> {
146 unsafe {
149 ret(syscall_readonly!(
150 __NR_epoll_ctl,
151 epfd,
152 c_uint(EPOLL_CTL_ADD),
153 fd,
154 by_ref(event)
155 ))
156 }
157}
158
159#[inline]
160pub(crate) fn epoll_mod(
161 epfd: BorrowedFd<'_>,
162 fd: BorrowedFd<'_>,
163 event: &epoll::Event,
164) -> io::Result<()> {
165 unsafe {
168 ret(syscall_readonly!(
169 __NR_epoll_ctl,
170 epfd,
171 c_uint(EPOLL_CTL_MOD),
172 fd,
173 by_ref(event)
174 ))
175 }
176}
177
178#[inline]
179pub(crate) fn epoll_del(epfd: BorrowedFd<'_>, fd: BorrowedFd<'_>) -> io::Result<()> {
180 unsafe {
183 ret(syscall_readonly!(
184 __NR_epoll_ctl,
185 epfd,
186 c_uint(EPOLL_CTL_DEL),
187 fd,
188 zero()
189 ))
190 }
191}
192
193#[cfg(feature = "alloc")]
194#[inline]
195pub(crate) fn epoll_wait(
196 epfd: BorrowedFd<'_>,
197 events: &mut [MaybeUninit<crate::event::epoll::Event>],
198 timeout: c::c_int,
199) -> io::Result<usize> {
200 let (buf_addr_mut, buf_len) = slice_mut(events);
201 #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
204 unsafe {
205 ret_usize(syscall!(
206 __NR_epoll_wait,
207 epfd,
208 buf_addr_mut,
209 buf_len,
210 c_int(timeout)
211 ))
212 }
213 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
216 unsafe {
217 ret_usize(syscall!(
218 __NR_epoll_pwait,
219 epfd,
220 buf_addr_mut,
221 buf_len,
222 c_int(timeout),
223 zero()
224 ))
225 }
226}
227
228#[inline]
229pub(crate) fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result<OwnedFd> {
230 unsafe { ret_owned_fd(syscall_readonly!(__NR_eventfd2, c_uint(initval), flags)) }
231}
232
233#[inline]
234pub(crate) fn pause() {
235 unsafe {
236 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
237 let error = ret_error(syscall_readonly!(
238 __NR_ppoll,
239 zero(),
240 zero(),
241 zero(),
242 zero()
243 ));
244
245 #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
246 let error = ret_error(syscall_readonly!(__NR_pause));
247
248 debug_assert_eq!(error, io::Errno::INTR);
249 }
250}