relibc/header/sys_epoll/mod.rs
1//! `sys/epoll.h` implementation.
2//!
3//! Non-POSIX, see <http://man7.org/linux/man-pages/man7/epoll.7.html>.
4
5use core::ptr;
6
7use crate::{
8 error::ResultExt,
9 header::bits_sigset_t::sigset_t,
10 platform::{
11 PalEpoll, Sys,
12 types::{c_int, c_uint, c_ulonglong, c_void},
13 },
14};
15
16/// Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor.
17#[cfg(target_os = "linux")]
18pub const EPOLL_CLOEXEC: c_int = 0x8_0000;
19
20/// Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor.
21#[cfg(target_os = "redox")]
22pub const EPOLL_CLOEXEC: c_int = 0x0100_0000;
23
24/// The associated file is available for read operations.
25pub const EPOLLIN: c_uint = 0x001;
26/// There is an exceptional condition on the file descriptor.
27pub const EPOLLPRI: c_uint = 0x002;
28/// The associated file is available for write operations.
29pub const EPOLLOUT: c_uint = 0x004;
30/// Error condition happened on the associated file descriptor.
31pub const EPOLLERR: c_uint = 0x008;
32/// Hang up happened onthe associated file descriptor.
33pub const EPOLLHUP: c_uint = 0x010;
34pub const EPOLLNVAL: c_uint = 0x020;
35pub const EPOLLRDNORM: c_uint = 0x040;
36pub const EPOLLRDBAND: c_uint = 0x080;
37pub const EPOLLWRNORM: c_uint = 0x100;
38pub const EPOLLWRBAND: c_uint = 0x200;
39pub const EPOLLMSG: c_uint = 0x400;
40/// Stream socket peer closed connection, or shut down writing half of
41/// connection.
42pub const EPOLLRDHUP: c_uint = 0x2000;
43/// Sets an exclusive wakeup mode for the epoll file descriptor that is being
44/// attached to the target file descriptor, `fd`.
45pub const EPOLLEXCLUSIVE: c_uint = 1 << 28;
46/// If `EPOLLONESHOT` and `EPOLLET` are clear and the process has the
47/// `CAP_BLOCK_SUSPEND` capability, ensure that the system does not enter
48/// "suspend" or "hibernate" while this event is pending or being processed.
49pub const EPOLLWAKEUP: c_uint = 1 << 29;
50/// Requests one-shot notification for the associated file descriptor.
51pub const EPOLLONESHOT: c_uint = 1 << 30;
52/// Requests edge-triggered notification for the associated file descriptor.
53pub const EPOLLET: c_uint = 1 << 31;
54
55/// Add an entry to the interest list of the epoll file descriptor, `epfd`.
56pub const EPOLL_CTL_ADD: c_int = 1;
57/// Remove (deregister) the target file descriptor `fd` from the interest list.
58pub const EPOLL_CTL_DEL: c_int = 2;
59/// Change the settings associated with `fd` in the interest list to the new
60/// settings specified in `event`.
61pub const EPOLL_CTL_MOD: c_int = 3;
62
63/// Non-POSIX, see <https://man7.org/linux/man-pages/man3/epoll_event.3type.html>.
64#[repr(C)]
65#[derive(Clone, Copy)]
66pub union epoll_data {
67 pub ptr: *mut c_void,
68 pub fd: c_int,
69 pub u32: c_uint,
70 pub u64: c_ulonglong,
71}
72impl Default for epoll_data {
73 fn default() -> Self {
74 Self { u64: 0 }
75 }
76}
77
78/// Non-POSIX, see <https://man7.org/linux/man-pages/man3/epoll_event.3type.html>.
79///
80/// Specifies data that the kernel should save and return when the
81/// corresponding file descriptor becomes ready.
82#[cfg(all(target_os = "redox", target_pointer_width = "64"))]
83#[repr(C)]
84#[derive(Clone, Copy, Default)]
85// This will match in size with syscall::Event (24 bytes on 64-bit
86// systems) on redox. The `Default` trait is here so we don't need to
87// worry about the padding when using this type.
88pub struct epoll_event {
89 /// Epoll events.
90 pub events: c_uint, // 4 bytes
91 // 4 automatic alignment bytes
92 /// User data variable.
93 pub data: epoll_data, // 8 bytes
94
95 pub _pad: c_ulonglong, // 8 bytes
96}
97
98/// Non-POSIX, see <https://man7.org/linux/man-pages/man3/epoll_event.3type.html>.
99///
100/// Specifies data that the kernel should save and return when the
101/// corresponding file descriptor becomes ready.
102#[cfg(not(all(target_os = "redox", target_pointer_width = "64")))]
103#[repr(C)]
104#[derive(Clone, Copy, Default)]
105pub struct epoll_event {
106 /// Epoll events.
107 pub events: c_uint,
108 /// User data variable.
109 pub data: epoll_data,
110}
111
112/// Non-POSIX, see <https://man7.org/linux/man-pages/man2/epoll_create.2.html>.
113///
114/// Creates a file descriptor referring to the new epoll instance.
115///
116/// Upon success, returns a file descriptor (a nonnegative integer). Upon
117/// error, `-1` is returned and errno set to indicate the error.
118///
119/// # Implementation
120/// The `_size` parameter is deliberately unused as it is no longer required.
121/// This function simply calls `epoll_create1`.
122#[unsafe(no_mangle)]
123pub extern "C" fn epoll_create(_size: c_int) -> c_int {
124 epoll_create1(0)
125}
126
127/// Non-POSIX, see <https://man7.org/linux/man-pages/man2/epoll_create1.2.html>.
128///
129/// Creates a file descriptor referring to the new epoll instance.
130///
131/// Upon success, returns a file descriptor (a nonnegative integer). Upon
132/// error, `-1` is returned and errno set to indicate the error.
133#[unsafe(no_mangle)]
134pub extern "C" fn epoll_create1(flags: c_int) -> c_int {
135 trace_expr!(
136 Sys::epoll_create1(flags).or_minus_one_errno(),
137 "epoll_create1({:#x})",
138 flags
139 )
140}
141
142/// Non-POSIX, see <https://man7.org/linux/man-pages/man2/epoll_ctl.2.html>.
143///
144/// Add, modify, or remove entries in the interest list of the epoll instance
145/// referred to by the file descriptor `epfd`.
146///
147/// Upon success, returns `0`. Upon error, returns `-1` and sets errno to
148/// indicate the error.
149#[unsafe(no_mangle)]
150pub unsafe extern "C" fn epoll_ctl(
151 epfd: c_int,
152 op: c_int,
153 fd: c_int,
154 event: *mut epoll_event,
155) -> c_int {
156 trace_expr!(
157 unsafe { Sys::epoll_ctl(epfd, op, fd, event) }
158 .map(|()| 0)
159 .or_minus_one_errno(),
160 "epoll_ctl({}, {}, {}, {:p})",
161 epfd,
162 op,
163 fd,
164 event
165 )
166}
167
168/// Non-POSIX, see <https://man7.org/linux/man-pages/man2/epoll_wait.2.html>.
169///
170/// Waits for events on the epoll instance referred to by the file descriptor
171/// `epdf`.
172///
173/// `timeout` represents the number of milliseconds this function call will
174/// block.
175///
176/// Will block until either:
177/// - a file descriptor delivers an event
178/// - the call is interrupted by a signal handler
179/// - the `timeout` expires
180///
181/// A `timeout` of `-1` will block indefinitely. A `timeout` of `0` will return
182/// immediately, even if no events are available.
183///
184/// Upon success, returns the number of file descriptors ready for the
185/// requested I/O operation, or `0` if no file descriptor became ready during
186/// the requested `timeout`. Upon failure, returns `-1` and sets errno to
187/// indicate the error.
188#[unsafe(no_mangle)]
189pub unsafe extern "C" fn epoll_wait(
190 epfd: c_int,
191 events: *mut epoll_event,
192 maxevents: c_int,
193 timeout: c_int,
194) -> c_int {
195 unsafe { epoll_pwait(epfd, events, maxevents, timeout, ptr::null()) }
196}
197
198/// Non-POSIX, see <https://man7.org/linux/man-pages/man2/epoll_wait.2.html>.
199///
200/// Allows an application to safely wait until either a file descriptor becomes
201/// ready or a signal is caught.
202///
203/// If `sigmask` is NULL, calling this function is equivalent to
204/// `epoll_wait()`.
205///
206/// Upon success, returns the number of file descriptors ready for the
207/// requested I/O operation, or `0` if no file descriptor became ready during
208/// the requested `timeout`. Upon failure, returns `-1` and sets errno to
209/// indicate the error.
210#[unsafe(no_mangle)]
211pub unsafe extern "C" fn epoll_pwait(
212 epfd: c_int,
213 events: *mut epoll_event,
214 maxevents: c_int,
215 timeout: c_int,
216 sigmask: *const sigset_t,
217) -> c_int {
218 trace_expr!(
219 unsafe { Sys::epoll_pwait(epfd, events, maxevents, timeout, sigmask) }
220 .map(|e| e as c_int)
221 .or_minus_one_errno(),
222 "epoll_pwait({}, {:p}, {}, {}, {:p})",
223 epfd,
224 events,
225 maxevents,
226 timeout,
227 sigmask
228 )
229}