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 
8 use crate::backend::c;
9 #[cfg(feature = "alloc")]
10 use crate::backend::conv::pass_usize;
11 use crate::backend::conv::{
12     by_ref, c_int, c_uint, raw_fd, ret, ret_error, ret_owned_fd, ret_usize, slice_mut, zero,
13 };
14 use crate::event::{epoll, EventfdFlags, PollFd};
15 use crate::fd::{BorrowedFd, OwnedFd};
16 use crate::io;
17 use linux_raw_sys::general::{EPOLL_CTL_ADD, EPOLL_CTL_DEL, EPOLL_CTL_MOD};
18 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
19 use {
20     crate::backend::conv::{opt_ref, size_of},
21     linux_raw_sys::general::{__kernel_timespec, kernel_sigset_t},
22 };
23 
24 #[inline]
poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result<usize>25 pub(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]
epoll_create(flags: epoll::CreateFlags) -> io::Result<OwnedFd>54 pub(crate) fn epoll_create(flags: epoll::CreateFlags) -> io::Result<OwnedFd> {
55     unsafe { ret_owned_fd(syscall_readonly!(__NR_epoll_create1, flags)) }
56 }
57 
58 #[inline]
epoll_add( epfd: BorrowedFd<'_>, fd: c::c_int, event: &epoll::Event, ) -> io::Result<()>59 pub(crate) unsafe fn epoll_add(
60     epfd: BorrowedFd<'_>,
61     fd: c::c_int,
62     event: &epoll::Event,
63 ) -> io::Result<()> {
64     ret(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]
epoll_mod( epfd: BorrowedFd<'_>, fd: c::c_int, event: &epoll::Event, ) -> io::Result<()>74 pub(crate) unsafe fn epoll_mod(
75     epfd: BorrowedFd<'_>,
76     fd: c::c_int,
77     event: &epoll::Event,
78 ) -> io::Result<()> {
79     ret(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]
epoll_del(epfd: BorrowedFd<'_>, fd: c::c_int) -> io::Result<()>89 pub(crate) unsafe fn epoll_del(epfd: BorrowedFd<'_>, fd: c::c_int) -> io::Result<()> {
90     ret(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]
epoll_wait( epfd: BorrowedFd<'_>, events: *mut epoll::Event, num_events: usize, timeout: c::c_int, ) -> io::Result<usize>101 pub(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(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]
eventfd(initval: u32, flags: EventfdFlags) -> io::Result<OwnedFd>131 pub(crate) fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result<OwnedFd> {
132     unsafe { ret_owned_fd(syscall_readonly!(__NR_eventfd2, c_uint(initval), flags)) }
133 }
134 
135 #[inline]
pause()136 pub(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 = ret_error(syscall_readonly!(__NR_pause));
149 
150         debug_assert_eq!(error, io::Errno::INTR);
151     }
152 }
153