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 ] |
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 ] |
54 | pub(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 ] |
59 | pub(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 ] |
74 | pub(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 ] |
89 | pub(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 ] |
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(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 ] |
131 | pub(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 ] |
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: Errno = ret_error(raw:syscall_readonly!(__NR_pause)); |
149 | |
150 | debug_assert_eq!(error, io::Errno::INTR); |
151 | } |
152 | } |
153 | |