1use core::{mem, ptr, slice};
6
7use crate::{
8 error::Errno,
9 fs::File,
10 header::{
11 bits_sigset_t::sigset_t,
12 errno::{EBADF, EINTR},
13 sys_epoll::{
14 EPOLL_CLOEXEC, EPOLL_CTL_ADD, EPOLLERR, EPOLLHUP, EPOLLIN, EPOLLNVAL, EPOLLOUT,
15 EPOLLPRI, EPOLLRDBAND, EPOLLRDNORM, EPOLLWRBAND, EPOLLWRNORM, epoll_data, epoll_event,
16 },
17 time::timespec,
18 },
19 platform::{
20 ERRNO, PalEpoll, Sys,
21 types::{c_int, c_short, c_ulong},
22 },
23};
24
25pub const POLLIN: c_short = 0x001;
27pub const POLLPRI: c_short = 0x002;
29pub const POLLOUT: c_short = 0x004;
31pub const POLLERR: c_short = 0x008;
33pub const POLLHUP: c_short = 0x010;
35pub const POLLNVAL: c_short = 0x020;
37pub const POLLRDNORM: c_short = 0x040;
39pub const POLLRDBAND: c_short = 0x080;
41pub const POLLWRNORM: c_short = 0x100;
43pub const POLLWRBAND: c_short = 0x200;
45
46#[allow(non_camel_case_types)]
48pub type nfds_t = c_ulong;
49
50#[allow(non_camel_case_types)]
54#[repr(C)]
55pub struct pollfd {
56 pub fd: c_int,
58 pub events: c_short,
60 pub revents: c_short,
62}
63
64#[allow(clippy::needless_update)] pub unsafe fn poll_epoll(fds: &mut [pollfd], timeout: c_int, sigmask: *const sigset_t) -> c_int {
66 let event_map = [
67 (POLLIN, EPOLLIN),
68 (POLLPRI, EPOLLPRI),
69 (POLLOUT, EPOLLOUT),
70 (POLLERR, EPOLLERR),
71 (POLLHUP, EPOLLHUP),
72 (POLLNVAL, EPOLLNVAL),
73 (POLLRDNORM, EPOLLRDNORM),
74 (POLLWRNORM, EPOLLWRNORM),
75 (POLLRDBAND, EPOLLRDBAND),
76 (POLLWRBAND, EPOLLWRBAND),
77 ];
78
79 let ep = {
80 let epfd = match Sys::epoll_create1(EPOLL_CLOEXEC) {
81 Ok(epfd) => epfd,
82 Err(Errno(err)) => {
83 ERRNO.set(err);
84 return -1;
85 }
86 };
87 File::new(epfd)
88 };
89
90 let mut closed = 0;
91 for (i, fd) in fds.iter_mut().enumerate() {
92 let pfd = fd;
93
94 pfd.revents = 0;
95
96 if pfd.fd < 0 {
98 continue;
99 }
100
101 #[expect(clippy::needless_update)]
102 let mut event = epoll_event {
103 events: 0,
104 data: epoll_data { u64: i as u64 },
105 ..Default::default() };
107
108 for (p, ep) in event_map.iter() {
109 if pfd.events & p > 0 {
110 event.events |= ep;
111 }
112 }
113
114 match unsafe { Sys::epoll_ctl(*ep, EPOLL_CTL_ADD, pfd.fd, &raw mut event) } {
115 Ok(()) => {}
116 Err(Errno(EBADF)) => {
117 pfd.revents |= POLLNVAL;
118 closed += 1;
119 }
120 Err(Errno(err)) => {
121 ERRNO.set(err);
122 return -1;
123 }
124 }
125 }
126
127 if closed > 0 && closed == fds.len() {
129 return closed as i32;
130 }
131
132 let mut events: [epoll_event; 32] = unsafe { mem::zeroed() };
133 match unsafe {
134 Sys::epoll_pwait(
135 *ep,
136 events.as_mut_ptr(),
137 events.len() as c_int,
138 timeout,
139 sigmask,
140 )
141 } {
142 Ok(res) => {
143 for event in events.iter().take(res) {
144 let pi = unsafe { event.data.u64 as usize };
145 if let Some(pfd) = fds.get_mut(pi) {
147 for (p, ep) in event_map.iter() {
148 if event.events & ep > 0 {
149 pfd.revents |= p;
150 }
151 }
152 }
153 }
154 }
155 Err(Errno(err)) => {
156 if err == EINTR && closed > 0 {
157 } else {
159 ERRNO.set(err);
160 return -1;
161 }
162 }
163 }
164
165 let mut count = 0;
166 for pfd in fds.iter() {
167 if pfd.revents > 0 {
168 count += 1;
169 }
170 }
171 count
172}
173
174#[unsafe(no_mangle)]
185pub unsafe extern "C" fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int {
186 trace_expr!(
187 unsafe {
188 poll_epoll(
189 slice::from_raw_parts_mut(fds, nfds as usize),
190 timeout,
191 ptr::null_mut(),
192 )
193 },
194 "poll({:p}, {}, {})",
195 fds,
196 nfds,
197 timeout,
198 )
199}
200
201#[unsafe(no_mangle)]
211pub unsafe extern "C" fn ppoll(
212 fds: *mut pollfd,
213 nfds: nfds_t,
214 tmo_p: *const timespec,
215 sigmask: *const sigset_t,
216) -> c_int {
217 let timeout = if tmo_p.is_null() {
218 -1
219 } else {
220 let tmo = unsafe { &*tmo_p };
221 if tmo.tv_sec > (c_int::MAX / 1000).into() {
222 c_int::MAX
223 } else {
224 ((tmo.tv_sec as c_int) * 1000) + ((tmo.tv_nsec as c_int) / 1000000)
225 }
226 };
227 trace_expr!(
228 unsafe {
229 poll_epoll(
230 slice::from_raw_parts_mut(fds, nfds as usize),
231 timeout,
232 sigmask,
233 )
234 },
235 "ppoll({:p}, {}, {:p}, {:p})",
236 fds,
237 nfds,
238 tmo_p,
239 sigmask
240 )
241}