]> git.proxmox.com Git - rustc.git/blob - vendor/rustix-0.37.6/src/backend/libc/io/epoll.rs
New upstream version 1.74.1+dfsg1
[rustc.git] / vendor / rustix-0.37.6 / src / backend / libc / io / epoll.rs
1 //! epoll support.
2 //!
3 //! This is an experiment, and it isn't yet clear whether epoll is the right
4 //! level of abstraction at which to introduce safety. But it works fairly well
5 //! in simple examples 🙂.
6 //!
7 //! # Examples
8 //!
9 //! ```no_run
10 //! # #![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
11 //! # #[cfg(feature = "net")]
12 //! # fn main() -> std::io::Result<()> {
13 //! use io_lifetimes::AsFd;
14 //! use rustix::io::{epoll, ioctl_fionbio, read, write};
15 //! use rustix::net::{
16 //! accept, bind_v4, listen, socket, AddressFamily, Ipv4Addr, Protocol, SocketAddrV4,
17 //! SocketType,
18 //! };
19 //! use std::collections::HashMap;
20 //! use std::os::unix::io::AsRawFd;
21 //!
22 //! // Create a socket and listen on it.
23 //! let listen_sock = socket(AddressFamily::INET, SocketType::STREAM, Protocol::default())?;
24 //! bind_v4(&listen_sock, &SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0))?;
25 //! listen(&listen_sock, 1)?;
26 //!
27 //! // Create an epoll object. Using `Owning` here means the epoll object will
28 //! // take ownership of the file descriptors registered with it.
29 //! let epoll = epoll::epoll_create(epoll::CreateFlags::CLOEXEC)?;
30 //!
31 //! // Register the socket with the epoll object.
32 //! epoll::epoll_add(&epoll, &listen_sock, 1, epoll::EventFlags::IN)?;
33 //!
34 //! // Keep track of the sockets we've opened.
35 //! let mut next_id = 2;
36 //! let mut sockets = HashMap::new();
37 //!
38 //! // Process events.
39 //! let mut event_list = epoll::EventVec::with_capacity(4);
40 //! loop {
41 //! epoll::epoll_wait(&epoll, &mut event_list, -1)?;
42 //! for (_event_flags, target) in &event_list {
43 //! if target == 1 {
44 //! // Accept a new connection, set it to non-blocking, and
45 //! // register to be notified when it's ready to write to.
46 //! let conn_sock = accept(&listen_sock)?;
47 //! ioctl_fionbio(&conn_sock, true)?;
48 //! epoll::epoll_add(
49 //! &epoll,
50 //! &conn_sock,
51 //! next_id,
52 //! epoll::EventFlags::OUT | epoll::EventFlags::ET,
53 //! )?;
54 //!
55 //! // Keep track of the socket.
56 //! sockets.insert(next_id, conn_sock);
57 //! next_id += 1;
58 //! } else {
59 //! // Write a message to the stream and then unregister it.
60 //! let target = sockets.remove(&target).unwrap();
61 //! write(&target, b"hello\n")?;
62 //! let _ = epoll::epoll_del(&epoll, &target)?;
63 //! }
64 //! }
65 //! }
66 //! # }
67 //! # #[cfg(not(feature = "net"))]
68 //! # fn main() {}
69 //! ```
70
71 use super::super::c;
72 use super::super::conv::{ret, ret_owned_fd, ret_u32};
73 use crate::fd::{AsFd, AsRawFd, OwnedFd};
74 use crate::io;
75 use alloc::vec::Vec;
76 use bitflags::bitflags;
77 use core::convert::TryInto;
78 use core::ptr::null_mut;
79
80 bitflags! {
81 /// `EPOLL_*` for use with [`Epoll::new`].
82 pub struct CreateFlags: c::c_int {
83 /// `EPOLL_CLOEXEC`
84 const CLOEXEC = c::EPOLL_CLOEXEC;
85 }
86 }
87
88 bitflags! {
89 /// `EPOLL*` for use with [`Epoll::add`].
90 #[derive(Default)]
91 pub struct EventFlags: u32 {
92 /// `EPOLLIN`
93 const IN = c::EPOLLIN as u32;
94
95 /// `EPOLLOUT`
96 const OUT = c::EPOLLOUT as u32;
97
98 /// `EPOLLPRI`
99 const PRI = c::EPOLLPRI as u32;
100
101 /// `EPOLLERR`
102 const ERR = c::EPOLLERR as u32;
103
104 /// `EPOLLHUP`
105 const HUP = c::EPOLLHUP as u32;
106
107 /// `EPOLLRDNORM`
108 const RDNORM = c::EPOLLRDNORM as u32;
109
110 /// `EPOLLRDBAND`
111 const RDBAND = c::EPOLLRDBAND as u32;
112
113 /// `EPOLLWRNORM`
114 const WRNORM = c::EPOLLWRNORM as u32;
115
116 /// `EPOLLWRBAND`
117 const WRBAND = c::EPOLLWRBAND as u32;
118
119 /// `EPOLLMSG`
120 const MSG = c::EPOLLMSG as u32;
121
122 /// `EPOLLRDHUP`
123 const RDHUP = c::EPOLLRDHUP as u32;
124
125 /// `EPOLLET`
126 const ET = c::EPOLLET as u32;
127
128 /// `EPOLLONESHOT`
129 const ONESHOT = c::EPOLLONESHOT as u32;
130
131 /// `EPOLLWAKEUP`
132 const WAKEUP = c::EPOLLWAKEUP as u32;
133
134 /// `EPOLLEXCLUSIVE`
135 #[cfg(not(target_os = "android"))]
136 const EXCLUSIVE = c::EPOLLEXCLUSIVE as u32;
137 }
138 }
139
140 /// `epoll_create1(flags)`—Creates a new `Epoll`.
141 ///
142 /// Use the [`CreateFlags::CLOEXEC`] flag to prevent the resulting file
143 /// descriptor from being implicitly passed across `exec` boundaries.
144 #[inline]
145 #[doc(alias = "epoll_create1")]
146 pub fn epoll_create(flags: CreateFlags) -> io::Result<OwnedFd> {
147 // SAFETY: We're calling `epoll_create1` via FFI and we know how it
148 // behaves.
149 unsafe { ret_owned_fd(c::epoll_create1(flags.bits())) }
150 }
151
152 /// `epoll_ctl(self, EPOLL_CTL_ADD, data, event)`—Adds an element to an
153 /// `Epoll`.
154 ///
155 /// Note that if `epoll_del` is not called on the I/O source passed into
156 /// this function before the I/O source is `close`d, then the `epoll` will
157 /// act as if the I/O source is still registered with it. This can lead to
158 /// spurious events being returned from `epoll_wait`. If a file descriptor
159 /// is an `Arc<dyn SystemResource>`, then `epoll` can be thought to maintain
160 /// a `Weak<dyn SystemResource>` to the file descriptor.
161 #[doc(alias = "epoll_ctl")]
162 pub fn epoll_add(
163 epoll: impl AsFd,
164 source: impl AsFd,
165 data: u64,
166 event_flags: EventFlags,
167 ) -> io::Result<()> {
168 // SAFETY: We're calling `epoll_ctl` via FFI and we know how it
169 // behaves.
170 unsafe {
171 let raw_fd = source.as_fd().as_raw_fd();
172 ret(c::epoll_ctl(
173 epoll.as_fd().as_raw_fd(),
174 c::EPOLL_CTL_ADD,
175 raw_fd,
176 &mut c::epoll_event {
177 events: event_flags.bits(),
178 r#u64: data,
179 },
180 ))
181 }
182 }
183
184 /// `epoll_ctl(self, EPOLL_CTL_MOD, target, event)`—Modifies an element in
185 /// this `Epoll`.
186 ///
187 /// This sets the events of interest with `target` to `events`.
188 #[doc(alias = "epoll_ctl")]
189 pub fn epoll_mod(
190 epoll: impl AsFd,
191 source: impl AsFd,
192 data: u64,
193 event_flags: EventFlags,
194 ) -> io::Result<()> {
195 let raw_fd = source.as_fd().as_raw_fd();
196
197 // SAFETY: We're calling `epoll_ctl` via FFI and we know how it
198 // behaves.
199 unsafe {
200 ret(c::epoll_ctl(
201 epoll.as_fd().as_raw_fd(),
202 c::EPOLL_CTL_MOD,
203 raw_fd,
204 &mut c::epoll_event {
205 events: event_flags.bits(),
206 r#u64: data,
207 },
208 ))
209 }
210 }
211
212 /// `epoll_ctl(self, EPOLL_CTL_DEL, target, NULL)`—Removes an element in
213 /// this `Epoll`.
214 #[doc(alias = "epoll_ctl")]
215 pub fn epoll_del(epoll: impl AsFd, source: impl AsFd) -> io::Result<()> {
216 // SAFETY: We're calling `epoll_ctl` via FFI and we know how it
217 // behaves.
218 unsafe {
219 let raw_fd = source.as_fd().as_raw_fd();
220 ret(c::epoll_ctl(
221 epoll.as_fd().as_raw_fd(),
222 c::EPOLL_CTL_DEL,
223 raw_fd,
224 null_mut(),
225 ))
226 }
227 }
228
229 /// `epoll_wait(self, events, timeout)`—Waits for registered events of
230 /// interest.
231 ///
232 /// For each event of interest, an element is written to `events`. On
233 /// success, this returns the number of written elements.
234 pub fn epoll_wait(
235 epoll: impl AsFd,
236 event_list: &mut EventVec,
237 timeout: c::c_int,
238 ) -> io::Result<()> {
239 // SAFETY: We're calling `epoll_wait` via FFI and we know how it
240 // behaves.
241 unsafe {
242 event_list.events.set_len(0);
243 let nfds = ret_u32(c::epoll_wait(
244 epoll.as_fd().as_raw_fd(),
245 event_list.events.as_mut_ptr().cast::<c::epoll_event>(),
246 event_list.events.capacity().try_into().unwrap_or(i32::MAX),
247 timeout,
248 ))?;
249 event_list.events.set_len(nfds as usize);
250 }
251
252 Ok(())
253 }
254
255 /// An iterator over the `Event`s in an `EventVec`.
256 pub struct Iter<'a> {
257 iter: core::slice::Iter<'a, Event>,
258 }
259
260 impl<'a> Iterator for Iter<'a> {
261 type Item = (EventFlags, u64);
262
263 fn next(&mut self) -> Option<Self::Item> {
264 // SAFETY: `self.context` is guaranteed to be valid because we hold
265 // `'context` for it. And we know this event is associated with this
266 // context because `wait` sets both.
267 self.iter
268 .next()
269 .map(|event| (event.event_flags, event.data))
270 }
271 }
272
273 /// A record of an event that occurred.
274 #[repr(C)]
275 #[cfg_attr(
276 any(
277 all(
278 target_arch = "x86",
279 not(target_env = "musl"),
280 not(target_os = "android"),
281 ),
282 target_arch = "x86_64",
283 ),
284 repr(packed)
285 )]
286 struct Event {
287 // Match the layout of `c::epoll_event`. We just use a `u64` instead of
288 // the full union.
289 event_flags: EventFlags,
290 data: u64,
291 }
292
293 /// A vector of `Event`s, plus context for interpreting them.
294 pub struct EventVec {
295 events: Vec<Event>,
296 }
297
298 impl EventVec {
299 /// Constructs an `EventVec` with memory for `capacity` `Event`s.
300 #[inline]
301 pub fn with_capacity(capacity: usize) -> Self {
302 Self {
303 events: Vec::with_capacity(capacity),
304 }
305 }
306
307 /// Returns the current `Event` capacity of this `EventVec`.
308 #[inline]
309 pub fn capacity(&self) -> usize {
310 self.events.capacity()
311 }
312
313 /// Reserves enough memory for at least `additional` more `Event`s.
314 #[inline]
315 pub fn reserve(&mut self, additional: usize) {
316 self.events.reserve(additional);
317 }
318
319 /// Reserves enough memory for exactly `additional` more `Event`s.
320 #[inline]
321 pub fn reserve_exact(&mut self, additional: usize) {
322 self.events.reserve_exact(additional);
323 }
324
325 /// Clears all the `Events` out of this `EventVec`.
326 #[inline]
327 pub fn clear(&mut self) {
328 self.events.clear();
329 }
330
331 /// Shrinks the capacity of this `EventVec` as much as possible.
332 #[inline]
333 pub fn shrink_to_fit(&mut self) {
334 self.events.shrink_to_fit();
335 }
336
337 /// Returns an iterator over the `Event`s in this `EventVec`.
338 #[inline]
339 pub fn iter(&self) -> Iter<'_> {
340 Iter {
341 iter: self.events.iter(),
342 }
343 }
344
345 /// Returns the number of `Event`s logically contained in this `EventVec`.
346 #[inline]
347 pub fn len(&mut self) -> usize {
348 self.events.len()
349 }
350
351 /// Tests whether this `EventVec` is logically empty.
352 #[inline]
353 pub fn is_empty(&mut self) -> bool {
354 self.events.is_empty()
355 }
356 }
357
358 impl<'a> IntoIterator for &'a EventVec {
359 type IntoIter = Iter<'a>;
360 type Item = (EventFlags, u64);
361
362 #[inline]
363 fn into_iter(self) -> Self::IntoIter {
364 self.iter()
365 }
366 }