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