1use crate::errno::Errno;
2pub use crate::poll_timeout::PollTimeout as EpollTimeout;
3pub use crate::poll_timeout::PollTimeoutTryFromError as EpollTimeoutTryFromError;
4use crate::Result;
5use libc::{self, c_int};
6use std::mem;
7use std::os::unix::io::{AsFd, AsRawFd, FromRawFd, OwnedFd, RawFd};
8
9libc_bitflags!(
10 pub struct EpollFlags: c_int {
11 EPOLLIN;
12 EPOLLPRI;
13 EPOLLOUT;
14 EPOLLRDNORM;
15 EPOLLRDBAND;
16 EPOLLWRNORM;
17 EPOLLWRBAND;
18 EPOLLMSG;
19 EPOLLERR;
20 EPOLLHUP;
21 EPOLLRDHUP;
22 EPOLLEXCLUSIVE;
23 #[cfg(not(target_arch = "mips"))]
24 EPOLLWAKEUP;
25 EPOLLONESHOT;
26 EPOLLET;
27 }
28);
29
30#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
31#[repr(i32)]
32#[non_exhaustive]
33pub enum EpollOp {
34 EpollCtlAdd = libc::EPOLL_CTL_ADD,
35 EpollCtlDel = libc::EPOLL_CTL_DEL,
36 EpollCtlMod = libc::EPOLL_CTL_MOD,
37}
38
39libc_bitflags! {
40 pub struct EpollCreateFlags: c_int {
41 EPOLL_CLOEXEC;
42 }
43}
44
45#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
46#[repr(transparent)]
47pub struct EpollEvent {
48 event: libc::epoll_event,
49}
50
51impl EpollEvent {
52 pub fn new(events: EpollFlags, data: u64) -> Self {
53 EpollEvent {
54 event: libc::epoll_event {
55 events: events.bits() as u32,
56 u64: data,
57 },
58 }
59 }
60
61 pub fn empty() -> Self {
62 unsafe { mem::zeroed::<EpollEvent>() }
63 }
64
65 pub fn events(&self) -> EpollFlags {
66 EpollFlags::from_bits(self.event.events as c_int).unwrap()
67 }
68
69 pub fn data(&self) -> u64 {
70 self.event.u64
71 }
72}
73
74#[derive(Debug)]
106pub struct Epoll(pub OwnedFd);
107impl Epoll {
108 pub fn new(flags: EpollCreateFlags) -> Result<Self> {
112 let res = unsafe { libc::epoll_create1(flags.bits()) };
113 let fd = Errno::result(res)?;
114 let owned_fd = unsafe { OwnedFd::from_raw_fd(fd) };
115 Ok(Self(owned_fd))
116 }
117 pub fn add<Fd: AsFd>(&self, fd: Fd, mut event: EpollEvent) -> Result<()> {
122 self.epoll_ctl(EpollOp::EpollCtlAdd, fd, &mut event)
123 }
124 pub fn delete<Fd: AsFd>(&self, fd: Fd) -> Result<()> {
128 self.epoll_ctl(EpollOp::EpollCtlDel, fd, None)
129 }
130 pub fn modify<Fd: AsFd>(
135 &self,
136 fd: Fd,
137 event: &mut EpollEvent,
138 ) -> Result<()> {
139 self.epoll_ctl(EpollOp::EpollCtlMod, fd, event)
140 }
141 pub fn wait<T: Into<EpollTimeout>>(
146 &self,
147 events: &mut [EpollEvent],
148 timeout: T,
149 ) -> Result<usize> {
150 let res = unsafe {
151 libc::epoll_wait(
152 self.0.as_raw_fd(),
153 events.as_mut_ptr().cast(),
154 events.len() as c_int,
155 timeout.into().into(),
156 )
157 };
158
159 Errno::result(res).map(|r| r as usize)
160 }
161 fn epoll_ctl<'a, Fd: AsFd, T>(
169 &self,
170 op: EpollOp,
171 fd: Fd,
172 event: T,
173 ) -> Result<()>
174 where
175 T: Into<Option<&'a mut EpollEvent>>,
176 {
177 let event: Option<&mut EpollEvent> = event.into();
178 let ptr = event
179 .map(|x| &mut x.event as *mut libc::epoll_event)
180 .unwrap_or(std::ptr::null_mut());
181 unsafe {
182 Errno::result(libc::epoll_ctl(
183 self.0.as_raw_fd(),
184 op as c_int,
185 fd.as_fd().as_raw_fd(),
186 ptr,
187 ))
188 .map(drop)
189 }
190 }
191}
192
193#[deprecated(since = "0.27.0", note = "Use Epoll::new() instead")]
194#[inline]
195pub fn epoll_create() -> Result<RawFd> {
196 let res = unsafe { libc::epoll_create(1024) };
197
198 Errno::result(res)
199}
200
201#[deprecated(since = "0.27.0", note = "Use Epoll::new() instead")]
202#[inline]
203pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> {
204 let res = unsafe { libc::epoll_create1(flags.bits()) };
205
206 Errno::result(res)
207}
208
209#[deprecated(
210 since = "0.27.0",
211 note = "Use corresponding Epoll methods instead"
212)]
213#[inline]
214pub fn epoll_ctl<'a, T>(
215 epfd: RawFd,
216 op: EpollOp,
217 fd: RawFd,
218 event: T,
219) -> Result<()>
220where
221 T: Into<Option<&'a mut EpollEvent>>,
222{
223 let mut event: Option<&mut EpollEvent> = event.into();
224 if event.is_none() && op != EpollOp::EpollCtlDel {
225 Err(Errno::EINVAL)
226 } else {
227 let res = unsafe {
228 if let Some(ref mut event) = event {
229 libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event)
230 } else {
231 libc::epoll_ctl(epfd, op as c_int, fd, std::ptr::null_mut())
232 }
233 };
234 Errno::result(res).map(drop)
235 }
236}
237
238#[deprecated(since = "0.27.0", note = "Use Epoll::wait() instead")]
239#[inline]
240pub fn epoll_wait(
241 epfd: RawFd,
242 events: &mut [EpollEvent],
243 timeout_ms: isize,
244) -> Result<usize> {
245 let res = unsafe {
246 libc::epoll_wait(
247 epfd,
248 events.as_mut_ptr().cast(),
249 events.len() as c_int,
250 timeout_ms as c_int,
251 )
252 };
253
254 Errno::result(res).map(|r| r as usize)
255}